- {
- /* 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. */
-
- static CRITICAL_SECTION date_lock;
- static mtime_t i_previous_time = INT64_C(-1);
- static int i_wrap_counts = -1;
-
- if( i_wrap_counts == -1 )
- {
- /* Initialization */
-#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 );
-#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 += INT64_C(0x100000000) * 1000;
- }
- i_previous_time = res;
- LeaveCriticalSection( &date_lock );
- }
-#else
- struct timeval tv_date;
-
- /* gettimeofday() cannot fail given &tv_date is a valid address */
- (void)gettimeofday( &tv_date, NULL );
- res = (mtime_t) tv_date.tv_sec * 1000000 + (mtime_t) tv_date.tv_usec;
-#endif
-
- return res;
-}
-
-/**
- * Wait for a date
- *
- * This function uses select() and an system date function to wake up at a
- * precise date. It should be used for process synchronization. If current date
- * is posterior to wished date, the function returns immediately.
- * \param date The date to wake up at
- */
-void mwait( mtime_t date )
-{
- /* If the deadline is already elapsed, or within the clock precision,
- * do not even bother the system timer. */
- date -= mprec();
-
-#if defined (HAVE_CLOCK_NANOSLEEP)
- lldiv_t d = lldiv( date, 1000000 );
- struct timespec ts = { d.quot, d.rem * 1000 };
-
- int val;
- while( ( val = clock_nanosleep( CLOCK_MONOTONIC, TIMER_ABSTIME, &ts,
- NULL ) ) == EINTR );
- if( val == EINVAL )
- {
- ts.tv_sec = d.quot; ts.tv_nsec = d.rem * 1000;
- while( clock_nanosleep( CLOCK_REALTIME, 0, &ts, NULL ) == EINTR );
- }
-
-#elif defined (WIN32)
- mtime_t total;
-
- while ((total = (date - mdate ())) > 0)
- {
- DWORD delay = (total > 0x7fffffff) ? 0x7fffffff : total;
- vlc_testcancel ();
- SleepEx (delay, TRUE);
- }
- vlc_testcancel ();
-
-#else
- mtime_t delay = date - mdate();
- if( delay > 0 )
- msleep( delay );
-
-#endif
-}
-
-/**
- * Portable usleep(). Cancellation point.
- *
- * \param delay the amount of time to sleep
- */
-void msleep( mtime_t delay )
-{
-#if defined( HAVE_CLOCK_NANOSLEEP )
- lldiv_t d = lldiv( delay, 1000000 );
- struct timespec ts = { d.quot, d.rem * 1000 };
-
- int val;
- while( ( val = clock_nanosleep( CLOCK_MONOTONIC, 0, &ts, &ts ) ) == EINTR );
- if( val == EINVAL )
- {
- ts.tv_sec = d.quot; ts.tv_nsec = d.rem * 1000;
- while( clock_nanosleep( CLOCK_REALTIME, 0, &ts, &ts ) == EINTR );
- }
-
-#elif defined( HAVE_KERNEL_OS_H )
- snooze( delay );
-
-#elif defined( WIN32 ) || defined( UNDER_CE )
- mwait (mdate () + delay);
-
-#elif defined( HAVE_NANOSLEEP )
- struct timespec ts_delay;
-
- ts_delay.tv_sec = delay / 1000000;
- ts_delay.tv_nsec = (delay % 1000000) * 1000;
-
- while( nanosleep( &ts_delay, &ts_delay ) && ( errno == EINTR ) );
-
-#else
- struct timeval tv_delay;
-
- tv_delay.tv_sec = delay / 1000000;
- tv_delay.tv_usec = delay % 1000000;
-
- /* If a signal is caught, you are screwed. Update your OS to nanosleep()
- * or clock_nanosleep() if this is an issue. */
- select( 0, NULL, NULL, NULL, &tv_delay );
-#endif