diff options
author | 2021-01-02 20:29:13 +0000 | |
---|---|---|
committer | 2021-01-02 20:29:13 +0000 | |
commit | 46035553bfdd96e63c94e32da0210227ec2e3cf1 (patch) | |
tree | b191f708fb9a2995ba745b2f31cdeeaee4872b7f /gnu/llvm/libcxx/src/chrono.cpp | |
parent | Move Makefiles for libc++ and libc++abi to gnu/lib in preparation for an (diff) | |
download | wireguard-openbsd-46035553bfdd96e63c94e32da0210227ec2e3cf1.tar.xz wireguard-openbsd-46035553bfdd96e63c94e32da0210227ec2e3cf1.zip |
Import libc++ 10.0.1 release.
Diffstat (limited to 'gnu/llvm/libcxx/src/chrono.cpp')
-rw-r--r-- | gnu/llvm/libcxx/src/chrono.cpp | 233 |
1 files changed, 233 insertions, 0 deletions
diff --git a/gnu/llvm/libcxx/src/chrono.cpp b/gnu/llvm/libcxx/src/chrono.cpp new file mode 100644 index 00000000000..9d448b6a985 --- /dev/null +++ b/gnu/llvm/libcxx/src/chrono.cpp @@ -0,0 +1,233 @@ +//===------------------------- chrono.cpp ---------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "chrono" +#include "cerrno" // errno +#include "system_error" // __throw_system_error +#include <time.h> // clock_gettime, CLOCK_MONOTONIC and CLOCK_REALTIME +#include "include/apple_availability.h" + +#if !defined(__APPLE__) +#define _LIBCPP_USE_CLOCK_GETTIME +#endif // __APPLE__ + +#if defined(_LIBCPP_WIN32API) +#define WIN32_LEAN_AND_MEAN +#define VC_EXTRA_LEAN +#include <windows.h> +#if _WIN32_WINNT >= _WIN32_WINNT_WIN8 +#include <winapifamily.h> +#endif +#else +#if !defined(CLOCK_REALTIME) || !defined(_LIBCPP_USE_CLOCK_GETTIME) +#include <sys/time.h> // for gettimeofday and timeval +#endif // !defined(CLOCK_REALTIME) +#endif // defined(_LIBCPP_WIN32API) + +#if !defined(_LIBCPP_HAS_NO_MONOTONIC_CLOCK) +#if __APPLE__ +#include <mach/mach_time.h> // mach_absolute_time, mach_timebase_info_data_t +#elif !defined(_LIBCPP_WIN32API) && !defined(CLOCK_MONOTONIC) +#error "Monotonic clock not implemented" +#endif +#endif + +#if defined(__ELF__) && defined(_LIBCPP_LINK_RT_LIB) +#pragma comment(lib, "rt") +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace chrono +{ + +// system_clock + +const bool system_clock::is_steady; + +system_clock::time_point +system_clock::now() _NOEXCEPT +{ +#if defined(_LIBCPP_WIN32API) + // FILETIME is in 100ns units + using filetime_duration = + _VSTD::chrono::duration<__int64, + _VSTD::ratio_multiply<_VSTD::ratio<100, 1>, + nanoseconds::period>>; + + // The Windows epoch is Jan 1 1601, the Unix epoch Jan 1 1970. + static _LIBCPP_CONSTEXPR const seconds nt_to_unix_epoch{11644473600}; + + FILETIME ft; +#if _WIN32_WINNT >= _WIN32_WINNT_WIN8 +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + GetSystemTimePreciseAsFileTime(&ft); +#else + GetSystemTimeAsFileTime(&ft); +#endif +#else + GetSystemTimeAsFileTime(&ft); +#endif + + filetime_duration d{(static_cast<__int64>(ft.dwHighDateTime) << 32) | + static_cast<__int64>(ft.dwLowDateTime)}; + return time_point(duration_cast<duration>(d - nt_to_unix_epoch)); +#else +#if defined(_LIBCPP_USE_CLOCK_GETTIME) && defined(CLOCK_REALTIME) + struct timespec tp; + if (0 != clock_gettime(CLOCK_REALTIME, &tp)) + __throw_system_error(errno, "clock_gettime(CLOCK_REALTIME) failed"); + return time_point(seconds(tp.tv_sec) + microseconds(tp.tv_nsec / 1000)); +#else + timeval tv; + gettimeofday(&tv, 0); + return time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec)); +#endif // _LIBCPP_USE_CLOCK_GETTIME && CLOCK_REALTIME +#endif +} + +time_t +system_clock::to_time_t(const time_point& t) _NOEXCEPT +{ + return time_t(duration_cast<seconds>(t.time_since_epoch()).count()); +} + +system_clock::time_point +system_clock::from_time_t(time_t t) _NOEXCEPT +{ + return system_clock::time_point(seconds(t)); +} + +#ifndef _LIBCPP_HAS_NO_MONOTONIC_CLOCK +// steady_clock +// +// Warning: If this is not truly steady, then it is non-conforming. It is +// better for it to not exist and have the rest of libc++ use system_clock +// instead. + +const bool steady_clock::is_steady; + +#if defined(__APPLE__) + +// Darwin libc versions >= 1133 provide ns precision via CLOCK_UPTIME_RAW +#if defined(_LIBCPP_USE_CLOCK_GETTIME) && defined(CLOCK_UPTIME_RAW) +steady_clock::time_point +steady_clock::now() _NOEXCEPT +{ + struct timespec tp; + if (0 != clock_gettime(CLOCK_UPTIME_RAW, &tp)) + __throw_system_error(errno, "clock_gettime(CLOCK_UPTIME_RAW) failed"); + return time_point(seconds(tp.tv_sec) + nanoseconds(tp.tv_nsec)); +} + +#else +// mach_absolute_time() * MachInfo.numer / MachInfo.denom is the number of +// nanoseconds since the computer booted up. MachInfo.numer and MachInfo.denom +// are run time constants supplied by the OS. This clock has no relationship +// to the Gregorian calendar. It's main use is as a high resolution timer. + +// MachInfo.numer / MachInfo.denom is often 1 on the latest equipment. Specialize +// for that case as an optimization. + +static +steady_clock::rep +steady_simplified() +{ + return static_cast<steady_clock::rep>(mach_absolute_time()); +} + +static +double +compute_steady_factor() +{ + mach_timebase_info_data_t MachInfo; + mach_timebase_info(&MachInfo); + return static_cast<double>(MachInfo.numer) / MachInfo.denom; +} + +static +steady_clock::rep +steady_full() +{ + static const double factor = compute_steady_factor(); + return static_cast<steady_clock::rep>(mach_absolute_time() * factor); +} + +typedef steady_clock::rep (*FP)(); + +static +FP +init_steady_clock() +{ + mach_timebase_info_data_t MachInfo; + mach_timebase_info(&MachInfo); + if (MachInfo.numer == MachInfo.denom) + return &steady_simplified; + return &steady_full; +} + +steady_clock::time_point +steady_clock::now() _NOEXCEPT +{ + static FP fp = init_steady_clock(); + return time_point(duration(fp())); +} +#endif // defined(_LIBCPP_USE_CLOCK_GETTIME) && defined(CLOCK_UPTIME_RAW) + +#elif defined(_LIBCPP_WIN32API) + +// https://msdn.microsoft.com/en-us/library/windows/desktop/ms644905(v=vs.85).aspx says: +// If the function fails, the return value is zero. <snip> +// On systems that run Windows XP or later, the function will always succeed +// and will thus never return zero. + +static LARGE_INTEGER +__QueryPerformanceFrequency() +{ + LARGE_INTEGER val; + (void) QueryPerformanceFrequency(&val); + return val; +} + +steady_clock::time_point +steady_clock::now() _NOEXCEPT +{ + static const LARGE_INTEGER freq = __QueryPerformanceFrequency(); + + LARGE_INTEGER counter; + (void) QueryPerformanceCounter(&counter); + return time_point(duration(counter.QuadPart * nano::den / freq.QuadPart)); +} + +#elif defined(CLOCK_MONOTONIC) + +// On Apple platforms only CLOCK_UPTIME_RAW or mach_absolute_time are able to +// time functions in the nanosecond range. Thus, they are the only acceptable +// implementations of steady_clock. +#ifdef __APPLE__ +#error "Never use CLOCK_MONOTONIC for steady_clock::now on Apple platforms" +#endif + +steady_clock::time_point +steady_clock::now() _NOEXCEPT +{ + struct timespec tp; + if (0 != clock_gettime(CLOCK_MONOTONIC, &tp)) + __throw_system_error(errno, "clock_gettime(CLOCK_MONOTONIC) failed"); + return time_point(seconds(tp.tv_sec) + nanoseconds(tp.tv_nsec)); +} + +#else +#error "Monotonic clock not implemented" +#endif + +#endif // !_LIBCPP_HAS_NO_MONOTONIC_CLOCK + +} + +_LIBCPP_END_NAMESPACE_STD |