int rb_gettimeofday(struct timeval *tp, void *not_used) { FT_t ft; /* this returns time in 100-nanosecond units (i.e. tens of usecs) */ GetSystemTimeAsFileTime(&ft.ft_val); /* seconds since epoch */ tp->tv_sec = (long)((ft.ft_i64 - EPOCH_BIAS) / Const64(10000000)); /* microseconds remaining */ tp->tv_usec = (long)((ft.ft_i64 / Const64(10)) % Const64(1000000)); return 0; }
int _gettimeofday(struct timeval *tp, void *not_used) { my_cxt_t MY_CXT; memset(&MY_CXT,0,sizeof(my_cxt_t)); unsigned __int64 ticks; FT_t ft; if (MY_CXT.run_count++ == 0 || MY_CXT.base_systime_as_filetime.ft_i64 > MY_CXT.reset_time) { QueryPerformanceFrequency((LARGE_INTEGER*)&MY_CXT.tick_frequency); QueryPerformanceCounter((LARGE_INTEGER*)&MY_CXT.base_ticks); GetSystemTimeAsFileTime(&MY_CXT.base_systime_as_filetime.ft_val); ft.ft_i64 = MY_CXT.base_systime_as_filetime.ft_i64; MY_CXT.reset_time = ft.ft_i64 + MAX_PERF_COUNTER_TICKS; } else { __int64 diff; QueryPerformanceCounter((LARGE_INTEGER*)&ticks); ticks -= MY_CXT.base_ticks; ft.ft_i64 = MY_CXT.base_systime_as_filetime.ft_i64 + Const64(10000000) * (ticks / MY_CXT.tick_frequency) +(Const64(10000000) * (ticks % MY_CXT.tick_frequency)) / MY_CXT.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; } } /* seconds since epoch */ tp->tv_sec = (long)((ft.ft_i64 - EPOCH_BIAS) / Const64(10000000)); /* microseconds remaining */ tp->tv_usec = (long)((ft.ft_i64 / Const64(10)) % Const64(1000000)); return 0; }
START_MY_CXT /* Number of 100 nanosecond units from 1/1/1601 to 1/1/1970 */ #ifdef __GNUC__ # define Const64(x) x##LL #else # define Const64(x) x##i64 #endif #define EPOCH_BIAS Const64(116444736000000000) /* NOTE: This does not compute the timezone info (doing so can be expensive, * and appears to be unsupported even by glibc) */ /* dMY_CXT needs a Perl context and we don't want to call PERL_GET_CONTEXT for performance reasons */ #undef gettimeofday #define gettimeofday(tp, not_used) _gettimeofday(aTHX_ tp, not_used) /* 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 Const64(5000000) /* 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 Const64(300000000) /* 300 seconds */ static int _gettimeofday(pTHX_ struct timeval *tp, void *not_used) { dMY_CXT; unsigned __int64 ticks; FT_t ft; if (MY_CXT.run_count++ == 0 || MY_CXT.base_systime_as_filetime.ft_i64 > MY_CXT.reset_time) { QueryPerformanceFrequency((LARGE_INTEGER*)&MY_CXT.tick_frequency); QueryPerformanceCounter((LARGE_INTEGER*)&MY_CXT.base_ticks); GetSystemTimeAsFileTime(&MY_CXT.base_systime_as_filetime.ft_val); ft.ft_i64 = MY_CXT.base_systime_as_filetime.ft_i64; MY_CXT.reset_time = ft.ft_i64 + MAX_PERF_COUNTER_TICKS; } else { __int64 diff; QueryPerformanceCounter((LARGE_INTEGER*)&ticks); ticks -= MY_CXT.base_ticks; ft.ft_i64 = MY_CXT.base_systime_as_filetime.ft_i64 + Const64(10000000) * (ticks / MY_CXT.tick_frequency) +(Const64(10000000) * (ticks % MY_CXT.tick_frequency)) / MY_CXT.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; } } /* seconds since epoch */ tp->tv_sec = (long)((ft.ft_i64 - EPOCH_BIAS) / Const64(10000000)); /* microseconds remaining */ tp->tv_usec = (long)((ft.ft_i64 / Const64(10)) % Const64(1000000)); return 0; }