1227825Stheraven//===------------------------- chrono.cpp ---------------------------------===// 2227825Stheraven// 3227825Stheraven// The LLVM Compiler Infrastructure 4227825Stheraven// 5227825Stheraven// This file is dual licensed under the MIT and the University of Illinois Open 6227825Stheraven// Source Licenses. See LICENSE.TXT for details. 7227825Stheraven// 8227825Stheraven//===----------------------------------------------------------------------===// 9227825Stheraven 10227825Stheraven#include "chrono" 11227825Stheraven#include <sys/time.h> //for gettimeofday and timeval 12249998Sdim#ifdef __APPLE__ 13227825Stheraven#include <mach/mach_time.h> // mach_absolute_time, mach_timebase_info_data_t 14227825Stheraven#else /* !__APPLE__ */ 15227825Stheraven#include <cerrno> // errno 16227825Stheraven#include <system_error> // __throw_system_error 17227825Stheraven#include <time.h> // clock_gettime, CLOCK_MONOTONIC 18227825Stheraven#endif // __APPLE__ 19227825Stheraven 20227825Stheraven_LIBCPP_BEGIN_NAMESPACE_STD 21227825Stheraven 22227825Stheravennamespace chrono 23227825Stheraven{ 24227825Stheraven 25227825Stheraven// system_clock 26227825Stheraven 27246487Stheravenconst bool system_clock::is_steady; 28246487Stheraven 29227825Stheravensystem_clock::time_point 30227825Stheravensystem_clock::now() _NOEXCEPT 31227825Stheraven{ 32227825Stheraven timeval tv; 33227825Stheraven gettimeofday(&tv, 0); 34227825Stheraven return time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec)); 35227825Stheraven} 36227825Stheraven 37227825Stheraventime_t 38227825Stheravensystem_clock::to_time_t(const time_point& t) _NOEXCEPT 39227825Stheraven{ 40227825Stheraven return time_t(duration_cast<seconds>(t.time_since_epoch()).count()); 41227825Stheraven} 42227825Stheraven 43227825Stheravensystem_clock::time_point 44227825Stheravensystem_clock::from_time_t(time_t t) _NOEXCEPT 45227825Stheraven{ 46227825Stheraven return system_clock::time_point(seconds(t)); 47227825Stheraven} 48227825Stheraven 49278724Sdim#ifndef _LIBCPP_HAS_NO_MONOTONIC_CLOCK 50227825Stheraven// steady_clock 51227825Stheraven 52246487Stheravenconst bool steady_clock::is_steady; 53246487Stheraven 54249998Sdim#ifdef __APPLE__ 55227825Stheraven// mach_absolute_time() * MachInfo.numer / MachInfo.denom is the number of 56227825Stheraven// nanoseconds since the computer booted up. MachInfo.numer and MachInfo.denom 57227825Stheraven// are run time constants supplied by the OS. This clock has no relationship 58227825Stheraven// to the Gregorian calendar. It's main use is as a high resolution timer. 59227825Stheraven 60227825Stheraven// MachInfo.numer / MachInfo.denom is often 1 on the latest equipment. Specialize 61227825Stheraven// for that case as an optimization. 62227825Stheraven 63227825Stheraven#pragma GCC visibility push(hidden) 64227825Stheraven 65227825Stheravenstatic 66227825Stheravensteady_clock::rep 67227825Stheravensteady_simplified() 68227825Stheraven{ 69232950Stheraven return static_cast<steady_clock::rep>(mach_absolute_time()); 70227825Stheraven} 71227825Stheraven 72227825Stheravenstatic 73227825Stheravendouble 74227825Stheravencompute_steady_factor() 75227825Stheraven{ 76227825Stheraven mach_timebase_info_data_t MachInfo; 77227825Stheraven mach_timebase_info(&MachInfo); 78227825Stheraven return static_cast<double>(MachInfo.numer) / MachInfo.denom; 79227825Stheraven} 80227825Stheraven 81227825Stheravenstatic 82227825Stheravensteady_clock::rep 83227825Stheravensteady_full() 84227825Stheraven{ 85227825Stheraven static const double factor = compute_steady_factor(); 86227825Stheraven return static_cast<steady_clock::rep>(mach_absolute_time() * factor); 87227825Stheraven} 88227825Stheraven 89227825Stheraventypedef steady_clock::rep (*FP)(); 90227825Stheraven 91227825Stheravenstatic 92227825StheravenFP 93227825Stheraveninit_steady_clock() 94227825Stheraven{ 95227825Stheraven mach_timebase_info_data_t MachInfo; 96227825Stheraven mach_timebase_info(&MachInfo); 97227825Stheraven if (MachInfo.numer == MachInfo.denom) 98227825Stheraven return &steady_simplified; 99227825Stheraven return &steady_full; 100227825Stheraven} 101227825Stheraven 102227825Stheraven#pragma GCC visibility pop 103227825Stheraven 104227825Stheravensteady_clock::time_point 105227825Stheravensteady_clock::now() _NOEXCEPT 106227825Stheraven{ 107227825Stheraven static FP fp = init_steady_clock(); 108227825Stheraven return time_point(duration(fp())); 109227825Stheraven} 110227825Stheraven 111227825Stheraven#else // __APPLE__ 112278724Sdim// FIXME: if _LIBCPP_HAS_NO_MONOTONIC_CLOCK, then clock_gettime isn't going to 113278724Sdim// work. It may be possible to fall back on something else, depending on the system. 114227825Stheraven 115227825Stheraven// Warning: If this is not truly steady, then it is non-conforming. It is 116227825Stheraven// better for it to not exist and have the rest of libc++ use system_clock 117227825Stheraven// instead. 118227825Stheraven 119227825Stheravensteady_clock::time_point 120227825Stheravensteady_clock::now() _NOEXCEPT 121227825Stheraven{ 122227825Stheraven struct timespec tp; 123227825Stheraven if (0 != clock_gettime(CLOCK_MONOTONIC, &tp)) 124227825Stheraven __throw_system_error(errno, "clock_gettime(CLOCK_MONOTONIC) failed"); 125227825Stheraven return time_point(seconds(tp.tv_sec) + nanoseconds(tp.tv_nsec)); 126227825Stheraven} 127227825Stheraven#endif // __APPLE__ 128227825Stheraven 129278724Sdim#endif // !_LIBCPP_HAS_NO_MONOTONIC_CLOCK 130278724Sdim 131227825Stheraven} 132227825Stheraven 133227825Stheraven_LIBCPP_END_NAMESPACE_STD 134