Created
December 5, 2023 12:12
-
-
Save marakew/af8a086d8ec9420ef9a64d12ec7e0353 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#if defined(_WIN32) | |
//jrtplib | |
inline unsigned __int64 CalculateFileTime(unsigned __int64 performancecount, unsigned __int64 performancefrequency) | |
{ | |
unsigned __int64 f = performancefrequency; | |
unsigned __int64 a = performancecount; | |
unsigned __int64 b = a/f; | |
unsigned __int64 c = a%f; // a = b*f+c => (a*10'000'000)/f = b*10'000'000+(c*10'000'000)/f | |
return b*10'000'000ui64+(c*10'000'000ui64)/f; | |
} | |
//https://github.com/Perl/perl5/blob/blead/dist/Time-HiRes/HiRes.xs | |
union FT_t | |
{ | |
unsigned __int64 ft_i64; | |
FILETIME ft_val; | |
}; | |
struct my_ctx | |
{ | |
unsigned long run_count; | |
unsigned __int64 base_ticks; | |
unsigned __int64 tick_frequency; | |
FT_t base_systime_as_filetime; | |
unsigned __int64 reset_time; | |
}; | |
/* Number of 100 nanosecond units from 1/1/1601 to 1/1/1970 */ | |
#define EPOCH_BIAS (116444736000000000LL) | |
/* If the performance counter delta drifts more than 0.5 seconds from the | |
* system time then we recalibrate to the system time. This means we may | |
* move *backwards* in time! */ | |
#define MAX_PERF_COUNTER_SKEW (5000000LL) /* 0.5 seconds */ | |
/* Reset reading from the performance counter every five minutes. | |
* Many PC clocks just seem to be so bad. */ | |
#define MAX_PERF_COUNTER_TICKS (300000000LL) /* 300 seconds */ | |
/* | |
* Windows 8 introduced GetSystemTimePreciseAsFileTime(), but currently we have | |
* to support older systems, so for now we provide our own implementation. | |
* In the future we will switch to the real deal. | |
*/ | |
static void _GetSystemTimePreciseAsFileTime(FILETIME *out) | |
{ | |
static my_ctx MY_CTX; | |
FT_t ft; | |
if (MY_CTX.run_count++ == 0 || | |
MY_CXT.base_systime_as_filetime.ft_i64 > MY_CXT.reset_time) | |
{ | |
::QueryPerformanceFrequency((LARGE_INTEGER*)&MY_CTX.tick_frequency); | |
::QueryPerformanceCounter((LARGE_INTEGER*)&MY_CTX.base_ticks); | |
::GetSystemTimeAsFileTime(&MY_CTX.base_systime_as_filetime.ft_val); | |
ft.ft_i64 = MY_CTX.base_systime_as_filetime.ft_i64; | |
MY_CXT.reset_time = ft.ft_i64 + MAX_PERF_COUNTER_TICKS; | |
} else | |
{ | |
__int64 diff; | |
unsigned __int64 ticks; | |
::QueryPerformanceCounter((LARGE_INTEGER*)&ticks); | |
ticks -= MY_CTX.base_ticks; | |
//ft.ft_i64 = MY_CTX.base_systime_as_filetime.ft_i64 + CalculateFileTime(ticks, MY_CTX.tick_frequency); | |
ft.ft_i64 = MY_CTX.base_systime_as_filetime.ft_i64 | |
+ (ticks / MY_CTX.tick_frequency) * 10'000'000LL | |
+ ((ticks % MY_CTX.tick_frequency) * 10'000'000LL) / MY_CTX.tick_frequency; | |
diff = ft.ft_i64 - MY_CXT.base_systime_as_filetime.ft_i64; | |
if (diff < -MAX_PERF_COUNTER_SKEW || diff > MAX_PERF_COUNTER_SKEW) | |
{ | |
MY_CXT.base_ticks += ticks; | |
::GetSystemTimeAsFileTime(&MY_CXT.base_systime_as_filetime.ft_val); | |
ft.ft_i64 = MY_CXT.base_systime_as_filetime.ft_i64; | |
} | |
} | |
*out = ft.ft_val; | |
} | |
static int gettimeofday(struct timeval *tv, void *tz) | |
{ | |
FT_t ft; | |
_GetSystemTimePreciseAsFileTime(&ft.ft_val); | |
/* seconds since epoch */ | |
tv->tv_sec = (long)((ft.ft_i64 - EPOCH_BIAS) / 10LL / 1'000'000LL); | |
/* microseconds remaining */ | |
tv->tv_usec = (long)((ft.ft_i64 / 10LL) % 1'000'000LL); | |
return 0; | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment