X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fmisc%2Fmtime.c;h=9966e473bec8f5a046fcf1b92ccbb132331bba48;hb=62dd14548820fb0966e6b90d586183f74a427e4b;hp=094556289404b7b831b0ba793e36f8339bb6671b;hpb=6ee1e193fd896ab9a4729fde14f009d9ce629815;p=vlc diff --git a/src/misc/mtime.c b/src/misc/mtime.c index 0945562894..9966e473be 100644 --- a/src/misc/mtime.c +++ b/src/misc/mtime.c @@ -29,17 +29,16 @@ * Preamble *****************************************************************************/ -#include +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include #include /* clock_gettime(), clock_nanosleep() */ #include #include - -#if defined( PTH_INIT_IN_PTH_H ) /* GNU Pth */ -# include -#endif - #ifdef HAVE_UNISTD_H # include /* select() */ #endif @@ -50,7 +49,13 @@ #if defined( WIN32 ) || defined( UNDER_CE ) # include +# include +#endif + +#if defined( UNDER_CE ) +# include #endif + #if defined(HAVE_SYS_TIME_H) # include #endif @@ -67,6 +72,24 @@ struct timespec int nanosleep(struct timespec *, struct timespec *); #endif +#if !defined (_POSIX_CLOCK_SELECTION) +# define _POSIX_CLOCK_SELECTION (-1) +#endif + +# if (_POSIX_CLOCK_SELECTION < 0) +/* + * We cannot use the monotonic clock is clock selection is not available, + * as it would screw vlc_cond_timedwait() completely. Instead, we have to + * stick to the realtime clock. Nevermind it screws everything when ntpdate + * warps the wall clock. + */ +# undef CLOCK_MONOTONIC +# define CLOCK_MONOTONIC CLOCK_REALTIME +#elif !defined (HAVE_CLOCK_NANOSLEEP) +/* Clock selection without clock in the first place, I don't think so. */ +# error We have quite a situation here! Fix me if it ever happens. +#endif + /** * Return a date in a readable format * @@ -102,13 +125,38 @@ char *mstrtime( char *psz_buffer, mtime_t date ) */ char *secstotimestr( char *psz_buffer, int i_seconds ) { - snprintf( psz_buffer, MSTRTIME_MAX_SIZE, "%d:%2.2d:%2.2d", - (int) (i_seconds / (60 *60)), - (int) ((i_seconds / 60) % 60), - (int) (i_seconds % 60) ); + int i_hours, i_mins; + i_mins = i_seconds / 60; + i_hours = i_mins / 60 ; + if( i_hours ) + { + snprintf( psz_buffer, MSTRTIME_MAX_SIZE, "%d:%2.2d:%2.2d", + (int) i_hours, + (int) (i_mins % 60), + (int) (i_seconds % 60) ); + } + else + { + snprintf( psz_buffer, MSTRTIME_MAX_SIZE, "%2.2d:%2.2d", + (int) i_mins , + (int) (i_seconds % 60) ); + } return( psz_buffer ); } +#if defined (HAVE_CLOCK_NANOSLEEP) +static unsigned prec = 0; + +static void mprec_once( void ) +{ + struct timespec ts; + if( clock_getres( CLOCK_MONOTONIC, &ts )) + clock_getres( CLOCK_REALTIME, &ts ); + + prec = ts.tv_nsec / 1000; +} +#endif + /** * Return a value that is no bigger than the clock precision * (possibly zero). @@ -116,28 +164,20 @@ char *secstotimestr( char *psz_buffer, int i_seconds ) static inline unsigned mprec( void ) { #if defined (HAVE_CLOCK_NANOSLEEP) - struct timespec ts; - if( clock_getres( CLOCK_MONOTONIC, &ts )) - clock_getres( CLOCK_REALTIME, &ts ); - - return ts.tv_nsec / 1000; -#endif + static pthread_once_t once = PTHREAD_ONCE_INIT; + pthread_once( &once, mprec_once ); + return prec; +#else return 0; -} - -static unsigned prec = 0; -static volatile mtime_t cached_time = 0; -#if defined( HAVE_CLOCK_NANOSLEEP ) -# if (_POSIX_MONOTONIC_CLOCK - 0 < 0) -# define CLOCK_MONOTONIC CLOCK_REALTIME -# endif #endif +} /** * Return high precision date * - * Uses the gettimeofday() function when possible (1 MHz resolution) or the - * ftime() function (1 kHz resolution). + * Use a 1 MHz clock when possible, or 1 kHz + * + * Beware ! It doesn't reflect the actual date (since epoch), but can be the machine's uptime or anything (when monotonic clock is used) */ mtime_t mdate( void ) { @@ -159,9 +199,9 @@ mtime_t mdate( void ) #elif defined( WIN32 ) || defined( UNDER_CE ) /* We don't need the real date, just the value of a high precision timer */ - static mtime_t freq = I64C(-1); + static mtime_t freq = INT64_C(-1); - if( freq == I64C(-1) ) + if( freq == INT64_C(-1) ) { /* Extract from the Tcl source code: * (http://www.cs.man.ac.uk/fellowsd-bin/TIP/7.html) @@ -184,8 +224,32 @@ mtime_t mdate( void ) LARGE_INTEGER buf; freq = ( QueryPerformanceFrequency( &buf ) && - (buf.QuadPart == I64C(1193182) || buf.QuadPart == I64C(3579545) ) ) + (buf.QuadPart == INT64_C(1193182) || buf.QuadPart == INT64_C(3579545) ) ) ? buf.QuadPart : 0; + +#if defined( WIN32 ) + /* on windows 2000, XP and Vista detect if there are two + cores there - that makes QueryPerformanceFrequency in + any case not trustable? + (may also be true, for single cores with adaptive + CPU frequency and active power management?) + */ + HINSTANCE h_Kernel32 = LoadLibrary(_T("kernel32.dll")); + if(h_Kernel32) + { + void WINAPI (*pf_GetSystemInfo)(LPSYSTEM_INFO); + pf_GetSystemInfo = (void WINAPI (*)(LPSYSTEM_INFO)) + GetProcAddress(h_Kernel32, _T("GetSystemInfo")); + if(pf_GetSystemInfo) + { + SYSTEM_INFO system_info; + pf_GetSystemInfo(&system_info); + if(system_info.dwNumberOfProcessors > 1) + freq = 0; + } + FreeLibrary(h_Kernel32); + } +#endif } if( freq != 0 ) @@ -201,31 +265,40 @@ mtime_t mdate( void ) } else { - /* Fallback on GetTickCount() which has a milisecond resolution - * (actually, best case is about 10 ms resolution) - * GetTickCount() only returns a DWORD thus will wrap after + /* Fallback on timeGetTime() which has a milisecond resolution + * (actually, best case is about 5 ms resolution) + * timeGetTime() only returns a DWORD thus will wrap after * about 49.7 days so we try to detect the wrapping. */ static CRITICAL_SECTION date_lock; - static mtime_t i_previous_time = I64C(-1); + static mtime_t i_previous_time = INT64_C(-1); static int i_wrap_counts = -1; if( i_wrap_counts == -1 ) { /* Initialization */ - i_previous_time = I64C(1000) * GetTickCount(); +#if defined( WIN32 ) + i_previous_time = INT64_C(1000) * timeGetTime(); +#else + i_previous_time = INT64_C(1000) * GetTickCount(); +#endif InitializeCriticalSection( &date_lock ); i_wrap_counts = 0; } EnterCriticalSection( &date_lock ); - res = I64C(1000) * - (i_wrap_counts * I64C(0x100000000) + GetTickCount()); +#if defined( WIN32 ) + res = INT64_C(1000) * + (i_wrap_counts * INT64_C(0x100000000) + timeGetTime()); +#else + res = INT64_C(1000) * + (i_wrap_counts * INT64_C(0x100000000) + GetTickCount()); +#endif if( i_previous_time > res ) { /* Counter wrapped */ i_wrap_counts++; - res += I64C(0x100000000) * 1000; + res += INT64_C(0x100000000) * 1000; } i_previous_time = res; LeaveCriticalSection( &date_lock ); @@ -238,7 +311,7 @@ mtime_t mdate( void ) res = (mtime_t) tv_date.tv_sec * 1000000 + (mtime_t) tv_date.tv_usec; #endif - return cached_time = res; + return res; } /** @@ -251,15 +324,11 @@ mtime_t mdate( void ) */ void mwait( mtime_t date ) { - if( prec == 0 ) - prec = mprec(); - /* If the deadline is already elapsed, or within the clock precision, - * do not even bother the clock. */ - if( ( date - cached_time ) < (mtime_t)prec ) // OK: mtime_t is signed - return; + * do not even bother the system timer. */ + date -= mprec(); -#if 0 && defined (HAVE_CLOCK_NANOSLEEP) +#if defined (HAVE_CLOCK_NANOSLEEP) lldiv_t d = lldiv( date, 1000000 ); struct timespec ts = { d.quot, d.rem * 1000 }; @@ -288,8 +357,6 @@ void mwait( mtime_t date ) */ void msleep( mtime_t delay ) { - mtime_t earlier = cached_time; - #if defined( HAVE_CLOCK_NANOSLEEP ) lldiv_t d = lldiv( delay, 1000000 ); struct timespec ts = { d.quot, d.rem * 1000 }; @@ -305,14 +372,8 @@ void msleep( mtime_t delay ) #elif defined( HAVE_KERNEL_OS_H ) snooze( delay ); -#elif defined( PTH_INIT_IN_PTH_H ) - pth_usleep( delay ); - -#elif defined( ST_INIT_IN_ST_H ) - st_usleep( delay ); - #elif defined( WIN32 ) || defined( UNDER_CE ) - Sleep( (int) (delay / 1000) ); + Sleep( (DWORD) (delay / 1000) ); #elif defined( HAVE_NANOSLEEP ) struct timespec ts_delay; @@ -332,10 +393,6 @@ void msleep( mtime_t delay ) * or clock_nanosleep() if this is an issue. */ select( 0, NULL, NULL, NULL, &tv_delay ); #endif - - earlier += delay; - if( cached_time < earlier ) - cached_time = earlier; } /*