From 9aa63e40740f2c372598c382ab911bb7ee6cd2e0 Mon Sep 17 00:00:00 2001 From: Daniel Gibson Date: Mon, 4 Mar 2013 00:47:14 +0100 Subject: [PATCH] Some timer-related improvements for POSIX * idSysSignal::Wait should now handle timeouts > 1s better (or at all) * Use clock_gettime for Sys_Milliseconds() * Use CLOCK_MONOTONIC_RAW (and CLOCK_MONOTONIC as fallback if that's not available) for Sys_Milliseconds() and Sys_Microseconds() CLOCK_MONOTONIC can behave strange when NTP is used * Small fixes in Sys_Microseconds(): use 64bit int to store time (like return type...), divide by 1000 (not 1000000) for nsec=>musec --- neo/idlib/sys/posix/posix_thread.cpp | 8 +++-- neo/sys/posix/posix_main.cpp | 44 +++++++++++++--------------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/neo/idlib/sys/posix/posix_thread.cpp b/neo/idlib/sys/posix/posix_thread.cpp index 5b7a301e..ad48521d 100644 --- a/neo/idlib/sys/posix/posix_thread.cpp +++ b/neo/idlib/sys/posix/posix_thread.cpp @@ -266,9 +266,11 @@ bool idSysSignal::Wait( int timeout ) { timespec ts; clock_gettime( CLOCK_REALTIME, &ts ); - - ts.tv_nsec += ( timeout * 1000000 ); - + // DG: handle timeouts > 1s better + int64 t = timeout * 1000000; + ts.tv_nsec += t % 1000000000; + ts.tv_sec += t / 1000000000; + // DG end result = pthread_cond_timedwait( &cond, &mutex, &ts ); assert( result == 0 || ( timeout != idSysSignal::WAIT_INFINITE && result == ETIMEDOUT ) ); diff --git a/neo/sys/posix/posix_main.cpp b/neo/sys/posix/posix_main.cpp index 80ee0831..1d39b45b 100644 --- a/neo/sys/posix/posix_main.cpp +++ b/neo/sys/posix/posix_main.cpp @@ -182,6 +182,14 @@ Sys_Milliseconds timeval:tv_sec is an int: assuming this wraps every 0x7fffffff - ~68 years since the Epoch (1970) - we're safe till 2038 using unsigned long data type to work right with Sys_XTimeToSysTime */ + +#ifdef CLOCK_MONOTONIC_RAW +// use RAW monotonic clock if available (=> not subject to NTP etc) +#define D3_CLOCK_TO_USE CLOCK_MONOTONIC_RAW +#else +#define D3_CLOCK_TO_USE CLOCK_MONOTONIC +#endif + // RB: changed long to int unsigned int sys_timeBase = 0; // RB end @@ -192,23 +200,12 @@ unsigned int sys_timeBase = 0; */ int Sys_Milliseconds() { - // RB: clock_gettime should be a good replacement on Android - // because gettimeofday() seemed to cause a 64 bit emulation and performance penalty -#if defined(__ANDROID__) -#if 0 + // DG: use clock_gettime on all platforms +#if 1 int curtime; struct timespec ts; - clock_gettime( CLOCK_MONOTONIC, &ts ); - - curtime = ts.tv_sec * 1000 + ts.tv_nsec / 1000000; - - return curtime; -#else - int curtime; - struct timespec ts; - - clock_gettime( CLOCK_MONOTONIC, &ts ); + clock_gettime( D3_CLOCK_TO_USE, &ts ); if( !sys_timeBase ) { @@ -219,24 +216,25 @@ int Sys_Milliseconds() curtime = ( ts.tv_sec - sys_timeBase ) * 1000 + ts.tv_nsec / 1000000; return curtime; -#endif -// RB end #else + // gettimeofday() implementation int curtime; struct timeval tp; - + gettimeofday( &tp, NULL ); - + if( !sys_timeBase ) { sys_timeBase = tp.tv_sec; return tp.tv_usec / 1000; } - + curtime = ( tp.tv_sec - sys_timeBase ) * 1000 + tp.tv_usec / 1000; - + return curtime; + * / #endif + // DG end } // RB: added for BFG @@ -270,15 +268,15 @@ uint64 Sys_Microseconds() return curtime; #else - int curtime; + uint64 curtime; struct timespec ts; - clock_gettime( CLOCK_MONOTONIC, &ts ); + clock_gettime( D3_CLOCK_TO_USE, &ts ); if( !sys_microTimeBase ) { sys_microTimeBase = ts.tv_sec; - return ts.tv_nsec / 1000000; + return ts.tv_nsec / 1000; } curtime = ( ts.tv_sec - sys_microTimeBase ) * 1000000 + ts.tv_nsec / 1000;