]> git.sesse.net Git - vlc/blob - src/misc/mtime.c
Cache system clock in userland to save a few avoidable sleeps.
[vlc] / src / misc / mtime.c
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
7  * $Id$
8  *
9  * Authors: Vincent Seguin <seguin@via.ecp.fr>
10  *          Rémi Denis-Courmont <rem$videolan,org>
11  *          Gisle Vanem
12  *
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.
17  *
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.
22  *
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  *****************************************************************************/
27
28 /*****************************************************************************
29  * Preamble
30  *****************************************************************************/
31
32 #include <vlc/vlc.h>
33
34 #include <stdio.h>                                              /* sprintf() */
35 #include <time.h>                      /* clock_gettime(), clock_nanosleep() */
36 #include <stdlib.h>                                               /* lldiv() */
37 #include <assert.h>
38
39
40 #if defined( PTH_INIT_IN_PTH_H )                                  /* GNU Pth */
41 #   include <pth.h>
42 #endif
43
44 #ifdef HAVE_UNISTD_H
45 #   include <unistd.h>                                           /* select() */
46 #endif
47
48 #ifdef HAVE_KERNEL_OS_H
49 #   include <kernel/OS.h>
50 #endif
51
52 #if defined( WIN32 ) || defined( UNDER_CE )
53 #   include <windows.h>
54 #endif
55 #if defined(HAVE_SYS_TIME_H)
56 #   include <sys/time.h>
57 #endif
58
59 #if !defined(HAVE_STRUCT_TIMESPEC)
60 struct timespec
61 {
62     time_t  tv_sec;
63     int32_t tv_nsec;
64 };
65 #endif
66
67 #if defined(HAVE_NANOSLEEP) && !defined(HAVE_DECL_NANOSLEEP)
68 int nanosleep(struct timespec *, struct timespec *);
69 #endif
70
71 /**
72  * Return a date in a readable format
73  *
74  * This function converts a mtime date into a string.
75  * psz_buffer should be a buffer long enough to store the formatted
76  * date.
77  * \param date to be converted
78  * \param psz_buffer should be a buffer at least MSTRTIME_MAX_SIZE characters
79  * \return psz_buffer is returned so this can be used as printf parameter.
80  */
81 char *mstrtime( char *psz_buffer, mtime_t date )
82 {
83     static mtime_t ll1000 = 1000, ll60 = 60, ll24 = 24;
84
85     snprintf( psz_buffer, MSTRTIME_MAX_SIZE, "%02d:%02d:%02d-%03d.%03d",
86              (int) (date / (ll1000 * ll1000 * ll60 * ll60) % ll24),
87              (int) (date / (ll1000 * ll1000 * ll60) % ll60),
88              (int) (date / (ll1000 * ll1000) % ll60),
89              (int) (date / ll1000 % ll1000),
90              (int) (date % ll1000) );
91     return( psz_buffer );
92 }
93
94 /**
95  * Convert seconds to a time in the format h:mm:ss.
96  *
97  * This function is provided for any interface function which need to print a
98  * time string in the format h:mm:ss
99  * date.
100  * \param secs  the date to be converted
101  * \param psz_buffer should be a buffer at least MSTRTIME_MAX_SIZE characters
102  * \return psz_buffer is returned so this can be used as printf parameter.
103  */
104 char *secstotimestr( char *psz_buffer, int i_seconds )
105 {
106     snprintf( psz_buffer, MSTRTIME_MAX_SIZE, "%d:%2.2d:%2.2d",
107               (int) (i_seconds / (60 *60)),
108               (int) ((i_seconds / 60) % 60),
109               (int) (i_seconds % 60) );
110     return( psz_buffer );
111 }
112
113 /**
114  * Return a value that is no bigger than the clock precision
115  * (possibly zero).
116  */
117 static inline unsigned mprec( void )
118 {
119 #if defined (HAVE_CLOCK_NANOSLEEP)
120     struct timespec ts;
121     if( clock_getres( CLOCK_MONOTONIC, &ts ))
122         clock_getres( CLOCK_REALTIME, &ts );
123
124     return ts.tv_nsec / 1000;
125 #endif
126     return 0;
127 }
128
129 static unsigned prec = 0;
130 static volatile mtime_t cached_time = 0;
131
132 /**
133  * Return high precision date
134  *
135  * Uses the gettimeofday() function when possible (1 MHz resolution) or the
136  * ftime() function (1 kHz resolution).
137  */
138 mtime_t mdate( void )
139 {
140     mtime_t res;
141
142 #if defined (HAVE_CLOCK_NANOSLEEP)
143     struct timespec ts;
144
145 # if (_POSIX_MONOTONIC_CLOCK - 0 >= 0)
146     /* Try to use POSIX monotonic clock if available */
147     if( clock_gettime( CLOCK_MONOTONIC, &ts ) )
148 # endif
149         /* Run-time fallback to real-time clock (always available) */
150         (void)clock_gettime( CLOCK_REALTIME, &ts );
151
152     res = ((mtime_t)ts.tv_sec * (mtime_t)1000000)
153            + (mtime_t)(ts.tv_nsec / 1000);
154
155 #elif defined( HAVE_KERNEL_OS_H )
156     res = real_time_clock_usecs();
157
158 #elif defined( WIN32 ) || defined( UNDER_CE )
159     /* We don't need the real date, just the value of a high precision timer */
160     static mtime_t freq = I64C(-1);
161
162     if( freq == I64C(-1) )
163     {
164         /* Extract from the Tcl source code:
165          * (http://www.cs.man.ac.uk/fellowsd-bin/TIP/7.html)
166          *
167          * Some hardware abstraction layers use the CPU clock
168          * in place of the real-time clock as a performance counter
169          * reference.  This results in:
170          *    - inconsistent results among the processors on
171          *      multi-processor systems.
172          *    - unpredictable changes in performance counter frequency
173          *      on "gearshift" processors such as Transmeta and
174          *      SpeedStep.
175          * There seems to be no way to test whether the performance
176          * counter is reliable, but a useful heuristic is that
177          * if its frequency is 1.193182 MHz or 3.579545 MHz, it's
178          * derived from a colorburst crystal and is therefore
179          * the RTC rather than the TSC.  If it's anything else, we
180          * presume that the performance counter is unreliable.
181          */
182         LARGE_INTEGER buf;
183
184         freq = ( QueryPerformanceFrequency( &buf ) &&
185                  (buf.QuadPart == I64C(1193182) || buf.QuadPart == I64C(3579545) ) )
186                ? buf.QuadPart : 0;
187     }
188
189     if( freq != 0 )
190     {
191         LARGE_INTEGER counter;
192         QueryPerformanceCounter (&counter);
193
194         /* Convert to from (1/freq) to microsecond resolution */
195         /* We need to split the division to avoid 63-bits overflow */
196         lldiv_t d = lldiv (counter.QuadPart, freq);
197
198         res = (d.quot * 1000000) + ((d.rem * 1000000) / freq);
199     }
200     else
201     {
202         /* Fallback on GetTickCount() which has a milisecond resolution
203          * (actually, best case is about 10 ms resolution)
204          * GetTickCount() only returns a DWORD thus will wrap after
205          * about 49.7 days so we try to detect the wrapping. */
206
207         static CRITICAL_SECTION date_lock;
208         static mtime_t i_previous_time = I64C(-1);
209         static int i_wrap_counts = -1;
210
211         if( i_wrap_counts == -1 )
212         {
213             /* Initialization */
214             i_previous_time = I64C(1000) * GetTickCount();
215             InitializeCriticalSection( &date_lock );
216             i_wrap_counts = 0;
217         }
218
219         EnterCriticalSection( &date_lock );
220         res = I64C(1000) *
221             (i_wrap_counts * I64C(0x100000000) + GetTickCount());
222         if( i_previous_time > res )
223         {
224             /* Counter wrapped */
225             i_wrap_counts++;
226             usec_time += I64C(0x100000000) * 1000;
227         }
228         i_previous_time = usec_time;
229         LeaveCriticalSection( &date_lock );
230     }
231 #else
232     struct timeval tv_date;
233
234     /* gettimeofday() cannot fail given &tv_date is a valid address */
235     (void)gettimeofday( &tv_date, NULL );
236     res = (mtime_t) tv_date.tv_sec * 1000000 + (mtime_t) tv_date.tv_usec;
237 #endif
238
239     return cached_time = res;
240 }
241
242 /**
243  * Wait for a date
244  *
245  * This function uses select() and an system date function to wake up at a
246  * precise date. It should be used for process synchronization. If current date
247  * is posterior to wished date, the function returns immediately.
248  * \param date The date to wake up at
249  */
250 void mwait( mtime_t date )
251 {
252     if( prec == 0 )
253         prec = mprec();
254
255     /* If the deadline is already elapsed, or within the clock precision,
256      * do not even bother the clock. */
257     if( ( date - cached_time ) < (mtime_t)prec ) // OK: mtime_t is signed
258         return;
259
260 #if 0 && defined (HAVE_CLOCK_NANOSLEEP)
261     lldiv_t d = lldiv( date, 1000000 );
262     struct timespec ts = { d.quot, d.rem * 1000 };
263
264 # if (_POSIX_MONOTONIC_CLOCK - 0 >= 0)
265     if( clock_nanosleep( CLOCK_MONOTONIC, TIMER_ABSTIME, &ts, NULL ) )
266 # endif
267         clock_nanosleep( CLOCK_REALTIME, TIMER_ABSTIME, &ts, NULL );
268 #else
269
270     mtime_t delay = date - mdate();
271     if( delay > 0 )
272         msleep( delay );
273
274 #endif
275 }
276
277 /**
278  * More precise sleep()
279  *
280  * Portable usleep() function.
281  * \param delay the amount of time to sleep
282  */
283 void msleep( mtime_t delay )
284 {
285     mtime_t earlier = cached_time;
286
287 #if defined( HAVE_CLOCK_NANOSLEEP ) 
288     lldiv_t d = lldiv( delay, 1000000 );
289     struct timespec ts = { d.quot, d.rem * 1000 };
290
291 # if (_POSIX_MONOTONIC_CLOCK - 0 >= 0)
292     if( clock_nanosleep( CLOCK_MONOTONIC, 0, &ts, NULL ) )
293 # endif
294         clock_nanosleep( CLOCK_REALTIME, 0, &ts, NULL );
295
296 #elif defined( HAVE_KERNEL_OS_H )
297     snooze( delay );
298
299 #elif defined( PTH_INIT_IN_PTH_H )
300     pth_usleep( delay );
301
302 #elif defined( ST_INIT_IN_ST_H )
303     st_usleep( delay );
304
305 #elif defined( WIN32 ) || defined( UNDER_CE )
306     Sleep( (int) (delay / 1000) );
307
308 #elif defined( HAVE_NANOSLEEP )
309     struct timespec ts_delay;
310
311     ts_delay.tv_sec = delay / 1000000;
312     ts_delay.tv_nsec = (delay % 1000000) * 1000;
313
314     nanosleep( &ts_delay, NULL );
315
316 #else
317     struct timeval tv_delay;
318
319     tv_delay.tv_sec = delay / 1000000;
320     tv_delay.tv_usec = delay % 1000000;
321
322     /* select() return value should be tested, since several possible errors
323      * can occur. However, they should only happen in very particular occasions
324      * (i.e. when a signal is sent to the thread, or when memory is full), and
325      * can be ignored. */
326     select( 0, NULL, NULL, NULL, &tv_delay );
327 #endif
328
329     earlier += delay;
330     if( cached_time < earlier )
331         cached_time = earlier;
332 }
333
334 /*
335  * Date management (internal and external)
336  */
337
338 /**
339  * Initialize a date_t.
340  *
341  * \param date to initialize
342  * \param divider (sample rate) numerator
343  * \param divider (sample rate) denominator
344  */
345
346 void date_Init( date_t *p_date, uint32_t i_divider_n, uint32_t i_divider_d )
347 {
348     p_date->date = 0;
349     p_date->i_divider_num = i_divider_n;
350     p_date->i_divider_den = i_divider_d;
351     p_date->i_remainder = 0;
352 }
353
354 /**
355  * Change a date_t.
356  *
357  * \param date to change
358  * \param divider (sample rate) numerator
359  * \param divider (sample rate) denominator
360  */
361
362 void date_Change( date_t *p_date, uint32_t i_divider_n, uint32_t i_divider_d )
363 {
364     p_date->i_divider_num = i_divider_n;
365     p_date->i_divider_den = i_divider_d;
366 }
367
368 /**
369  * Set the date value of a date_t.
370  *
371  * \param date to set
372  * \param date value
373  */
374 void date_Set( date_t *p_date, mtime_t i_new_date )
375 {
376     p_date->date = i_new_date;
377     p_date->i_remainder = 0;
378 }
379
380 /**
381  * Get the date of a date_t
382  *
383  * \param date to get
384  * \return date value
385  */
386 mtime_t date_Get( const date_t *p_date )
387 {
388     return p_date->date;
389 }
390
391 /**
392  * Move forwards or backwards the date of a date_t.
393  *
394  * \param date to move
395  * \param difference value
396  */
397 void date_Move( date_t *p_date, mtime_t i_difference )
398 {
399     p_date->date += i_difference;
400 }
401
402 /**
403  * Increment the date and return the result, taking into account
404  * rounding errors.
405  *
406  * \param date to increment
407  * \param incrementation in number of samples
408  * \return date value
409  */
410 mtime_t date_Increment( date_t *p_date, uint32_t i_nb_samples )
411 {
412     mtime_t i_dividend = (mtime_t)i_nb_samples * 1000000;
413     p_date->date += i_dividend / p_date->i_divider_num * p_date->i_divider_den;
414     p_date->i_remainder += (int)(i_dividend % p_date->i_divider_num);
415
416     if( p_date->i_remainder >= p_date->i_divider_num )
417     {
418         /* This is Bresenham algorithm. */
419         p_date->date += p_date->i_divider_den;
420         p_date->i_remainder -= p_date->i_divider_num;
421     }
422
423     return p_date->date;
424 }
425
426 #ifdef WIN32
427 /*
428  * Number of micro-seconds between the beginning of the Windows epoch
429  * (Jan. 1, 1601) and the Unix epoch (Jan. 1, 1970).
430  *
431  * This assumes all Win32 compilers have 64-bit support.
432  */
433 #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS) || defined(__WATCOMC__)
434 #   define DELTA_EPOCH_IN_USEC  11644473600000000Ui64
435 #else
436 #   define DELTA_EPOCH_IN_USEC  11644473600000000ULL
437 #endif
438
439 static uint64_t filetime_to_unix_epoch (const FILETIME *ft)
440 {
441     uint64_t res = (uint64_t) ft->dwHighDateTime << 32;
442
443     res |= ft->dwLowDateTime;
444     res /= 10;                   /* from 100 nano-sec periods to usec */
445     res -= DELTA_EPOCH_IN_USEC;  /* from Win epoch to Unix epoch */
446     return (res);
447 }
448
449 static int gettimeofday (struct timeval *tv, void *tz )
450 {
451     FILETIME  ft;
452     uint64_t tim;
453
454     if (!tv) {
455         return VLC_EGENERIC;
456     }
457     GetSystemTimeAsFileTime (&ft);
458     tim = filetime_to_unix_epoch (&ft);
459     tv->tv_sec  = (long) (tim / 1000000L);
460     tv->tv_usec = (long) (tim % 1000000L);
461     return (0);
462 }
463 #endif
464
465
466
467 /**
468  * @return NTP 64-bits timestamp in host byte order.
469  */
470 uint64_t NTPtime64 (void)
471 {
472     struct timespec ts;
473 #if defined (CLOCK_REALTIME)
474     clock_gettime (CLOCK_REALTIME, &ts);
475 #else
476     {
477         struct timeval tv;
478         gettimeofday (&tv, NULL);
479         ts.tv_sec = tv.tv_sec;
480         ts.tv_nsec = tv.tv_usec * 1000;
481     }
482 #endif
483
484     /* Convert nanoseconds to 32-bits fraction (232 picosecond units) */
485     uint64_t t = (uint64_t)(ts.tv_nsec) << 32;
486     t /= 1000000000;
487
488
489     /* There is 70 years (incl. 17 leap ones) offset to the Unix Epoch.
490      * No leap seconds during that period since they were not invented yet.
491      */
492     assert (t < 0x100000000);
493     t |= ((70LL * 365 + 17) * 24 * 60 * 60 + ts.tv_sec) << 32;
494     return t;
495 }
496