* Preamble
*****************************************************************************/
-#include <vlc/vlc.h>
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
-#include <stdio.h> /* sprintf() */
#include <time.h> /* clock_gettime(), clock_nanosleep() */
-#include <stdlib.h> /* lldiv() */
#include <assert.h>
#include <errno.h>
-
-#if defined( PTH_INIT_IN_PTH_H ) /* GNU Pth */
-# include <pth.h>
-#endif
-
#ifdef HAVE_UNISTD_H
# include <unistd.h> /* select() */
#endif
#if defined( WIN32 ) || defined( UNDER_CE )
# include <windows.h>
+# include <mmsystem.h>
+#endif
+
+#if defined( UNDER_CE )
+# include <windows.h>
#endif
+
#if defined(HAVE_SYS_TIME_H)
# include <sys/time.h>
#endif
int nanosleep(struct timespec *, struct timespec *);
#endif
+#if !defined (_POSIX_CLOCK_SELECTION)
+# define _POSIX_CLOCK_SELECTION (-1)
+#endif
+
+# if (_POSIX_CLOCK_SELECTION < 0)
+/*
+ * We cannot use the monotonic clock is 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
+ * warps the wall clock.
+ */
+# undef CLOCK_MONOTONIC
+# define CLOCK_MONOTONIC CLOCK_REALTIME
+#elif !defined (HAVE_CLOCK_NANOSLEEP)
+/* Clock selection without clock in the first place, I don't think so. */
+# error We have quite a situation here! Fix me if it ever happens.
+#endif
+
/**
* Return a date in a readable format
*
*/
char *secstotimestr( char *psz_buffer, int i_seconds )
{
- snprintf( psz_buffer, MSTRTIME_MAX_SIZE, "%d:%2.2d:%2.2d",
- (int) (i_seconds / (60 *60)),
- (int) ((i_seconds / 60) % 60),
- (int) (i_seconds % 60) );
+ int i_hours, i_mins;
+ i_mins = i_seconds / 60;
+ i_hours = i_mins / 60 ;
+ if( i_hours )
+ {
+ snprintf( psz_buffer, MSTRTIME_MAX_SIZE, "%d:%2.2d:%2.2d",
+ (int) i_hours,
+ (int) (i_mins % 60),
+ (int) (i_seconds % 60) );
+ }
+ else
+ {
+ snprintf( psz_buffer, MSTRTIME_MAX_SIZE, "%2.2d:%2.2d",
+ (int) i_mins ,
+ (int) (i_seconds % 60) );
+ }
return( psz_buffer );
}
+#if defined (HAVE_CLOCK_NANOSLEEP)
+static unsigned prec = 0;
+
+static void mprec_once( void )
+{
+ struct timespec ts;
+ if( clock_getres( CLOCK_MONOTONIC, &ts ))
+ clock_getres( CLOCK_REALTIME, &ts );
+
+ prec = ts.tv_nsec / 1000;
+}
+#endif
+
/**
* Return a value that is no bigger than the clock precision
* (possibly zero).
static inline unsigned mprec( void )
{
#if defined (HAVE_CLOCK_NANOSLEEP)
- struct timespec ts;
- if( clock_getres( CLOCK_MONOTONIC, &ts ))
- clock_getres( CLOCK_REALTIME, &ts );
-
- return ts.tv_nsec / 1000;
-#endif
+ static pthread_once_t once = PTHREAD_ONCE_INIT;
+ pthread_once( &once, mprec_once );
+ return prec;
+#else
return 0;
-}
-
-static unsigned prec = 0;
-static volatile mtime_t cached_time = 0;
-#if (_POSIX_MONOTONIC_CLOCK - 0 < 0)
-# define CLOCK_MONOTONIC CLOCK_REALTIME
#endif
+}
/**
* Return high precision date
*
- * Uses the gettimeofday() function when possible (1 MHz resolution) or the
- * ftime() function (1 kHz resolution).
+ * Use a 1 MHz clock when possible, or 1 kHz
+ *
+ * Beware ! It doesn't reflect the actual date (since epoch), but can be the machine's uptime or anything (when monotonic clock is used)
*/
mtime_t mdate( void )
{
#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 = I64C(-1);
- mtime_t usec_time;
+ static mtime_t freq = INT64_C(-1);
- if( freq == I64C(-1) )
+ if( freq == INT64_C(-1) )
{
/* Extract from the Tcl source code:
* (http://www.cs.man.ac.uk/fellowsd-bin/TIP/7.html)
LARGE_INTEGER buf;
freq = ( QueryPerformanceFrequency( &buf ) &&
- (buf.QuadPart == I64C(1193182) || buf.QuadPart == I64C(3579545) ) )
+ (buf.QuadPart == INT64_C(1193182) || buf.QuadPart == INT64_C(3579545) ) )
? buf.QuadPart : 0;
+
+#if defined( WIN32 )
+ /* on windows 2000, XP and Vista detect if there are two
+ cores there - that makes QueryPerformanceFrequency in
+ any case not trustable?
+ (may also be true, for single cores with adaptive
+ CPU frequency and active power management?)
+ */
+ HINSTANCE h_Kernel32 = LoadLibrary(_T("kernel32.dll"));
+ if(h_Kernel32)
+ {
+ void WINAPI (*pf_GetSystemInfo)(LPSYSTEM_INFO);
+ pf_GetSystemInfo = (void WINAPI (*)(LPSYSTEM_INFO))
+ GetProcAddress(h_Kernel32, _T("GetSystemInfo"));
+ if(pf_GetSystemInfo)
+ {
+ SYSTEM_INFO system_info;
+ pf_GetSystemInfo(&system_info);
+ if(system_info.dwNumberOfProcessors > 1)
+ freq = 0;
+ }
+ FreeLibrary(h_Kernel32);
+ }
+#endif
}
if( freq != 0 )
}
else
{
- /* Fallback on GetTickCount() which has a milisecond resolution
- * (actually, best case is about 10 ms resolution)
- * GetTickCount() only returns a DWORD thus will wrap after
+ /* Fallback on timeGetTime() which has a milisecond 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 = I64C(-1);
+ static mtime_t i_previous_time = INT64_C(-1);
static int i_wrap_counts = -1;
if( i_wrap_counts == -1 )
{
/* Initialization */
- i_previous_time = I64C(1000) * GetTickCount();
+#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 );
- res = I64C(1000) *
- (i_wrap_counts * I64C(0x100000000) + GetTickCount());
+#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++;
- usec_time += I64C(0x100000000) * 1000;
+ res += INT64_C(0x100000000) * 1000;
}
- i_previous_time = usec_time;
+ i_previous_time = res;
LeaveCriticalSection( &date_lock );
}
#else
res = (mtime_t) tv_date.tv_sec * 1000000 + (mtime_t) tv_date.tv_usec;
#endif
- return cached_time = res;
+ return res;
}
/**
*/
void mwait( mtime_t date )
{
- if( prec == 0 )
- prec = mprec();
-
/* If the deadline is already elapsed, or within the clock precision,
- * do not even bother the clock. */
- if( ( date - cached_time ) < (mtime_t)prec ) // OK: mtime_t is signed
- return;
+ * do not even bother the system timer. */
+ date -= mprec();
-#if 0 && defined (HAVE_CLOCK_NANOSLEEP)
+#if defined (HAVE_CLOCK_NANOSLEEP)
lldiv_t d = lldiv( date, 1000000 );
struct timespec ts = { d.quot, d.rem * 1000 };
*/
void msleep( mtime_t delay )
{
- mtime_t earlier = cached_time;
-
-#if defined( HAVE_CLOCK_NANOSLEEP )
+#if defined( HAVE_CLOCK_NANOSLEEP )
lldiv_t d = lldiv( delay, 1000000 );
struct timespec ts = { d.quot, d.rem * 1000 };
#elif defined( HAVE_KERNEL_OS_H )
snooze( delay );
-#elif defined( PTH_INIT_IN_PTH_H )
- pth_usleep( delay );
-
-#elif defined( ST_INIT_IN_ST_H )
- st_usleep( delay );
-
#elif defined( WIN32 ) || defined( UNDER_CE )
- Sleep( (int) (delay / 1000) );
+ Sleep( (DWORD) (delay / 1000) );
#elif defined( HAVE_NANOSLEEP )
struct timespec ts_delay;
* or clock_nanosleep() if this is an issue. */
select( 0, NULL, NULL, NULL, &tv_delay );
#endif
-
- earlier += delay;
- if( cached_time < earlier )
- cached_time = earlier;
}
/*
return p_date->date;
}
+#ifndef HAVE_GETTIMEOFDAY
+
#ifdef WIN32
+
/*
* Number of micro-seconds between the beginning of the Windows epoch
* (Jan. 1, 1601) and the Unix epoch (Jan. 1, 1970).
tv->tv_usec = (long) (tim % 1000000L);
return (0);
}
-#endif
+#endif
+#endif
/**
* @return NTP 64-bits timestamp in host byte order.