1227825Stheraven//===------------------------- chrono.cpp ---------------------------------===// 2227825Stheraven// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6227825Stheraven// 7227825Stheraven//===----------------------------------------------------------------------===// 8227825Stheraven 9227825Stheraven#include "chrono" 10288943Sdim#include "cerrno" // errno 11288943Sdim#include "system_error" // __throw_system_error 12288943Sdim#include <time.h> // clock_gettime, CLOCK_MONOTONIC and CLOCK_REALTIME 13341825Sdim#include "include/apple_availability.h" 14288943Sdim 15341825Sdim#if !defined(__APPLE__) 16341825Sdim#define _LIBCPP_USE_CLOCK_GETTIME 17314564Sdim#endif // __APPLE__ 18288943Sdim 19314564Sdim#if defined(_LIBCPP_WIN32API) 20314564Sdim#define WIN32_LEAN_AND_MEAN 21314564Sdim#define VC_EXTRA_LEAN 22321369Sdim#include <windows.h> 23314564Sdim#if _WIN32_WINNT >= _WIN32_WINNT_WIN8 24314564Sdim#include <winapifamily.h> 25314564Sdim#endif 26314564Sdim#else 27341825Sdim#if !defined(CLOCK_REALTIME) || !defined(_LIBCPP_USE_CLOCK_GETTIME) 28314564Sdim#include <sys/time.h> // for gettimeofday and timeval 29314564Sdim#endif // !defined(CLOCK_REALTIME) 30314564Sdim#endif // defined(_LIBCPP_WIN32API) 31314564Sdim 32314564Sdim#if !defined(_LIBCPP_HAS_NO_MONOTONIC_CLOCK) 33288943Sdim#if __APPLE__ 34227825Stheraven#include <mach/mach_time.h> // mach_absolute_time, mach_timebase_info_data_t 35314564Sdim#elif !defined(_LIBCPP_WIN32API) && !defined(CLOCK_MONOTONIC) 36288943Sdim#error "Monotonic clock not implemented" 37288943Sdim#endif 38288943Sdim#endif 39227825Stheraven 40360784Sdim#if defined(__ELF__) && defined(_LIBCPP_LINK_RT_LIB) 41353358Sdim#pragma comment(lib, "rt") 42353358Sdim#endif 43353358Sdim 44227825Stheraven_LIBCPP_BEGIN_NAMESPACE_STD 45227825Stheraven 46227825Stheravennamespace chrono 47227825Stheraven{ 48227825Stheraven 49227825Stheraven// system_clock 50227825Stheraven 51246468Stheravenconst bool system_clock::is_steady; 52246468Stheraven 53227825Stheravensystem_clock::time_point 54227825Stheravensystem_clock::now() _NOEXCEPT 55227825Stheraven{ 56314564Sdim#if defined(_LIBCPP_WIN32API) 57314564Sdim // FILETIME is in 100ns units 58314564Sdim using filetime_duration = 59314564Sdim _VSTD::chrono::duration<__int64, 60314564Sdim _VSTD::ratio_multiply<_VSTD::ratio<100, 1>, 61314564Sdim nanoseconds::period>>; 62314564Sdim 63314564Sdim // The Windows epoch is Jan 1 1601, the Unix epoch Jan 1 1970. 64314564Sdim static _LIBCPP_CONSTEXPR const seconds nt_to_unix_epoch{11644473600}; 65314564Sdim 66314564Sdim FILETIME ft; 67314564Sdim#if _WIN32_WINNT >= _WIN32_WINNT_WIN8 68314564Sdim#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) 69314564Sdim GetSystemTimePreciseAsFileTime(&ft); 70314564Sdim#else 71314564Sdim GetSystemTimeAsFileTime(&ft); 72314564Sdim#endif 73314564Sdim#else 74314564Sdim GetSystemTimeAsFileTime(&ft); 75314564Sdim#endif 76314564Sdim 77314564Sdim filetime_duration d{(static_cast<__int64>(ft.dwHighDateTime) << 32) | 78314564Sdim static_cast<__int64>(ft.dwLowDateTime)}; 79314564Sdim return time_point(duration_cast<duration>(d - nt_to_unix_epoch)); 80314564Sdim#else 81341825Sdim#if defined(_LIBCPP_USE_CLOCK_GETTIME) && defined(CLOCK_REALTIME) 82341825Sdim struct timespec tp; 83341825Sdim if (0 != clock_gettime(CLOCK_REALTIME, &tp)) 84341825Sdim __throw_system_error(errno, "clock_gettime(CLOCK_REALTIME) failed"); 85341825Sdim return time_point(seconds(tp.tv_sec) + microseconds(tp.tv_nsec / 1000)); 86314564Sdim#else 87227825Stheraven timeval tv; 88227825Stheraven gettimeofday(&tv, 0); 89227825Stheraven return time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec)); 90341825Sdim#endif // _LIBCPP_USE_CLOCK_GETTIME && CLOCK_REALTIME 91314564Sdim#endif 92227825Stheraven} 93227825Stheraven 94227825Stheraventime_t 95227825Stheravensystem_clock::to_time_t(const time_point& t) _NOEXCEPT 96227825Stheraven{ 97227825Stheraven return time_t(duration_cast<seconds>(t.time_since_epoch()).count()); 98227825Stheraven} 99227825Stheraven 100227825Stheravensystem_clock::time_point 101227825Stheravensystem_clock::from_time_t(time_t t) _NOEXCEPT 102227825Stheraven{ 103227825Stheraven return system_clock::time_point(seconds(t)); 104227825Stheraven} 105227825Stheraven 106276792Sdim#ifndef _LIBCPP_HAS_NO_MONOTONIC_CLOCK 107227825Stheraven// steady_clock 108288943Sdim// 109288943Sdim// Warning: If this is not truly steady, then it is non-conforming. It is 110288943Sdim// better for it to not exist and have the rest of libc++ use system_clock 111288943Sdim// instead. 112227825Stheraven 113246468Stheravenconst bool steady_clock::is_steady; 114246468Stheraven 115314564Sdim#if defined(__APPLE__) 116288943Sdim 117314564Sdim// Darwin libc versions >= 1133 provide ns precision via CLOCK_UPTIME_RAW 118341825Sdim#if defined(_LIBCPP_USE_CLOCK_GETTIME) && defined(CLOCK_UPTIME_RAW) 119288943Sdimsteady_clock::time_point 120288943Sdimsteady_clock::now() _NOEXCEPT 121288943Sdim{ 122288943Sdim struct timespec tp; 123314564Sdim if (0 != clock_gettime(CLOCK_UPTIME_RAW, &tp)) 124314564Sdim __throw_system_error(errno, "clock_gettime(CLOCK_UPTIME_RAW) failed"); 125288943Sdim return time_point(seconds(tp.tv_sec) + nanoseconds(tp.tv_nsec)); 126288943Sdim} 127288943Sdim 128314564Sdim#else 129227825Stheraven// mach_absolute_time() * MachInfo.numer / MachInfo.denom is the number of 130227825Stheraven// nanoseconds since the computer booted up. MachInfo.numer and MachInfo.denom 131227825Stheraven// are run time constants supplied by the OS. This clock has no relationship 132227825Stheraven// to the Gregorian calendar. It's main use is as a high resolution timer. 133227825Stheraven 134227825Stheraven// MachInfo.numer / MachInfo.denom is often 1 on the latest equipment. Specialize 135227825Stheraven// for that case as an optimization. 136227825Stheraven 137227825Stheravenstatic 138227825Stheravensteady_clock::rep 139227825Stheravensteady_simplified() 140227825Stheraven{ 141232924Stheraven return static_cast<steady_clock::rep>(mach_absolute_time()); 142227825Stheraven} 143227825Stheraven 144227825Stheravenstatic 145227825Stheravendouble 146227825Stheravencompute_steady_factor() 147227825Stheraven{ 148227825Stheraven mach_timebase_info_data_t MachInfo; 149227825Stheraven mach_timebase_info(&MachInfo); 150227825Stheraven return static_cast<double>(MachInfo.numer) / MachInfo.denom; 151227825Stheraven} 152227825Stheraven 153227825Stheravenstatic 154227825Stheravensteady_clock::rep 155227825Stheravensteady_full() 156227825Stheraven{ 157227825Stheraven static const double factor = compute_steady_factor(); 158227825Stheraven return static_cast<steady_clock::rep>(mach_absolute_time() * factor); 159227825Stheraven} 160227825Stheraven 161227825Stheraventypedef steady_clock::rep (*FP)(); 162227825Stheraven 163227825Stheravenstatic 164227825StheravenFP 165227825Stheraveninit_steady_clock() 166227825Stheraven{ 167227825Stheraven mach_timebase_info_data_t MachInfo; 168227825Stheraven mach_timebase_info(&MachInfo); 169227825Stheraven if (MachInfo.numer == MachInfo.denom) 170227825Stheraven return &steady_simplified; 171227825Stheraven return &steady_full; 172227825Stheraven} 173227825Stheraven 174227825Stheravensteady_clock::time_point 175227825Stheravensteady_clock::now() _NOEXCEPT 176227825Stheraven{ 177227825Stheraven static FP fp = init_steady_clock(); 178227825Stheraven return time_point(duration(fp())); 179227825Stheraven} 180341825Sdim#endif // defined(_LIBCPP_USE_CLOCK_GETTIME) && defined(CLOCK_UPTIME_RAW) 181227825Stheraven 182314564Sdim#elif defined(_LIBCPP_WIN32API) 183314564Sdim 184353358Sdim// https://msdn.microsoft.com/en-us/library/windows/desktop/ms644905(v=vs.85).aspx says: 185353358Sdim// If the function fails, the return value is zero. <snip> 186360784Sdim// On systems that run Windows XP or later, the function will always succeed 187353358Sdim// and will thus never return zero. 188353358Sdim 189353358Sdimstatic LARGE_INTEGER 190353358Sdim__QueryPerformanceFrequency() 191353358Sdim{ 192353358Sdim LARGE_INTEGER val; 193353358Sdim (void) QueryPerformanceFrequency(&val); 194353358Sdim return val; 195353358Sdim} 196353358Sdim 197314564Sdimsteady_clock::time_point 198314564Sdimsteady_clock::now() _NOEXCEPT 199314564Sdim{ 200353358Sdim static const LARGE_INTEGER freq = __QueryPerformanceFrequency(); 201314564Sdim 202314564Sdim LARGE_INTEGER counter; 203353358Sdim (void) QueryPerformanceCounter(&counter); 204314564Sdim return time_point(duration(counter.QuadPart * nano::den / freq.QuadPart)); 205314564Sdim} 206314564Sdim 207314564Sdim#elif defined(CLOCK_MONOTONIC) 208314564Sdim 209314564Sdim// On Apple platforms only CLOCK_UPTIME_RAW or mach_absolute_time are able to 210314564Sdim// time functions in the nanosecond range. Thus, they are the only acceptable 211314564Sdim// implementations of steady_clock. 212314564Sdim#ifdef __APPLE__ 213314564Sdim#error "Never use CLOCK_MONOTONIC for steady_clock::now on Apple platforms" 214314564Sdim#endif 215314564Sdim 216314564Sdimsteady_clock::time_point 217314564Sdimsteady_clock::now() _NOEXCEPT 218314564Sdim{ 219314564Sdim struct timespec tp; 220314564Sdim if (0 != clock_gettime(CLOCK_MONOTONIC, &tp)) 221314564Sdim __throw_system_error(errno, "clock_gettime(CLOCK_MONOTONIC) failed"); 222314564Sdim return time_point(seconds(tp.tv_sec) + nanoseconds(tp.tv_nsec)); 223314564Sdim} 224314564Sdim 225288943Sdim#else 226288943Sdim#error "Monotonic clock not implemented" 227288943Sdim#endif 228227825Stheraven 229276792Sdim#endif // !_LIBCPP_HAS_NO_MONOTONIC_CLOCK 230276792Sdim 231227825Stheraven} 232227825Stheraven 233227825Stheraven_LIBCPP_END_NAMESPACE_STD 234