X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fmisc%2Fmtime.c;h=a0c24e8e39d84d6169f4bc9d89a453e29add6764;hb=26c0d12f9a06670adcb7081245aaf8e94b3e3cbf;hp=5ab08c5e89a7487e227e50337369f49b153c51ca;hpb=1a0832b256f9ffcf9229ae6a3fc056848140a266;p=vlc diff --git a/src/misc/mtime.c b/src/misc/mtime.c index 5ab08c5e89..a0c24e8e39 100644 --- a/src/misc/mtime.c +++ b/src/misc/mtime.c @@ -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 { @@ -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,11 @@ mtime_t mdate( void ) i_previous_time = res; LeaveCriticalSection( &date_lock ); } +#elif 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 +340,7 @@ mtime_t mdate( void ) return res; } +#undef mwait /** * Wait for a date * @@ -340,8 +367,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 +388,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,9 +415,7 @@ void msleep( mtime_t delay ) snooze( delay ); #elif defined( WIN32 ) || defined( UNDER_CE ) - for (delay /= 1000; delay > 0x7fffffff; delay -= 0x7fffffff) - Sleep (0x7fffffff); - Sleep (delay); + mwait (mdate () + delay); #elif defined( HAVE_NANOSLEEP ) struct timespec ts_delay; @@ -385,6 +425,11 @@ void msleep( mtime_t delay ) while( nanosleep( &ts_delay, &ts_delay ) && ( errno == EINTR ) ); +#elif 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; @@ -427,6 +472,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; } @@ -475,20 +522,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