void get_real_time (timeout_t * to) { #if defined (WIN32) #if 0 static DWORD prec_nsec = 0, dummy; static BOOL b1; if (prec_nsec == 0) GetSystemTimeAdjustment (&dummy, &prec_nsec, &dummy); to->to_sec = time (NULL); if (prec_nsec) to->to_usec = (((long) (GetTickCount () / (prec_nsec * 10))) * (prec_nsec * 10)) % 1000; else to->to_usec = GetTickCount () % 1000; #else ULARGE_INTEGER tim; GetSystemTimeAsFileTime ((FILETIME *) & tim); /* 100ns ticks since Jan 1, 1601 */ tim.QuadPart -= 0x19DB1DED53E8000L; /* ticks between 1601 and 1970 year */ tim.QuadPart /= 10; /* convert to microseconds */ to->to_usec = (int32) (tim.QuadPart % 1000000); /* microseconds */ to->to_sec = (int32) (tim.QuadPart / 1000000); /* seconds */ #endif #else struct timeval tv; gettimeofday (&tv, NULL); to->to_sec = tv.tv_sec; to->to_usec = tv.tv_usec; #endif }
/** * Get the SCHED_RR interval. * @param pid The process identifier. * @param tp The SCHED_RR interval. * @return Always return 0. */ int sched_rr_get_interval(pid_t pid, struct timespec * tp) { DWORD timeAdjustment, timeIncrement; BOOL isTimeAdjustmentDisabled; (void) GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement, &isTimeAdjustmentDisabled); tp->tv_sec = 0; tp->tv_nsec = timeIncrement * 100; return 0; }
/* * This function is called every time the random pool needs * stirring, and will acquire the system time in all available * forms. */ void noise_get_light(void (*func) (void *, int)) { SYSTEMTIME systime; DWORD adjust[2]; BOOL rubbish; GetSystemTime(&systime); func(&systime, sizeof(systime)); GetSystemTimeAdjustment(&adjust[0], &adjust[1], &rubbish); func(&adjust, sizeof(adjust)); }
static void hugsprim_GetSystemTimeAdjustment_5(HugsStackPtr hugs_root) { HsPtr arg1; HsPtr arg2; HsPtr arg3; HsBool res1; arg1 = hugs->getPtr(); arg2 = hugs->getPtr(); arg3 = hugs->getPtr(); res1 = GetSystemTimeAdjustment(arg1, arg2, arg3); hugs->putBool(res1); hugs->returnIO(hugs_root,1); }
/* * This function is called every time the random pool needs * stirring, and will acquire the system time in all available * forms and the battery status. */ void noise_get_light(void (*func) (void *, int)) { SYSTEMTIME systime; DWORD adjust[2]; BOOL rubbish; SYSTEM_POWER_STATUS pwrstat; GetSystemTime(&systime); func(&systime, sizeof(systime)); GetSystemTimeAdjustment(&adjust[0], &adjust[1], &rubbish); func(&adjust, sizeof(adjust)); if (GetSystemPowerStatus(&pwrstat)) func(&pwrstat, sizeof(pwrstat)); }
static void InitThresholds() { DWORD timeAdjustment = 0, timeIncrement = 0; BOOL timeAdjustmentDisabled; GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement, &timeAdjustmentDisabled); LOG(("TimeStamp: timeIncrement=%d [100ns]", timeIncrement)); if (!timeIncrement) timeIncrement = kDefaultTimeIncrement; // Ceiling to a millisecond // Example values: 156001, 210000 DWORD timeIncrementCeil = timeIncrement; // Don't want to round up if already rounded, values will be: 156000, 209999 timeIncrementCeil -= 1; // Convert to ms, values will be: 15, 20 timeIncrementCeil /= 10000; // Round up, values will be: 16, 21 timeIncrementCeil += 1; // Convert back to 100ns, values will be: 160000, 210000 timeIncrementCeil *= 10000; // How many milli-ticks has the interval LONGLONG ticksPerGetTickCountResolution = (int64_t(timeIncrement) * sFrequencyPerSec) / 10000LL; // How many milli-ticks has the interval rounded up LONGLONG ticksPerGetTickCountResolutionCeiling = (int64_t(timeIncrementCeil) * sFrequencyPerSec) / 10000LL; // I observed differences about 2 times of the GTC resolution. GTC may // jump by 32 ms in two steps, therefor use the ceiling value. // Having 64 (15.6 or 16 * 4 exactly) is used to avoid false negatives // for very short times where QPC and GTC may jitter even more. sUnderrunThreshold = LONGLONG((-4) * ticksPerGetTickCountResolutionCeiling); // QPC should go no further than 2 * GTC resolution. sOverrunThreshold = LONGLONG((+4) * ticksPerGetTickCountResolution); sQPCHardFailureDetectionInterval = LONGLONG(kQPCHardFailureDetectionInterval) * sFrequencyPerSec; }
static void InitThresholds() { DWORD timeAdjustment = 0, timeIncrement = 0; BOOL timeAdjustmentDisabled; GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement, &timeAdjustmentDisabled); if (!timeIncrement) timeIncrement = kDefaultTimeIncrement; // Ceiling to a millisecond // Example values: 156001, 210000 DWORD timeIncrementCeil = timeIncrement; // Don't want to round up if already rounded, values will be: 156000, 209999 timeIncrementCeil -= 1; // Convert to ms, values will be: 15, 20 timeIncrementCeil /= 10000; // Round up, values will be: 16, 21 timeIncrementCeil += 1; // Convert back to 100ns, values will be: 160000, 210000 timeIncrementCeil *= 10000; // How many milli-ticks has the interval LONGLONG ticksPerGetTickCountResolution = (PRInt64(timeIncrement) * sFrequencyPerSec) / 10000LL; // How many milli-ticks has the interval rounded up LONGLONG ticksPerGetTickCountResolutionCeiling = (PRInt64(timeIncrementCeil) * sFrequencyPerSec) / 10000LL; // I observed differences about 2 times of the GTC resolution. GTC may // jump by 32 ms in two steps, therefor use the ceiling value. sUnderrunThreshold = LONGLONG((-2) * ticksPerGetTickCountResolutionCeiling); // QPC should go no further then 2 * GTC resolution sOverrunThreshold = LONGLONG((+2) * ticksPerGetTickCountResolution); }
extern "C" int clock_getres(clockid_t clock_id, struct timespec* res) { if (!res) { errno = EFAULT; return -1; } static constexpr size_t kNsPerSec = 1000000000; switch (clock_id) { case CLOCK_REALTIME: { constexpr auto perSec = double(std::chrono::system_clock::period::num) / std::chrono::system_clock::period::den; res->tv_sec = time_t(perSec); res->tv_nsec = time_t(perSec * kNsPerSec); return 0; } case CLOCK_MONOTONIC: { constexpr auto perSec = double(std::chrono::steady_clock::period::num) / std::chrono::steady_clock::period::den; res->tv_sec = time_t(perSec); res->tv_nsec = time_t(perSec * kNsPerSec); return 0; } case CLOCK_PROCESS_CPUTIME_ID: case CLOCK_THREAD_CPUTIME_ID: { DWORD adj, timeIncrement; BOOL adjDisabled; if (!GetSystemTimeAdjustment(&adj, &timeIncrement, &adjDisabled)) { errno = EINVAL; return -1; } res->tv_sec = 0; res->tv_nsec = long(timeIncrement * 100); return 0; } default: errno = EINVAL; return -1; } }
static void InitThresholds() { DWORD timeAdjustment = 0, timeIncrement = 0; BOOL timeAdjustmentDisabled; GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement, &timeAdjustmentDisabled); LOG(("TimeStamp: timeIncrement=%d [100ns]", timeIncrement)); if (!timeIncrement) { timeIncrement = kDefaultTimeIncrement; } // Ceiling to a millisecond // Example values: 156001, 210000 DWORD timeIncrementCeil = timeIncrement; // Don't want to round up if already rounded, values will be: 156000, 209999 timeIncrementCeil -= 1; // Convert to ms, values will be: 15, 20 timeIncrementCeil /= 10000; // Round up, values will be: 16, 21 timeIncrementCeil += 1; // Convert back to 100ns, values will be: 160000, 210000 timeIncrementCeil *= 10000; // How many milli-ticks has the interval rounded up LONGLONG ticksPerGetTickCountResolutionCeiling = (int64_t(timeIncrementCeil) * sFrequencyPerSec) / 10000LL; // GTC may jump by 32 (2*16) ms in two steps, therefor use the ceiling value. sGTCResolutionThreshold = LONGLONG(kGTCTickLeapTolerance * ticksPerGetTickCountResolutionCeiling); sHardFailureLimit = ms2mt(kHardFailureLimit); sFailureFreeInterval = ms2mt(kFailureFreeInterval); sFailureThreshold = ms2mt(kFailureThreshold); }
double __kmps_get_wtick( void ) { // Number of seconds between successive clock ticks. double wtick = 0.0; i; #if KMP_OS_WINDOWS { DWORD increment; DWORD adjustment; BOOL disabled; BOOL rc; rc = GetSystemTimeAdjustment( & adjustment, & increment, & disabled ); if ( rc ) { wtick = 1.0E-07 * (double)( disabled ? increment : adjustment ); } else { // TODO: Assert or abort here. wtick = 1.0E-03; }; // if } #else // TODO: gettimeofday() returns in microseconds, but what the precision? wtick = 1.0E-06; #endif return wtick; }; // __kmps_get_wtick
static PyObject* pymonotonic(_Py_clock_info_t *info) { #if defined(MS_WINDOWS) static ULONGLONG (*GetTickCount64) (void) = NULL; static ULONGLONG (CALLBACK *Py_GetTickCount64)(void); static int has_getickcount64 = -1; double result; if (has_getickcount64 == -1) { /* GetTickCount64() was added to Windows Vista */ if (winver.dwMajorVersion >= 6) { HINSTANCE hKernel32; hKernel32 = GetModuleHandleW(L"KERNEL32"); *(FARPROC*)&Py_GetTickCount64 = GetProcAddress(hKernel32, "GetTickCount64"); has_getickcount64 = (Py_GetTickCount64 != NULL); } else has_getickcount64 = 0; } if (has_getickcount64) { ULONGLONG ticks; ticks = Py_GetTickCount64(); result = (double)ticks * 1e-3; } else { static DWORD last_ticks = 0; static DWORD n_overflow = 0; DWORD ticks; ticks = GetTickCount(); if (ticks < last_ticks) n_overflow++; last_ticks = ticks; result = ldexp(n_overflow, 32); result += ticks; result *= 1e-3; } if (info) { DWORD timeAdjustment, timeIncrement; BOOL isTimeAdjustmentDisabled, ok; if (has_getickcount64) info->implementation = "GetTickCount64()"; else info->implementation = "GetTickCount()"; info->monotonic = 1; ok = GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement, &isTimeAdjustmentDisabled); if (!ok) { PyErr_SetFromWindowsErr(0); return NULL; } info->resolution = timeIncrement * 1e-7; info->adjustable = 0; } return PyFloat_FromDouble(result); #elif defined(__APPLE__) static mach_timebase_info_data_t timebase; uint64_t time; double secs; if (timebase.denom == 0) { /* According to the Technical Q&A QA1398, mach_timebase_info() cannot fail: https://developer.apple.com/library/mac/#qa/qa1398/ */ (void)mach_timebase_info(&timebase); } time = mach_absolute_time(); secs = (double)time * timebase.numer / timebase.denom * 1e-9; if (info) { info->implementation = "mach_absolute_time()"; info->resolution = (double)timebase.numer / timebase.denom * 1e-9; info->monotonic = 1; info->adjustable = 0; } return PyFloat_FromDouble(secs); #elif defined(HAVE_CLOCK_GETTIME) && (defined(CLOCK_HIGHRES) || defined(CLOCK_MONOTONIC)) struct timespec tp; #ifdef CLOCK_HIGHRES const clockid_t clk_id = CLOCK_HIGHRES; const char *function = "clock_gettime(CLOCK_HIGHRES)"; #else const clockid_t clk_id = CLOCK_MONOTONIC; const char *function = "clock_gettime(CLOCK_MONOTONIC)"; #endif if (clock_gettime(clk_id, &tp) != 0) { PyErr_SetFromErrno(PyExc_OSError); return NULL; } if (info) { struct timespec res; info->monotonic = 1; info->implementation = function; info->adjustable = 0; if (clock_getres(clk_id, &res) == 0) info->resolution = res.tv_sec + res.tv_nsec * 1e-9; else info->resolution = 1e-9; } return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9); #endif }
void init_winnt_time(void) { BOOL noslew; HANDLE hToken; TOKEN_PRIVILEGES tkp; /* * Get privileges needed for fiddling with the clock */ /* get the current process token handle */ if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { msyslog(LOG_ERR, "OpenProcessToken failed: %m"); exit(-1); } /* get the LUID for system-time privilege. */ LookupPrivilegeValue(NULL, SE_SYSTEMTIME_NAME, &tkp.Privileges[0].Luid); tkp.PrivilegeCount = 1; /* one privilege to set */ tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; /* get set-time privilege for this process. */ AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES) NULL, 0); /* cannot use return value of AdjustTokenPrivileges. */ /* (success does not indicate all privileges were set) */ if (GetLastError() != ERROR_SUCCESS) { msyslog(LOG_ERR, "AdjustTokenPrivileges failed: %m"); /* later set time call will probably fail */ } /* Reset the Clock to a reasonable increment */ if (!GetSystemTimeAdjustment(&initial_units_per_tick, &every,&noslew)) { msyslog(LOG_ERR, "GetSystemTimeAdjustment failed: %m\n"); exit (-1); } units_per_tick = initial_units_per_tick; /* Calculate the time adjustment resulting from incrementing * units per tick by 1 unit for 1 second */ ppm_per_adjust_unit = 1000000.0 / (double) every; #ifdef DEBUG msyslog(LOG_INFO, "Initial Clock increment %7.1f us", (float) (units_per_tick / 10)); msyslog(LOG_INFO, "Adjustment rate %5.3f ppm/s", ppm_per_adjust_unit); #endif /*++++ Gerhard Junker * see Platform SDK for QueryPerformanceCounter * On a multiprocessor machine, it should not matter which processor is called. * However, you can get different results on different processors due to bugs in the BIOS or the HAL. * To specify processor affinity for a thread, use the SetThreadAffinityMask function. * ... we will hope, the apc routine will run on the same processor */ SetThreadAffinityMask(GetCurrentThread(), 1L); /*---- Gerhard Junker */ }
/** * @interface_method_impl{VBOXSERVICE,pfnInit} */ static DECLCALLBACK(int) vgsvcTimeSyncInit(void) { /* * If not specified, find the right interval default. * Then create the event sem to block on. */ if (!g_TimeSyncInterval) g_TimeSyncInterval = g_DefaultInterval * 1000; if (!g_TimeSyncInterval) g_TimeSyncInterval = 10 * 1000; VbglR3GetSessionId(&g_idTimeSyncSession); /* The status code is ignored as this information is not available with VBox < 3.2.10. */ int rc = RTSemEventMultiCreate(&g_TimeSyncEvent); AssertRC(rc); #ifdef RT_OS_WINDOWS if (RT_SUCCESS(rc)) { /* * Adjust privileges of this process so we can make system time adjustments. */ if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &g_hTokenProcess)) { TOKEN_PRIVILEGES tkPriv; RT_ZERO(tkPriv); tkPriv.PrivilegeCount = 1; tkPriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if (LookupPrivilegeValue(NULL, SE_SYSTEMTIME_NAME, &tkPriv.Privileges[0].Luid)) { DWORD cbRet = sizeof(g_TkOldPrivileges); if (AdjustTokenPrivileges(g_hTokenProcess, FALSE, &tkPriv, sizeof(TOKEN_PRIVILEGES), &g_TkOldPrivileges, &cbRet)) rc = VINF_SUCCESS; else { DWORD dwErr = GetLastError(); rc = RTErrConvertFromWin32(dwErr); VGSvcError("vgsvcTimeSyncInit: Adjusting token privileges (SE_SYSTEMTIME_NAME) failed with status code %u/%Rrc!\n", dwErr, rc); } } else { DWORD dwErr = GetLastError(); rc = RTErrConvertFromWin32(dwErr); VGSvcError("vgsvcTimeSyncInit: Looking up token privileges (SE_SYSTEMTIME_NAME) failed with status code %u/%Rrc!\n", dwErr, rc); } if (RT_FAILURE(rc)) { CloseHandle(g_hTokenProcess); g_hTokenProcess = NULL; } } else { DWORD dwErr = GetLastError(); rc = RTErrConvertFromWin32(dwErr); VGSvcError("vgsvcTimeSyncInit: Opening process token (SE_SYSTEMTIME_NAME) failed with status code %u/%Rrc!\n", dwErr, rc); g_hTokenProcess = NULL; } } if (GetSystemTimeAdjustment(&g_dwWinTimeAdjustment, &g_dwWinTimeIncrement, &g_bWinTimeAdjustmentDisabled)) VGSvcVerbose(3, "vgsvcTimeSyncInit: Initially %ld (100ns) units per %ld (100 ns) units interval, disabled=%d\n", g_dwWinTimeAdjustment, g_dwWinTimeIncrement, g_bWinTimeAdjustmentDisabled ? 1 : 0); else { DWORD dwErr = GetLastError(); rc = RTErrConvertFromWin32(dwErr); VGSvcError("vgsvcTimeSyncInit: Could not get time adjustment values! Last error: %ld!\n", dwErr); } #endif /* RT_OS_WINDOWS */ return rc; }
/** * Try adjust the time using adjtime or similar. * * @returns true on success, false on failure. * * @param pDrift The time adjustment. */ static bool vgsvcTimeSyncAdjust(PCRTTIMESPEC pDrift) { #ifdef RT_OS_WINDOWS /** @todo r=bird: g_hTokenProcess cannot be NULL here. * vgsvcTimeSyncInit will fail and the service will not be started with * it being NULL. vgsvcTimeSyncInit OTOH will *NOT* be called until the * service thread has terminated. If anything * else is the case, there is buggy code somewhere.*/ if (g_hTokenProcess == NULL) /* Is the token already closed when shutting down? */ return false; DWORD dwWinTimeAdjustment, dwWinNewTimeAdjustment, dwWinTimeIncrement; BOOL fWinTimeAdjustmentDisabled; if (GetSystemTimeAdjustment(&dwWinTimeAdjustment, &dwWinTimeIncrement, &fWinTimeAdjustmentDisabled)) { DWORD dwDiffMax = g_dwWinTimeAdjustment * 0.50; DWORD dwDiffNew = dwWinTimeAdjustment * 0.10; if (RTTimeSpecGetMilli(pDrift) > 0) { dwWinNewTimeAdjustment = dwWinTimeAdjustment + dwDiffNew; if (dwWinNewTimeAdjustment > (g_dwWinTimeAdjustment + dwDiffMax)) { dwWinNewTimeAdjustment = g_dwWinTimeAdjustment + dwDiffMax; dwDiffNew = dwDiffMax; } } else { dwWinNewTimeAdjustment = dwWinTimeAdjustment - dwDiffNew; if (dwWinNewTimeAdjustment < (g_dwWinTimeAdjustment - dwDiffMax)) { dwWinNewTimeAdjustment = g_dwWinTimeAdjustment - dwDiffMax; dwDiffNew = dwDiffMax; } } VGSvcVerbose(3, "vgsvcTimeSyncAdjust: Drift=%lldms\n", RTTimeSpecGetMilli(pDrift)); VGSvcVerbose(3, "vgsvcTimeSyncAdjust: OrgTA=%ld, CurTA=%ld, NewTA=%ld, DiffNew=%ld, DiffMax=%ld\n", g_dwWinTimeAdjustment, dwWinTimeAdjustment, dwWinNewTimeAdjustment, dwDiffNew, dwDiffMax); if (SetSystemTimeAdjustment(dwWinNewTimeAdjustment, FALSE /* Periodic adjustments enabled. */)) { g_cTimeSyncErrors = 0; return true; } if (g_cTimeSyncErrors++ < 10) VGSvcError("vgsvcTimeSyncAdjust: SetSystemTimeAdjustment failed, error=%u\n", GetLastError()); } else if (g_cTimeSyncErrors++ < 10) VGSvcError("vgsvcTimeSyncAdjust: GetSystemTimeAdjustment failed, error=%ld\n", GetLastError()); #elif defined(RT_OS_OS2) || defined(RT_OS_HAIKU) /* No API for doing gradual time adjustments. */ #else /* PORTME */ /* * Try use adjtime(), most unix-like systems have this. */ struct timeval tv; RTTimeSpecGetTimeval(pDrift, &tv); if (adjtime(&tv, NULL) == 0) { if (g_cVerbosity >= 1) VGSvcVerbose(1, "vgsvcTimeSyncAdjust: adjtime by %RDtimespec\n", pDrift); g_cTimeSyncErrors = 0; return true; } #endif /* failed */ return false; }
static void pygettimeofday(_PyTime_timeval *tp, _Py_clock_info_t *info) { #ifdef MS_WINDOWS FILETIME system_time; ULARGE_INTEGER large; ULONGLONG microseconds; GetSystemTimeAsFileTime(&system_time); large.u.LowPart = system_time.dwLowDateTime; large.u.HighPart = system_time.dwHighDateTime; /* 11,644,473,600,000,000: number of microseconds between the 1st january 1601 and the 1st january 1970 (369 years + 89 leap days). */ microseconds = large.QuadPart / 10 - 11644473600000000; tp->tv_sec = microseconds / 1000000; tp->tv_usec = microseconds % 1000000; if (info) { DWORD timeAdjustment, timeIncrement; BOOL isTimeAdjustmentDisabled; info->implementation = "GetSystemTimeAsFileTime()"; info->monotonic = 0; (void) GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement, &isTimeAdjustmentDisabled); info->resolution = timeIncrement * 1e-7; info->adjustable = 1; } #else /* There are three ways to get the time: (1) gettimeofday() -- resolution in microseconds (2) ftime() -- resolution in milliseconds (3) time() -- resolution in seconds In all cases the return value in a timeval struct. Since on some systems (e.g. SCO ODT 3.0) gettimeofday() may fail, so we fall back on ftime() or time(). Note: clock resolution does not imply clock accuracy! */ #ifdef HAVE_GETTIMEOFDAY int err; #ifdef GETTIMEOFDAY_NO_TZ err = gettimeofday(tp); #else err = gettimeofday(tp, (struct timezone *)NULL); #endif if (err == 0) { if (info) { info->implementation = "gettimeofday()"; info->resolution = 1e-6; info->monotonic = 0; info->adjustable = 1; } return; } #endif /* HAVE_GETTIMEOFDAY */ #if defined(HAVE_FTIME) { struct timeb t; ftime(&t); tp->tv_sec = t.time; tp->tv_usec = t.millitm * 1000; if (info) { info->implementation = "ftime()"; info->resolution = 1e-3; info->monotonic = 0; info->adjustable = 1; } } #else /* !HAVE_FTIME */ tp->tv_sec = time(NULL); tp->tv_usec = 0; if (info) { info->implementation = "time()"; info->resolution = 1.0; info->monotonic = 0; info->adjustable = 1; } #endif /* !HAVE_FTIME */ #endif /* MS_WINDOWS */ }
static int pymonotonic(_PyTime_t *tp, _Py_clock_info_t *info, int raise) { #if defined(MS_WINDOWS) ULONGLONG ticks; _PyTime_t t; assert(info == NULL || raise); ticks = GetTickCount64(); Py_BUILD_ASSERT(sizeof(ticks) <= sizeof(_PyTime_t)); t = (_PyTime_t)ticks; if (_PyTime_check_mul_overflow(t, MS_TO_NS)) { if (raise) { _PyTime_overflow(); return -1; } /* Hello, time traveler! */ assert(0); } *tp = t * MS_TO_NS; if (info) { DWORD timeAdjustment, timeIncrement; BOOL isTimeAdjustmentDisabled, ok; info->implementation = "GetTickCount64()"; info->monotonic = 1; ok = GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement, &isTimeAdjustmentDisabled); if (!ok) { PyErr_SetFromWindowsErr(0); return -1; } info->resolution = timeIncrement * 1e-7; info->adjustable = 0; } #elif defined(__APPLE__) static mach_timebase_info_data_t timebase; uint64_t time; if (timebase.denom == 0) { /* According to the Technical Q&A QA1398, mach_timebase_info() cannot fail: https://developer.apple.com/library/mac/#qa/qa1398/ */ (void)mach_timebase_info(&timebase); } time = mach_absolute_time(); /* apply timebase factor */ time *= timebase.numer; time /= timebase.denom; *tp = time; if (info) { info->implementation = "mach_absolute_time()"; info->resolution = (double)timebase.numer / timebase.denom * 1e-9; info->monotonic = 1; info->adjustable = 0; } #else struct timespec ts; #ifdef CLOCK_HIGHRES const clockid_t clk_id = CLOCK_HIGHRES; const char *implementation = "clock_gettime(CLOCK_HIGHRES)"; #else const clockid_t clk_id = CLOCK_MONOTONIC; const char *implementation = "clock_gettime(CLOCK_MONOTONIC)"; #endif assert(info == NULL || raise); if (clock_gettime(clk_id, &ts) != 0) { if (raise) { PyErr_SetFromErrno(PyExc_OSError); return -1; } return -1; } if (info) { struct timespec res; info->monotonic = 1; info->implementation = implementation; info->adjustable = 0; if (clock_getres(clk_id, &res) != 0) { PyErr_SetFromErrno(PyExc_OSError); return -1; } info->resolution = res.tv_sec + res.tv_nsec * 1e-9; } if (_PyTime_FromTimespec(tp, &ts, raise) < 0) return -1; #endif return 0; }
static int pygettimeofday(_PyTime_t *tp, _Py_clock_info_t *info, int raise) { #ifdef MS_WINDOWS FILETIME system_time; ULARGE_INTEGER large; assert(info == NULL || raise); GetSystemTimeAsFileTime(&system_time); large.u.LowPart = system_time.dwLowDateTime; large.u.HighPart = system_time.dwHighDateTime; /* 11,644,473,600,000,000,000: number of nanoseconds between the 1st january 1601 and the 1st january 1970 (369 years + 89 leap days). */ *tp = large.QuadPart * 100 - 11644473600000000000; if (info) { DWORD timeAdjustment, timeIncrement; BOOL isTimeAdjustmentDisabled, ok; info->implementation = "GetSystemTimeAsFileTime()"; info->monotonic = 0; ok = GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement, &isTimeAdjustmentDisabled); if (!ok) { PyErr_SetFromWindowsErr(0); return -1; } info->resolution = timeIncrement * 1e-7; info->adjustable = 1; } #else /* MS_WINDOWS */ int err; #ifdef HAVE_CLOCK_GETTIME struct timespec ts; #else struct timeval tv; #endif assert(info == NULL || raise); #ifdef HAVE_CLOCK_GETTIME err = clock_gettime(CLOCK_REALTIME, &ts); if (err) { if (raise) PyErr_SetFromErrno(PyExc_OSError); return -1; } if (_PyTime_FromTimespec(tp, &ts, raise) < 0) return -1; if (info) { struct timespec res; info->implementation = "clock_gettime(CLOCK_REALTIME)"; info->monotonic = 0; info->adjustable = 1; if (clock_getres(CLOCK_REALTIME, &res) == 0) info->resolution = res.tv_sec + res.tv_nsec * 1e-9; else info->resolution = 1e-9; } #else /* HAVE_CLOCK_GETTIME */ /* test gettimeofday() */ #ifdef GETTIMEOFDAY_NO_TZ err = gettimeofday(&tv); #else err = gettimeofday(&tv, (struct timezone *)NULL); #endif if (err) { if (raise) PyErr_SetFromErrno(PyExc_OSError); return -1; } if (_PyTime_FromTimeval(tp, &tv, raise) < 0) return -1; if (info) { info->implementation = "gettimeofday()"; info->resolution = 1e-6; info->monotonic = 0; info->adjustable = 1; } #endif /* !HAVE_CLOCK_GETTIME */ #endif /* !MS_WINDOWS */ return 0; }
JSInt64 PRMJ_Now(void) { #ifdef XP_OS2 JSInt64 s, us, ms2us, s2us; struct timeb b; #endif #ifdef XP_WIN static int nCalls = 0; long double lowresTime, highresTimerValue; FILETIME ft; LARGE_INTEGER now; JSBool calibrated = JS_FALSE; JSBool needsCalibration = JS_FALSE; JSInt64 returnedTime; long double cachedOffset = 0.0; #endif #if defined(XP_UNIX) || defined(XP_BEOS) struct timeval tv; JSInt64 s, us, s2us; #endif /* XP_UNIX */ #ifdef XP_OS2 ftime(&b); JSLL_UI2L(ms2us, PRMJ_USEC_PER_MSEC); JSLL_UI2L(s2us, PRMJ_USEC_PER_SEC); JSLL_UI2L(s, b.time); JSLL_UI2L(us, b.millitm); JSLL_MUL(us, us, ms2us); JSLL_MUL(s, s, s2us); JSLL_ADD(s, s, us); return s; #endif #ifdef XP_WIN /* To avoid regressing startup time (where high resolution is likely not needed), give the old behavior for the first few calls. This does not appear to be needed on Vista as the timeBegin/timeEndPeriod calls seem to immediately take effect. */ int thiscall = JS_ATOMIC_INCREMENT(&nCalls); /* 10 seems to be the number of calls to load with a blank homepage */ if (thiscall <= 10) { GetSystemTimeAsFileTime(&ft); return (FILETIME2INT64(ft)-win2un)/10L; } /* For non threadsafe platforms, NowInit is not necessary */ #ifdef JS_THREADSAFE PR_CallOnce(&calibrationOnce, NowInit); #endif do { if (!calibration.calibrated || needsCalibration) { MUTEX_LOCK(&calibration.calibration_lock); MUTEX_LOCK(&calibration.data_lock); /* Recalibrate only if no one else did before us */ if(calibration.offset == cachedOffset) { /* Since calibration can take a while, make any other threads immediately wait */ MUTEX_SETSPINCOUNT(&calibration.data_lock, 0); NowCalibrate(); calibrated = JS_TRUE; /* Restore spin count */ MUTEX_SETSPINCOUNT(&calibration.data_lock, DATALOCK_SPINCOUNT); } MUTEX_UNLOCK(&calibration.data_lock); MUTEX_UNLOCK(&calibration.calibration_lock); } /* Calculate a low resolution time */ GetSystemTimeAsFileTime(&ft); lowresTime = 0.1*(long double)(FILETIME2INT64(ft) - win2un); if (calibration.freq > 0.0) { long double highresTime, diff; DWORD timeAdjustment, timeIncrement; BOOL timeAdjustmentDisabled; /* Default to 15.625 ms if the syscall fails */ long double skewThreshold = 15625.25; /* Grab high resolution time */ QueryPerformanceCounter(&now); highresTimerValue = (long double)now.QuadPart; MUTEX_LOCK(&calibration.data_lock); highresTime = calibration.offset + PRMJ_USEC_PER_SEC* (highresTimerValue-calibration.timer_offset)/calibration.freq; cachedOffset = calibration.offset; /* On some dual processor/core systems, we might get an earlier time so we cache the last time that we returned */ calibration.last = max(calibration.last,(JSInt64)highresTime); returnedTime = calibration.last; MUTEX_UNLOCK(&calibration.data_lock); /* Rather than assume the NT kernel ticks every 15.6ms, ask it */ if (GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement, &timeAdjustmentDisabled)) { if (timeAdjustmentDisabled) { /* timeAdjustment is in units of 100ns */ skewThreshold = timeAdjustment/10.0; } else { /* timeIncrement is in units of 100ns */ skewThreshold = timeIncrement/10.0; } } /* Check for clock skew */ diff = lowresTime - highresTime; /* For some reason that I have not determined, the skew can be up to twice a kernel tick. This does not seem to happen by itself, but I have only seen it triggered by another program doing some kind of file I/O. The symptoms are a negative diff followed by an equally large positive diff. */ if (fabs(diff) > 2*skewThreshold) { /*fprintf(stderr,"Clock skew detected (diff = %f)!\n", diff);*/ if (calibrated) { /* If we already calibrated once this instance, and the clock is still skewed, then either the processor(s) are wildly changing clockspeed or the system is so busy that we get switched out for long periods of time. In either case, it would be infeasible to make use of high resolution results for anything, so let's resort to old behavior for this call. It's possible that in the future, the user will want the high resolution timer, so we don't disable it entirely. */ returnedTime = (JSInt64)lowresTime; needsCalibration = JS_FALSE; } else { /* It is possible that when we recalibrate, we will return a value less than what we have returned before; this is unavoidable. We cannot tell the different between a faulty QueryPerformanceCounter implementation and user changes to the operating system time. Since we must respect user changes to the operating system time, we cannot maintain the invariant that Date.now() never decreases; the old implementation has this behavior as well. */ needsCalibration = JS_TRUE; } } else { /* No detectable clock skew */ returnedTime = (JSInt64)highresTime; needsCalibration = JS_FALSE; } } else { /* No high resolution timer is available, so fall back */ returnedTime = (JSInt64)lowresTime; } } while (needsCalibration); return returnedTime; #endif #if defined(XP_UNIX) || defined(XP_BEOS) #ifdef _SVID_GETTOD /* Defined only on Solaris, see Solaris <sys/types.h> */ gettimeofday(&tv); #else gettimeofday(&tv, 0); #endif /* _SVID_GETTOD */ JSLL_UI2L(s2us, PRMJ_USEC_PER_SEC); JSLL_UI2L(s, tv.tv_sec); JSLL_UI2L(us, tv.tv_usec); JSLL_MUL(s, s, s2us); JSLL_ADD(s, s, us); return s; #endif /* XP_UNIX */ }
int64_t PRMJ_Now(void) { static int nCalls = 0; long double lowresTime, highresTimerValue; FILETIME ft; LARGE_INTEGER now; bool calibrated = false; bool needsCalibration = false; int64_t returnedTime; long double cachedOffset = 0.0; /* For non threadsafe platforms, NowInit is not necessary */ #ifdef JS_THREADSAFE PR_CallOnce(&calibrationOnce, NowInit); #endif do { if (!calibration.calibrated || needsCalibration) { MUTEX_LOCK(&calibration.calibration_lock); MUTEX_LOCK(&calibration.data_lock); /* Recalibrate only if no one else did before us */ if(calibration.offset == cachedOffset) { /* Since calibration can take a while, make any other threads immediately wait */ MUTEX_SETSPINCOUNT(&calibration.data_lock, 0); NowCalibrate(); calibrated = true; /* Restore spin count */ MUTEX_SETSPINCOUNT(&calibration.data_lock, DATALOCK_SPINCOUNT); } MUTEX_UNLOCK(&calibration.data_lock); MUTEX_UNLOCK(&calibration.calibration_lock); } /* Calculate a low resolution time */ GetSystemTimeAsFileTime(&ft); lowresTime = 0.1*(long double)(FILETIME2INT64(ft) - win2un); if (calibration.freq > 0.0) { long double highresTime, diff; DWORD timeAdjustment, timeIncrement; BOOL timeAdjustmentDisabled; /* Default to 15.625 ms if the syscall fails */ long double skewThreshold = 15625.25; /* Grab high resolution time */ QueryPerformanceCounter(&now); highresTimerValue = (long double)now.QuadPart; MUTEX_LOCK(&calibration.data_lock); highresTime = calibration.offset + PRMJ_USEC_PER_SEC* (highresTimerValue-calibration.timer_offset)/calibration.freq; cachedOffset = calibration.offset; /* On some dual processor/core systems, we might get an earlier time so we cache the last time that we returned */ calibration.last = js::Max(calibration.last, int64_t(highresTime)); returnedTime = calibration.last; MUTEX_UNLOCK(&calibration.data_lock); /* Rather than assume the NT kernel ticks every 15.6ms, ask it */ if (GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement, &timeAdjustmentDisabled)) { if (timeAdjustmentDisabled) { /* timeAdjustment is in units of 100ns */ skewThreshold = timeAdjustment/10.0; } else { /* timeIncrement is in units of 100ns */ skewThreshold = timeIncrement/10.0; } } /* Check for clock skew */ diff = lowresTime - highresTime; /* For some reason that I have not determined, the skew can be up to twice a kernel tick. This does not seem to happen by itself, but I have only seen it triggered by another program doing some kind of file I/O. The symptoms are a negative diff followed by an equally large positive diff. */ if (mozilla::Abs(diff) > 2 * skewThreshold) { /*fprintf(stderr,"Clock skew detected (diff = %f)!\n", diff);*/ if (calibrated) { /* If we already calibrated once this instance, and the clock is still skewed, then either the processor(s) are wildly changing clockspeed or the system is so busy that we get switched out for long periods of time. In either case, it would be infeasible to make use of high resolution results for anything, so let's resort to old behavior for this call. It's possible that in the future, the user will want the high resolution timer, so we don't disable it entirely. */ returnedTime = int64_t(lowresTime); needsCalibration = false; } else { /* It is possible that when we recalibrate, we will return a value less than what we have returned before; this is unavoidable. We cannot tell the different between a faulty QueryPerformanceCounter implementation and user changes to the operating system time. Since we must respect user changes to the operating system time, we cannot maintain the invariant that Date.now() never decreases; the old implementation has this behavior as well. */ needsCalibration = true; } } else { /* No detectable clock skew */ returnedTime = int64_t(highresTime); needsCalibration = false; } } else { /* No high resolution timer is available, so fall back */ returnedTime = int64_t(lowresTime); } } while (needsCalibration); return returnedTime; }