1 /*****************************************************************************
2 * mtime.c: high resolution time management functions
3 * Functions are prototyped in vlc_mtime.h.
4 *****************************************************************************
5 * Copyright (C) 1998-2007 the VideoLAN team
6 * Copyright © 2006-2007 Rémi Denis-Courmont
9 * Authors: Vincent Seguin <seguin@via.ecp.fr>
10 * Rémi Denis-Courmont <rem$videolan,org>
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
26 *****************************************************************************/
28 /*****************************************************************************
30 *****************************************************************************/
36 #include <vlc_common.h>
38 #include <time.h> /* clock_gettime(), clock_nanosleep() */
43 # include <unistd.h> /* select() */
46 #ifdef HAVE_KERNEL_OS_H
47 # include <kernel/OS.h>
50 #if defined( WIN32 ) || defined( UNDER_CE )
52 # include <mmsystem.h>
55 #if defined(HAVE_SYS_TIME_H)
56 # include <sys/time.h>
59 #if defined(__APPLE__) && !defined(__powerpc__) && !defined(__ppc__) && !defined(__ppc64__)
60 #define USE_APPLE_MACH 1
61 # include <mach/mach.h>
62 # include <mach/mach_time.h>
65 #if !defined(HAVE_STRUCT_TIMESPEC)
73 #if defined(HAVE_NANOSLEEP) && !defined(HAVE_DECL_NANOSLEEP)
74 int nanosleep(struct timespec
*, struct timespec
*);
77 #if !defined (_POSIX_CLOCK_SELECTION)
78 # define _POSIX_CLOCK_SELECTION (-1)
81 # if (_POSIX_CLOCK_SELECTION < 0)
83 * We cannot use the monotonic clock if clock selection is not available,
84 * as it would screw vlc_cond_timedwait() completely. Instead, we have to
85 * stick to the realtime clock. Nevermind it screws everything up when ntpdate
86 * warps the wall clock.
88 # undef CLOCK_MONOTONIC
89 # define CLOCK_MONOTONIC CLOCK_REALTIME
90 #elif !defined (HAVE_CLOCK_NANOSLEEP)
91 /* Clock selection without clock in the first place, I don't think so. */
92 # error We have quite a situation here! Fix me if it ever happens.
96 * Return a date in a readable format
98 * This function converts a mtime date into a string.
99 * psz_buffer should be a buffer long enough to store the formatted
101 * \param date to be converted
102 * \param psz_buffer should be a buffer at least MSTRTIME_MAX_SIZE characters
103 * \return psz_buffer is returned so this can be used as printf parameter.
105 char *mstrtime( char *psz_buffer
, mtime_t date
)
107 static const mtime_t ll1000
= 1000, ll60
= 60, ll24
= 24;
109 snprintf( psz_buffer
, MSTRTIME_MAX_SIZE
, "%02d:%02d:%02d-%03d.%03d",
110 (int) (date
/ (ll1000
* ll1000
* ll60
* ll60
) % ll24
),
111 (int) (date
/ (ll1000
* ll1000
* ll60
) % ll60
),
112 (int) (date
/ (ll1000
* ll1000
) % ll60
),
113 (int) (date
/ ll1000
% ll1000
),
114 (int) (date
% ll1000
) );
115 return( psz_buffer
);
119 * Convert seconds to a time in the format h:mm:ss.
121 * This function is provided for any interface function which need to print a
122 * time string in the format h:mm:ss
124 * \param secs the date to be converted
125 * \param psz_buffer should be a buffer at least MSTRTIME_MAX_SIZE characters
126 * \return psz_buffer is returned so this can be used as printf parameter.
128 char *secstotimestr( char *psz_buffer
, int32_t i_seconds
)
130 if( unlikely(i_seconds
< 0) )
132 secstotimestr( psz_buffer
+ 1, -i_seconds
);
139 d
= div( i_seconds
, 60 );
141 d
= div( d
.quot
, 60 );
144 snprintf( psz_buffer
, MSTRTIME_MAX_SIZE
, "%u:%02u:%02u",
145 d
.quot
, d
.rem
, i_seconds
);
147 snprintf( psz_buffer
, MSTRTIME_MAX_SIZE
, "%02u:%02u",
152 #if defined (HAVE_CLOCK_NANOSLEEP)
153 static unsigned prec
= 0;
155 static void mprec_once( void )
158 if( clock_getres( CLOCK_MONOTONIC
, &ts
))
159 clock_getres( CLOCK_REALTIME
, &ts
);
161 prec
= ts
.tv_nsec
/ 1000;
166 * Return a value that is no bigger than the clock precision
169 static inline unsigned mprec( void )
171 #if defined (HAVE_CLOCK_NANOSLEEP)
172 static pthread_once_t once
= PTHREAD_ONCE_INIT
;
173 pthread_once( &once
, mprec_once
);
180 #ifdef USE_APPLE_MACH
181 static mach_timebase_info_data_t mtime_timebase_info
;
182 static pthread_once_t mtime_timebase_info_once
= PTHREAD_ONCE_INIT
;
183 static void mtime_init_timebase(void)
185 mach_timebase_info(&mtime_timebase_info
);
190 * Return high precision date
192 * Use a 1 MHz clock when possible, or 1 kHz
194 * Beware ! It doesn't reflect the actual date (since epoch), but can be the machine's uptime or anything (when monotonic clock is used)
196 mtime_t
mdate( void )
200 #if defined (HAVE_CLOCK_NANOSLEEP)
203 /* Try to use POSIX monotonic clock if available */
204 if( clock_gettime( CLOCK_MONOTONIC
, &ts
) == EINVAL
)
205 /* Run-time fallback to real-time clock (always available) */
206 (void)clock_gettime( CLOCK_REALTIME
, &ts
);
208 res
= ((mtime_t
)ts
.tv_sec
* (mtime_t
)1000000)
209 + (mtime_t
)(ts
.tv_nsec
/ 1000);
211 #elif defined( HAVE_KERNEL_OS_H )
212 res
= real_time_clock_usecs();
214 #elif defined( USE_APPLE_MACH )
215 pthread_once(&mtime_timebase_info_once
, mtime_init_timebase
);
216 uint64_t date
= mach_absolute_time();
218 /* Convert to nanoseconds */
219 date
*= mtime_timebase_info
.numer
;
220 date
/= mtime_timebase_info
.denom
;
222 /* Convert to microseconds */
224 #elif defined( WIN32 ) || defined( UNDER_CE )
225 /* We don't need the real date, just the value of a high precision timer */
226 static mtime_t freq
= INT64_C(-1);
228 if( freq
== INT64_C(-1) )
230 /* Extract from the Tcl source code:
231 * (http://www.cs.man.ac.uk/fellowsd-bin/TIP/7.html)
233 * Some hardware abstraction layers use the CPU clock
234 * in place of the real-time clock as a performance counter
235 * reference. This results in:
236 * - inconsistent results among the processors on
237 * multi-processor systems.
238 * - unpredictable changes in performance counter frequency
239 * on "gearshift" processors such as Transmeta and
241 * There seems to be no way to test whether the performance
242 * counter is reliable, but a useful heuristic is that
243 * if its frequency is 1.193182 MHz or 3.579545 MHz, it's
244 * derived from a colorburst crystal and is therefore
245 * the RTC rather than the TSC. If it's anything else, we
246 * presume that the performance counter is unreliable.
250 freq
= ( QueryPerformanceFrequency( &buf
) &&
251 (buf
.QuadPart
== INT64_C(1193182) || buf
.QuadPart
== INT64_C(3579545) ) )
255 /* on windows 2000, XP and Vista detect if there are two
256 cores there - that makes QueryPerformanceFrequency in
257 any case not trustable?
258 (may also be true, for single cores with adaptive
259 CPU frequency and active power management?)
261 HINSTANCE h_Kernel32
= LoadLibrary(_T("kernel32.dll"));
264 void WINAPI (*pf_GetSystemInfo
)(LPSYSTEM_INFO
);
265 pf_GetSystemInfo
= (void WINAPI (*)(LPSYSTEM_INFO
))
266 GetProcAddress(h_Kernel32
, _T("GetSystemInfo"));
269 SYSTEM_INFO system_info
;
270 pf_GetSystemInfo(&system_info
);
271 if(system_info
.dwNumberOfProcessors
> 1)
274 FreeLibrary(h_Kernel32
);
281 LARGE_INTEGER counter
;
282 QueryPerformanceCounter (&counter
);
284 /* Convert to from (1/freq) to microsecond resolution */
285 /* We need to split the division to avoid 63-bits overflow */
286 lldiv_t d
= lldiv (counter
.QuadPart
, freq
);
288 res
= (d
.quot
* 1000000) + ((d
.rem
* 1000000) / freq
);
292 /* Fallback on timeGetTime() which has a millisecond resolution
293 * (actually, best case is about 5 ms resolution)
294 * timeGetTime() only returns a DWORD thus will wrap after
295 * about 49.7 days so we try to detect the wrapping. */
297 static CRITICAL_SECTION date_lock
;
298 static mtime_t i_previous_time
= INT64_C(-1);
299 static int i_wrap_counts
= -1;
301 if( i_wrap_counts
== -1 )
305 i_previous_time
= INT64_C(1000) * timeGetTime();
307 i_previous_time
= INT64_C(1000) * GetTickCount();
309 InitializeCriticalSection( &date_lock
);
313 EnterCriticalSection( &date_lock
);
315 res
= INT64_C(1000) *
316 (i_wrap_counts
* INT64_C(0x100000000) + timeGetTime());
318 res
= INT64_C(1000) *
319 (i_wrap_counts
* INT64_C(0x100000000) + GetTickCount());
321 if( i_previous_time
> res
)
323 /* Counter wrapped */
325 res
+= INT64_C(0x100000000) * 1000;
327 i_previous_time
= res
;
328 LeaveCriticalSection( &date_lock
);
330 #elif defined(USE_APPLE_MACH)
331 /* The version that should be used, if it was cancelable */
332 pthread_once(&mtime_timebase_info_once
, mtime_init_timebase
);
333 uint64_t mach_time
= date
* 1000 * mtime_timebase_info
.denom
/ mtime_timebase_info
.numer
;
334 mach_wait_until(mach_time
);
337 struct timeval tv_date
;
339 /* gettimeofday() cannot fail given &tv_date is a valid address */
340 (void)gettimeofday( &tv_date
, NULL
);
341 res
= (mtime_t
) tv_date
.tv_sec
* 1000000 + (mtime_t
) tv_date
.tv_usec
;
351 * This function uses select() and an system date function to wake up at a
352 * precise date. It should be used for process synchronization. If current date
353 * is posterior to wished date, the function returns immediately.
354 * \param date The date to wake up at
356 void mwait( mtime_t date
)
358 /* If the deadline is already elapsed, or within the clock precision,
359 * do not even bother the system timer. */
362 #if defined (HAVE_CLOCK_NANOSLEEP)
363 lldiv_t d
= lldiv( date
, 1000000 );
364 struct timespec ts
= { d
.quot
, d
.rem
* 1000 };
367 while( ( val
= clock_nanosleep( CLOCK_MONOTONIC
, TIMER_ABSTIME
, &ts
,
371 ts
.tv_sec
= d
.quot
; ts
.tv_nsec
= d
.rem
* 1000;
372 while( clock_nanosleep( CLOCK_REALTIME
, 0, &ts
, NULL
) == EINTR
);
375 #elif defined (WIN32)
378 while( (i_total
= (date
- mdate())) > 0 )
380 const mtime_t i_sleep
= i_total
/ 1000;
381 DWORD i_delay
= (i_sleep
> 0x7fffffff) ? 0x7fffffff : i_sleep
;
383 SleepEx( i_delay
, TRUE
);
388 mtime_t delay
= date
- mdate();
396 #include "libvlc.h" /* vlc_backtrace() */
400 * Portable usleep(). Cancellation point.
402 * \param delay the amount of time to sleep
404 void msleep( mtime_t delay
)
406 #if defined( HAVE_CLOCK_NANOSLEEP )
407 lldiv_t d
= lldiv( delay
, 1000000 );
408 struct timespec ts
= { d
.quot
, d
.rem
* 1000 };
411 while( ( val
= clock_nanosleep( CLOCK_MONOTONIC
, 0, &ts
, &ts
) ) == EINTR
);
414 ts
.tv_sec
= d
.quot
; ts
.tv_nsec
= d
.rem
* 1000;
415 while( clock_nanosleep( CLOCK_REALTIME
, 0, &ts
, &ts
) == EINTR
);
418 #elif defined( HAVE_KERNEL_OS_H )
421 #elif defined( WIN32 ) || defined( UNDER_CE )
422 mwait (mdate () + delay
);
424 #elif defined( HAVE_NANOSLEEP )
425 struct timespec ts_delay
;
427 ts_delay
.tv_sec
= delay
/ 1000000;
428 ts_delay
.tv_nsec
= (delay
% 1000000) * 1000;
430 while( nanosleep( &ts_delay
, &ts_delay
) && ( errno
== EINTR
) );
432 #elif defined (USE_APPLE_MACH)
433 /* The version that should be used, if it was cancelable */
434 pthread_once(&mtime_timebase_info_once
, mtime_init_timebase
);
435 uint64_t mach_time
= delay
* 1000 * mtime_timebase_info
.denom
/ mtime_timebase_info
.numer
;
436 mach_wait_until(mach_time
+ mach_absolute_time());
439 struct timeval tv_delay
;
441 tv_delay
.tv_sec
= delay
/ 1000000;
442 tv_delay
.tv_usec
= delay
% 1000000;
444 /* If a signal is caught, you are screwed. Update your OS to nanosleep()
445 * or clock_nanosleep() if this is an issue. */
446 select( 0, NULL
, NULL
, NULL
, &tv_delay
);
451 * Date management (internal and external)
455 * Initialize a date_t.
457 * \param date to initialize
458 * \param divider (sample rate) numerator
459 * \param divider (sample rate) denominator
462 void date_Init( date_t
*p_date
, uint32_t i_divider_n
, uint32_t i_divider_d
)
465 p_date
->i_divider_num
= i_divider_n
;
466 p_date
->i_divider_den
= i_divider_d
;
467 p_date
->i_remainder
= 0;
473 * \param date to change
474 * \param divider (sample rate) numerator
475 * \param divider (sample rate) denominator
478 void date_Change( date_t
*p_date
, uint32_t i_divider_n
, uint32_t i_divider_d
)
480 /* change time scale of remainder */
481 p_date
->i_remainder
= p_date
->i_remainder
* i_divider_n
/ p_date
->i_divider_num
;
482 p_date
->i_divider_num
= i_divider_n
;
483 p_date
->i_divider_den
= i_divider_d
;
487 * Set the date value of a date_t.
492 void date_Set( date_t
*p_date
, mtime_t i_new_date
)
494 p_date
->date
= i_new_date
;
495 p_date
->i_remainder
= 0;
499 * Get the date of a date_t
504 mtime_t
date_Get( const date_t
*p_date
)
510 * Move forwards or backwards the date of a date_t.
512 * \param date to move
513 * \param difference value
515 void date_Move( date_t
*p_date
, mtime_t i_difference
)
517 p_date
->date
+= i_difference
;
521 * Increment the date and return the result, taking into account
524 * \param date to increment
525 * \param incrementation in number of samples
528 mtime_t
date_Increment( date_t
*p_date
, uint32_t i_nb_samples
)
530 mtime_t i_dividend
= (mtime_t
)i_nb_samples
* 1000000 * p_date
->i_divider_den
;
531 p_date
->date
+= i_dividend
/ p_date
->i_divider_num
;
532 p_date
->i_remainder
+= (int)(i_dividend
% p_date
->i_divider_num
);
534 if( p_date
->i_remainder
>= p_date
->i_divider_num
)
536 /* This is Bresenham algorithm. */
537 assert( p_date
->i_remainder
< 2*p_date
->i_divider_num
);
539 p_date
->i_remainder
-= p_date
->i_divider_num
;
546 * Decrement the date and return the result, taking into account
549 * \param date to decrement
550 * \param decrementation in number of samples
553 mtime_t
date_Decrement( date_t
*p_date
, uint32_t i_nb_samples
)
555 mtime_t i_dividend
= (mtime_t
)i_nb_samples
* 1000000 * p_date
->i_divider_den
;
556 p_date
->date
-= i_dividend
/ p_date
->i_divider_num
;
557 unsigned i_rem_adjust
= i_dividend
% p_date
->i_divider_num
;
559 if( p_date
->i_remainder
< i_rem_adjust
)
561 /* This is Bresenham algorithm. */
562 assert( p_date
->i_remainder
> -p_date
->i_divider_num
);
564 p_date
->i_remainder
+= p_date
->i_divider_num
;
567 p_date
->i_remainder
-= i_rem_adjust
;
572 #ifndef HAVE_GETTIMEOFDAY
577 * Number of micro-seconds between the beginning of the Windows epoch
578 * (Jan. 1, 1601) and the Unix epoch (Jan. 1, 1970).
580 * This assumes all Win32 compilers have 64-bit support.
582 #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS) || defined(__WATCOMC__)
583 # define DELTA_EPOCH_IN_USEC 11644473600000000Ui64
585 # define DELTA_EPOCH_IN_USEC 11644473600000000ULL
588 static uint64_t filetime_to_unix_epoch (const FILETIME
*ft
)
590 uint64_t res
= (uint64_t) ft
->dwHighDateTime
<< 32;
592 res
|= ft
->dwLowDateTime
;
593 res
/= 10; /* from 100 nano-sec periods to usec */
594 res
-= DELTA_EPOCH_IN_USEC
; /* from Win epoch to Unix epoch */
598 static int gettimeofday (struct timeval
*tv
, void *tz
)
606 GetSystemTimeAsFileTime (&ft
);
607 tim
= filetime_to_unix_epoch (&ft
);
608 tv
->tv_sec
= (long) (tim
/ 1000000L);
609 tv
->tv_usec
= (long) (tim
% 1000000L);
618 * @return NTP 64-bits timestamp in host byte order.
620 uint64_t NTPtime64 (void)
623 #if defined (CLOCK_REALTIME)
624 clock_gettime (CLOCK_REALTIME
, &ts
);
628 gettimeofday (&tv
, NULL
);
629 ts
.tv_sec
= tv
.tv_sec
;
630 ts
.tv_nsec
= tv
.tv_usec
* 1000;
634 /* Convert nanoseconds to 32-bits fraction (232 picosecond units) */
635 uint64_t t
= (uint64_t)(ts
.tv_nsec
) << 32;
639 /* There is 70 years (incl. 17 leap ones) offset to the Unix Epoch.
640 * No leap seconds during that period since they were not invented yet.
642 assert (t
< 0x100000000);
643 t
|= ((70LL * 365 + 17) * 24 * 60 * 60 + ts
.tv_sec
) << 32;