int main( int argc, char** argv ) { tick_t start, time; tick_t tick, freq, res; printf( "Timer test\n" ); timer_lib_initialize(); res = 0xFFFFFFFFFFFFFFFFULL; freq = timer_ticks_per_second(); start = timer_current(); while( 1 ) { time = timer_current(); do { tick = timer_elapsed_ticks( time ); } while( !tick ); if( tick < res ) res = tick; if( timer_elapsed( start ) > 10.0 ) break; } printf( "Resolution: %lfms (%d ticks)\n", 1000.0 * (double)timer_ticks_to_seconds( res ), (int)res ); timer_lib_shutdown(); return 0; }
void timer_reset( timer* time ) { #if defined( _WIN32 ) || defined( _WIN64 ) QueryPerformanceCounter( (LARGE_INTEGER*)&time->clock ); #if USE_FALLBACK time->ref = timeGetTime(); #endif #elif __APPLE__ absolutetime_to_nanoseconds( mach_absolute_time(), &time->clock ); #else struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 }; clock_gettime( CLOCK_MONOTONIC, &ts ); time->clock = ( (tick_t)ts.tv_sec * 1000000000ULL ) + ts.tv_nsec; #endif } deltatime_t timer_elapsed( timer* time, int reset ) { return (deltatime_t)timer_elapsed_ticks( time, reset ) * time->oofreq; } tick_t timer_elapsed_ticks( timer* time, int reset ) { tick_t dt = 0; #if defined( _WIN32 ) || defined( _WIN64 ) tick_t diff; #if USE_FALLBACK tick_t refdiff; deltatime_t timerdiff; tick_t ref = time->ref; #endif tick_t curclock = time->clock; QueryPerformanceCounter( (LARGE_INTEGER*)&curclock ); #if USE_FALLBACK ref = timeGetTime(); #endif diff = curclock - time->clock; #if USE_FALLBACK refdiff = ref - time->ref; if( ref < time->ref ) refdiff = (tick_t)( 1000.0 * diff * time->oofreq ); //Catch looping of the millisecond counter timerdiff = (deltatime_t)( ( diff * time->oofreq ) - ( refdiff * 0.001 ) ); if( ( diff < 0 ) || ( timerdiff > 0.1 ) || ( timerdiff < -0.1 ) ) diff = (tick_t)( ( refdiff * 0.001 ) * time->freq ); //Performance counter messed up, transform reference to counter frequency #endif dt = diff; #if USE_FALLBACK if( reset ) time->ref = ref; #endif #elif __APPLE__ tick_t curclock = time->clock; absolutetime_to_nanoseconds( mach_absolute_time(), &curclock ); dt = curclock - time->clock; #else tick_t curclock; struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 }; clock_gettime( CLOCK_MONOTONIC, &ts ); curclock = ( (tick_t)ts.tv_sec * 1000000000ULL ) + ts.tv_nsec; dt = curclock - time->clock; #endif if( reset ) time->clock = curclock; return dt; } tick_t timer_ticks_per_second( timer* time ) { return time->freq; } tick_t timer_current() { #if defined( _WIN32 ) || defined( _WIN64 ) //TODO: Fallback to timeGetTime for messed up perf counter values tick_t curclock; QueryPerformanceCounter( (LARGE_INTEGER*)&curclock ); return curclock; #elif __APPLE__ tick_t curclock = 0; absolutetime_to_nanoseconds( mach_absolute_time(), &curclock ); return curclock; #else struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 }; clock_gettime( CLOCK_MONOTONIC, &ts ); return ( (uint64_t)ts.tv_sec * 1000000000ULL ) + ts.tv_nsec; #endif } tick_t timer_current_ticks_per_second() { #if defined( _WIN32 ) || defined( _WIN64 ) return _timerlib_curtime_freq; #elif __APPLE__ return 1000000000; #else return 1000000000; #endif } #if defined( _WIN32 ) || defined( _WIN64 ) # if _MSC_VER # include <sys/timeb.h> # else struct __timeb64 { __time64_t time; unsigned short millitm; short timezone; short dstflag; }; _CRTIMP errno_t __cdecl _ftime64_s(_Out_ struct __timeb64 * _Time); # endif #endif tick_t timer_system() { #if defined( _WIN32 ) || defined( _WIN64 ) struct __timeb64 tb; _ftime64_s( &tb ); return ( (tick_t)tb.time * 1000ULL ) + (tick_t)tb.millitm; #elif __APPLE__ tick_t curclock = 0; absolutetime_to_nanoseconds( mach_absolute_time(), &curclock ); return ( curclock / 1000000ULL ); #else struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 }; clock_gettime( CLOCK_REALTIME, &ts ); return ( (uint64_t)ts.tv_sec * 1000ULL ) + ( ts.tv_nsec / 1000000ULL ); #endif }