#include #include #include #include #include // Library: Winmm.lib. // gcc clockres.c -l winmm -l ntdll // http://www.sysinternals.com/Information/HighResolutionTimers.html WINAPI NTSTATUS NtQueryTimerResolution ( PULONG MinimumResolution, PULONG MaximumResolution, PULONG ActualResolution ); // A side effect of this function is to synchronize the caller to a tick DWORD get_timeGetTime_resolution() { DWORD time1, time2, priority; priority = GetThreadPriority (GetCurrentThread ()); SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_TIME_CRITICAL); time1 = timeGetTime(); do { time2 = timeGetTime(); } while (time1 == time2); SetThreadPriority (GetCurrentThread (), priority); return time2 - time1; } DWORD get_NT_resolution() { #ifndef Win9x DWORD res; ULONG MinRes, MaxRes, ActRes; res = NtQueryTimerResolution(&MinRes, &MaxRes, &ActRes); if (res) printf("NtStatus %lu\n", res); return ActRes; #else return 0; #endif } //---------------------------------------------------------------------- // // Main // //---------------------------------------------------------------------- int main( int argc, char *argv[] ) { ULONG MinRes, MaxRes, ActRes; DWORD adjustment, clockInterval; BOOL adjustmentDisabled; DWORD NtRes, TGTRes, Wait, NtResOld, TGTResOld, WaitOld; DWORD time1, time2, time3, time4; DWORD delay, resolution; DWORD res; MMRESULT mmres; int i, count; volatile int loop; const int delay_loop = 10000000; // Calibrate a random delay loop time1 = timeGetTime(); time1 = timeGetTime(); for (loop = 0; loop < delay_loop; loop++) {} time2 = timeGetTime(); printf("Random delay value will be between 0 and %lu ms\n", time2 - time1); printf("Adjust so that it is greater than the resolution.\n"); if (argc > 1) count = atoi(argv[1]); else count = 1; if (argc > 2) delay = atoi(argv[2]); else { printf("Enter delay:\n"); while ((res = scanf("%lu", &delay)) != 1) {printf("%lu\n", res);}; } #ifndef Win9x res = NtQueryTimerResolution(&MinRes, &MaxRes, &ActRes); printf("NtStatus %lu; Min %lu Max %lu Act %lu x 100 ns\n", res, MinRes, MaxRes, ActRes); #endif GetSystemTimeAdjustment( &adjustment, &clockInterval, &adjustmentDisabled ); printf( "The system clock interval is %.06f ms\n", (float) clockInterval / 10000 ); // Make sure WaitFor is loaded. WaitForSingleObject(GetCurrentProcess(), 0); NtResOld = TGTResOld = WaitOld = 0; for (i = 0; i < count; i++) { // Randomize time before calling WaitFor for (loop = 0; loop < rand() % delay_loop; loop++) {} time1 = timeGetTime(); res = WaitForSingleObject(GetCurrentProcess(), delay); time2 = timeGetTime(); Wait = time2 - time1; TGTRes = get_timeGetTime_resolution(); NtRes = get_NT_resolution(); if ((NtRes != NtResOld) ||(TGTRes != TGTResOld) ||(Wait != WaitOld)) { if (delay > Wait) printf("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"); printf("%d: Nt Res %lu, timeGetTime Res %lu, WaitFor Wait %lu\n", i, NtRes, TGTRes, Wait); NtResOld = NtRes; TGTResOld = TGTRes; WaitOld = Wait; } Sleep(950); } // Set the resolution and watch the effect if (argc > 3) resolution = atoi(argv[3]); else { printf("Enter resolution:\n"); while (scanf("%lu", &resolution) != 1) {}; } mmres = timeBeginPeriod(resolution); if (mmres != TIMERR_NOERROR) printf("timeBeginPeriod error %d\n", mmres); else printf("\ntimeBeginPeriod success\n"); time3 = timeGetTime(); res = WaitForSingleObject(GetCurrentProcess(), delay); time4 = timeGetTime(); if (res != WAIT_TIMEOUT) printf("WaitForSingleObject error %lu\n", res); #ifndef Win9x res = NtQueryTimerResolution(&MinRes, &MaxRes, &ActRes); printf("NtStatus %lu; Min %lu Max %lu Act %lu x 100 ns\n", res, MinRes, MaxRes, ActRes); #endif GetSystemTimeAdjustment( &adjustment, &clockInterval, &adjustmentDisabled ); printf( "The system clock interval is %.06f ms\n", (float) clockInterval / 10000 ); printf("timeGetTime resolution %lu\n", get_timeGetTime_resolution()); printf("WaitFor Delay %lu, Wait %lu\n", delay, time4 - time3); exit(0); }