X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fmisc%2Fmtime.c;h=454e99fb27a5ac3b415d92ab98d2f39245dbea2b;hb=10f105d2bfe55fff1f735af7d4a0ee545bb21120;hp=b25f1a5f77c9ff67ee9381201c5611e9a7e1557d;hpb=665a5b28ae3e50d725fdd6e903c6af8b9440a5c7;p=vlc diff --git a/src/misc/mtime.c b/src/misc/mtime.c index b25f1a5f77..454e99fb27 100644 --- a/src/misc/mtime.c +++ b/src/misc/mtime.c @@ -33,7 +33,7 @@ # include "config.h" #endif -#include +#include #include /* clock_gettime(), clock_nanosleep() */ #include @@ -52,14 +52,16 @@ # include #endif -#if defined( UNDER_CE ) -# include -#endif - #if defined(HAVE_SYS_TIME_H) # include #endif +#if defined(__APPLE__) && !defined(__powerpc__) && !defined(__ppc__) && !defined(__ppc64__) +#define USE_APPLE_MACH 1 +# include +# include +#endif + #if !defined(HAVE_STRUCT_TIMESPEC) struct timespec { @@ -78,9 +80,9 @@ int nanosleep(struct timespec *, struct timespec *); # if (_POSIX_CLOCK_SELECTION < 0) /* - * We cannot use the monotonic clock is clock selection is not available, + * We cannot use the monotonic clock if 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 + * stick to the realtime clock. Nevermind it screws everything up when ntpdate * warps the wall clock. */ # undef CLOCK_MONOTONIC @@ -102,7 +104,7 @@ int nanosleep(struct timespec *, struct timespec *); */ char *mstrtime( char *psz_buffer, mtime_t date ) { - static mtime_t ll1000 = 1000, ll60 = 60, ll24 = 24; + static const mtime_t ll1000 = 1000, ll60 = 60, ll24 = 24; snprintf( psz_buffer, MSTRTIME_MAX_SIZE, "%02d:%02d:%02d-%03d.%03d", (int) (date / (ll1000 * ll1000 * ll60 * ll60) % ll24), @@ -172,6 +174,15 @@ static inline unsigned mprec( void ) #endif } +#ifdef USE_APPLE_MACH +static mach_timebase_info_data_t mtime_timebase_info; +static pthread_once_t mtime_timebase_info_once = PTHREAD_ONCE_INIT; +static void mtime_init_timebase(void) +{ + mach_timebase_info(&mtime_timebase_info); +} +#endif + /** * Return high precision date * @@ -197,6 +208,16 @@ mtime_t mdate( void ) #elif defined( HAVE_KERNEL_OS_H ) res = real_time_clock_usecs(); +#elif defined( USE_APPLE_MACH ) + pthread_once(&mtime_timebase_info_once, mtime_init_timebase); + uint64_t date = mach_absolute_time(); + + /* Convert to nanoseconds */ + date *= mtime_timebase_info.numer; + date /= mtime_timebase_info.denom; + + /* Convert to microseconds */ + res = date / 1000; #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 = INT64_C(-1); @@ -265,7 +286,7 @@ mtime_t mdate( void ) } else { - /* Fallback on timeGetTime() which has a milisecond resolution + /* Fallback on timeGetTime() which has a millisecond 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. */ @@ -303,6 +324,12 @@ mtime_t mdate( void ) i_previous_time = res; LeaveCriticalSection( &date_lock ); } +#elif defined(USE_APPLE_MACH) + /* The version that should be used, if it was cancelable */ + pthread_once(&mtime_timebase_info_once, mtime_init_timebase); + uint64_t mach_time = date * 1000 * mtime_timebase_info.denom / mtime_timebase_info.numer; + mach_wait_until(mach_time); + #else struct timeval tv_date; @@ -314,6 +341,7 @@ mtime_t mdate( void ) return res; } +#undef mwait /** * Wait for a date * @@ -340,8 +368,20 @@ void mwait( mtime_t date ) ts.tv_sec = d.quot; ts.tv_nsec = d.rem * 1000; while( clock_nanosleep( CLOCK_REALTIME, 0, &ts, NULL ) == EINTR ); } -#else +#elif defined (WIN32) + mtime_t i_total; + + while( (i_total = (date - mdate())) > 0 ) + { + const mtime_t i_sleep = i_total / 1000; + DWORD i_delay = (i_sleep > 0x7fffffff) ? 0x7fffffff : i_sleep; + vlc_testcancel(); + SleepEx( i_delay, TRUE ); + } + vlc_testcancel(); + +#else mtime_t delay = date - mdate(); if( delay > 0 ) msleep( delay ); @@ -349,10 +389,13 @@ void mwait( mtime_t date ) #endif } + +#include "libvlc.h" /* vlc_backtrace() */ +#undef msleep + /** - * More precise sleep() + * Portable usleep(). Cancellation point. * - * Portable usleep() function. * \param delay the amount of time to sleep */ void msleep( mtime_t delay ) @@ -373,7 +416,7 @@ void msleep( mtime_t delay ) snooze( delay ); #elif defined( WIN32 ) || defined( UNDER_CE ) - Sleep( (DWORD) (delay / 1000) ); + mwait (mdate () + delay); #elif defined( HAVE_NANOSLEEP ) struct timespec ts_delay; @@ -383,6 +426,12 @@ void msleep( mtime_t delay ) while( nanosleep( &ts_delay, &ts_delay ) && ( errno == EINTR ) ); +#elif defined (USE_APPLE_MACH) + /* The version that should be used, if it was cancelable */ + pthread_once(&mtime_timebase_info_once, mtime_init_timebase); + uint64_t mach_time = delay * 1000 * mtime_timebase_info.denom / mtime_timebase_info.numer; + mach_wait_until(mach_time + mach_absolute_time()); + #else struct timeval tv_delay; @@ -425,6 +474,8 @@ void date_Init( date_t *p_date, uint32_t i_divider_n, uint32_t i_divider_d ) void date_Change( date_t *p_date, uint32_t i_divider_n, uint32_t i_divider_d ) { + /* change time scale of remainder */ + p_date->i_remainder = p_date->i_remainder * i_divider_n / p_date->i_divider_num; p_date->i_divider_num = i_divider_n; p_date->i_divider_den = i_divider_d; } @@ -473,20 +524,48 @@ void date_Move( date_t *p_date, mtime_t i_difference ) */ mtime_t date_Increment( date_t *p_date, uint32_t i_nb_samples ) { - mtime_t i_dividend = (mtime_t)i_nb_samples * 1000000; - p_date->date += i_dividend / p_date->i_divider_num * p_date->i_divider_den; + mtime_t i_dividend = (mtime_t)i_nb_samples * 1000000 * p_date->i_divider_den; + p_date->date += i_dividend / p_date->i_divider_num; p_date->i_remainder += (int)(i_dividend % p_date->i_divider_num); if( p_date->i_remainder >= p_date->i_divider_num ) { /* This is Bresenham algorithm. */ - p_date->date += p_date->i_divider_den; + assert( p_date->i_remainder < 2*p_date->i_divider_num); + p_date->date += 1; p_date->i_remainder -= p_date->i_divider_num; } return p_date->date; } +/** + * Decrement the date and return the result, taking into account + * rounding errors. + * + * \param date to decrement + * \param decrementation in number of samples + * \return date value + */ +mtime_t date_Decrement( date_t *p_date, uint32_t i_nb_samples ) +{ + mtime_t i_dividend = (mtime_t)i_nb_samples * 1000000 * p_date->i_divider_den; + p_date->date -= i_dividend / p_date->i_divider_num; + unsigned i_rem_adjust = i_dividend % p_date->i_divider_num; + + if( p_date->i_remainder < i_rem_adjust ) + { + /* This is Bresenham algorithm. */ + assert( p_date->i_remainder > -p_date->i_divider_num); + p_date->date -= 1; + p_date->i_remainder += p_date->i_divider_num; + } + + p_date->i_remainder -= i_rem_adjust; + + return p_date->date; +} + #ifndef HAVE_GETTIMEOFDAY #ifdef WIN32