X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fmisc%2Fmtime.c;h=b85c7ef0e3cedca38b14d43142615b18a97f1fa4;hb=354f70c527ff183d34f0432b3611ef762fbc84b9;hp=96049e55a45e62c626a4e9ffe412209f3020af1f;hpb=19e9de434c48cd2dbea1ad3872c041daf0a26668;p=vlc diff --git a/src/misc/mtime.c b/src/misc/mtime.c index 96049e55a4..b85c7ef0e3 100644 --- a/src/misc/mtime.c +++ b/src/misc/mtime.c @@ -56,6 +56,12 @@ # 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 { @@ -74,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 @@ -119,25 +125,28 @@ char *mstrtime( char *psz_buffer, mtime_t date ) * \param psz_buffer should be a buffer at least MSTRTIME_MAX_SIZE characters * \return psz_buffer is returned so this can be used as printf parameter. */ -char *secstotimestr( char *psz_buffer, int i_seconds ) +char *secstotimestr( char *psz_buffer, int32_t i_seconds ) { - int i_hours, i_mins; - i_mins = i_seconds / 60; - i_hours = i_mins / 60 ; - if( i_hours ) + if( unlikely(i_seconds < 0) ) { - snprintf( psz_buffer, MSTRTIME_MAX_SIZE, "%d:%2.2d:%2.2d", - (int) i_hours, - (int) (i_mins % 60), - (int) (i_seconds % 60) ); + secstotimestr( psz_buffer + 1, -i_seconds ); + *psz_buffer = '-'; + return psz_buffer; } + + div_t d; + + d = div( i_seconds, 60 ); + i_seconds = d.rem; + d = div( d.quot, 60 ); + + if( d.quot ) + snprintf( psz_buffer, MSTRTIME_MAX_SIZE, "%u:%02u:%02u", + d.quot, d.rem, i_seconds ); else - { - snprintf( psz_buffer, MSTRTIME_MAX_SIZE, "%2.2d:%2.2d", - (int) i_mins , - (int) (i_seconds % 60) ); - } - return( psz_buffer ); + snprintf( psz_buffer, MSTRTIME_MAX_SIZE, "%02u:%02u", + d.rem, i_seconds ); + return psz_buffer; } #if defined (HAVE_CLOCK_NANOSLEEP) @@ -168,6 +177,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 * @@ -193,6 +211,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); @@ -299,6 +327,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; @@ -350,25 +384,6 @@ void mwait( mtime_t date ) } vlc_testcancel(); -#elif defined( __APPLE__ ) - /* Explicit hack: OSX does not cancel at nanosleep() */ - struct vlc_mutex_t lock; - struct vlc_cond_t wait; - - vlc_mutex_init (&lock); - vlc_cond_init (&wait); - vlc_mutex_lock (&lock); - - vlc_cleanup_push (vlc_mutex_destroy, &lock); - vlc_cleanup_push (vlc_cond_destroy, &wait); - vlc_cleanup_push (vlc_mutex_unlock, &lock); - - vlc_cond_timedwait (&wait, &lock, date); - - vlc_cleanup_run (); - vlc_cleanup_run (); - vlc_cleanup_run (); - #else mtime_t delay = date - mdate(); if( delay > 0 ) @@ -381,20 +396,6 @@ void mwait( mtime_t date ) #include "libvlc.h" /* vlc_backtrace() */ #undef msleep -#if defined(__APPLE__) && defined( HAVE_NANOSLEEP ) -/* Mac OS X 10.5's nanosleep is not a cancellation point */ -static inline int -semi_testcancelable_nanosleep(const struct timespec *rqtp, struct timespec *rmtp) -{ - int ret; - pthread_testcancel(); - ret = nanosleep(rqtp, rmtp); - pthread_testcancel(); - return ret; -} -#define nanosleep semi_testcancelable_nanosleep -#endif - /** * Portable usleep(). Cancellation point. * @@ -417,7 +418,7 @@ void msleep( mtime_t delay ) #elif defined( HAVE_KERNEL_OS_H ) snooze( delay ); -#elif defined( WIN32 ) || defined( UNDER_CE ) || defined( __APPLE__ ) +#elif defined( WIN32 ) || defined( UNDER_CE ) mwait (mdate () + delay); #elif defined( HAVE_NANOSLEEP ) @@ -428,6 +429,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; @@ -535,6 +542,33 @@ mtime_t date_Increment( date_t *p_date, uint32_t i_nb_samples ) 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