13 #if defined(__APPLE__)
14 #include <mach/mach.h>
15 #include <mach/mach_time.h>
19 #elif defined(unix) || defined(__unix) || defined(__unix__)
21 #elif defined(_WIN32) || defined(_WIN64)
30 #if defined(__APPLE__)
32 uint32_t CeilLog2(uint32_t x)
49 mach_timebase_info_data_t BestFrac(
double a,
double b)
51 if (floor(a) < floor(b))
53 mach_timebase_info_data_t rv = { (uint32_t)ceil(a), 1 };
58 mach_timebase_info_data_t next = BestFrac(1 / (b - m), 1 / (a - m));
59 mach_timebase_info_data_t rv = { (int)m * next.numer + next.denom, next.numer };
65 uint64_t GetExpressibleSpan(uint32_t numer, uint32_t denom)
67 uint64_t maxDiffWithoutOverflow = ((uint64_t)1 << (64 - CeilLog2(numer))) - 1;
68 return maxDiffWithoutOverflow * numer / denom;
74 uint64_t PrepareTimebaseInfo(mach_timebase_info_data_t& tb)
79 kern_return_t mtiStatus = mach_timebase_info(&tb);
80 if (mtiStatus != KERN_SUCCESS)
83 double frac = (double)tb.numer / tb.denom;
84 uint64_t spanTarget = 315360000000000000llu;
85 if (GetExpressibleSpan(tb.numer, tb.denom) >= spanTarget)
88 for (
double errorTarget = 1 / 1024.0; errorTarget > 0.000001;)
90 mach_timebase_info_data_t newFrac = BestFrac((1 - errorTarget) * frac, (1 + errorTarget) * frac);
91 if (GetExpressibleSpan(newFrac.numer, newFrac.denom) < spanTarget)
94 errorTarget = fabs((
double)tb.numer / tb.denom - frac) / frac / 8;
107 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
108 struct timespec timestamp;
109 if (clock_gettime(CLOCK_REALTIME, ×tamp) != 0)
111 return (timestamp.tv_sec * 1000000000) + timestamp.tv_nsec;
112 #elif defined(_WIN32) || defined(_WIN64)
114 GetSystemTimePreciseAsFileTime(&ft);
116 ULARGE_INTEGER result;
117 result.LowPart = ft.dwLowDateTime;
118 result.HighPart = ft.dwHighDateTime;
119 return (result.QuadPart - 116444736000000000ull) * 100;
125 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
126 uint64_t timestamp =
utc();
130 time_t
seconds = timestamp / (1000000000);
133 return timestamp + (
local.tm_gmtoff * 1000000000);
134 #elif defined(_WIN32) || defined(_WIN64)
136 #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
137 GetSystemTimePreciseAsFileTime(&ft);
139 GetSystemTimeAsFileTime(&ft);
143 if (!FileTimeToLocalFileTime(&ft, &ft_local))
146 ULARGE_INTEGER result;
147 result.LowPart = ft_local.dwLowDateTime;
148 result.HighPart = ft_local.dwHighDateTime;
149 return (result.QuadPart - 116444736000000000ull) * 100;
155 #if defined(__APPLE__)
156 static mach_timebase_info_data_t info;
157 static uint64_t bias = Internals::PrepareTimebaseInfo(info);
158 return ((mach_absolute_time() - bias) * info.numer) / info.denom;
159 #elif defined(unix) || defined(__unix) || defined(__unix__)
160 struct timespec timestamp = { 0 };
161 if (clock_gettime(CLOCK_MONOTONIC, ×tamp) != 0)
163 return (timestamp.tv_sec * 1000000000) + timestamp.tv_nsec;
164 #elif defined(_WIN32) || defined(_WIN64)
165 static uint64_t offset = 0;
166 static LARGE_INTEGER first = { 0 };
167 static LARGE_INTEGER frequency = { 0 };
168 static bool initialized =
false;
169 static bool qpc =
true;
175 GetSystemTimePreciseAsFileTime(×tamp);
177 ULARGE_INTEGER result;
178 result.LowPart = timestamp.dwLowDateTime;
179 result.HighPart = timestamp.dwHighDateTime;
182 result.QuadPart -= 116444736000000000ll;
183 offset = result.QuadPart * 100;
186 qpc = QueryPerformanceFrequency(&frequency) && QueryPerformanceCounter(&first);
193 LARGE_INTEGER timestamp = { 0 };
194 QueryPerformanceCounter(×tamp);
195 timestamp.QuadPart -= first.QuadPart;
196 return offset +
Math::MulDiv64(timestamp.QuadPart, 1000000000, frequency.QuadPart);
201 #error Unsupported platform
207 #if defined(__APPLE__)
217 return mach_absolute_time();
218 #elif defined(_MSC_VER)
220 #elif defined(__i386__)
222 __asm__
volatile(
"rdtsc" :
"=A"(ret));
224 #elif defined(__x86_64__) || defined(__amd64__)
226 __asm__
volatile(
"rdtsc" :
"=a"(low),
"=d"(high));
227 return (high << 32) | low;
228 #elif defined(__powerpc__) || defined(__ppc__)
230 int64_t tbl, tbu0, tbu1;
231 asm(
"mftbu %0" :
"=r"(tbu0));
232 asm(
"mftb %0" :
"=r"(tbl));
233 asm(
"mftbu %0" :
"=r"(tbu1));
234 tbl &= -
static_cast<int64
>(tbu0 == tbu1);
237 return (tbu1 << 32) | tbl;
238 #elif defined(__sparc__)
240 asm(
".byte 0x83, 0x41, 0x00, 0x00");
241 asm(
"mov %%g1, %0" :
"=r"(tick));
243 #elif defined(__ia64__)
245 asm(
"mov %0 = ar.itc" :
"=r"(itc));
247 #elif defined(COMPILER_MSVC) && defined(_M_IX86)
253 #elif defined(__aarch64__)
258 int64_t virtual_timer_value;
259 asm volatile(
"mrs %0, cntvct_el0" :
"=r"(virtual_timer_value));
260 return virtual_timer_value;
261 #elif defined(__ARM_ARCH)
264 #if (__ARM_ARCH >= 6)
269 asm volatile(
"mrc p15, 0, %0, c9, c14, 0" :
"=r"(pmuseren));
273 asm volatile(
"mrc p15, 0, %0, c9, c12, 1" :
"=r"(pmcntenset));
274 if (pmcntenset & 0x80000000ul)
277 asm volatile(
"mrc p15, 0, %0, c9, c13, 0" :
"=r"(pmccntr));
279 return static_cast<int64_t
>(pmccntr) * 64;
285 gettimeofday(&tv,
nullptr);
286 return static_cast<int64_t
>(tv.tv_sec) * 1000000 + tv.tv_usec;
287 #elif defined(__mips__)
291 gettimeofday(&tv,
nullptr);
292 return static_cast<int64_t
>(tv.tv_sec) * 1000000 + tv.tv_usec;
294 #error Unsupported platform
static uint64_t MulDiv64(uint64_t operant, uint64_t multiplier, uint64_t divider)
Calculate (operant * multiplier / divider) with 64-bit unsigned integer values.
static uint64_t local()
Get the local timestamp.
static uint64_t utc()
Get the UTC timestamp.
static uint64_t nano()
Get the high resolution timestamp.
uint64_t seconds() const noexcept
Get total seconds of the current timestamp.
static uint64_t rdts()
Get the current value of RDTS (Read Time Stamp Counter)
#define throwex
Throw extended exception macro.
C++ Common project definitions.