46
46
# include <kernel/OS.h>
49
#if defined( WIN32 ) || defined( UNDER_CE )
50
50
# include <windows.h>
52
52
# include <sys/time.h>
59
/*****************************************************************************
60
* mstrtime: return a date in a readable format
61
*****************************************************************************
62
* This functions is provided for any interface function which need to print a
63
* date. psz_buffer should be a buffer long enough to store the formatted
55
#if defined(HAVE_NANOSLEEP) && !defined(HAVE_STRUCT_TIMESPEC)
63
#if defined(HAVE_NANOSLEEP) && !defined(HAVE_DECL_NANOSLEEP)
64
int nanosleep(struct timespec *, struct timespec *);
68
* Return a date in a readable format
70
* This function converts a mtime date into a string.
71
* psz_buffer should be a buffer long enough to store the formatted
65
*****************************************************************************/
73
* \param date to be converted
74
* \param psz_buffer should be a buffer at least MSTRTIME_MAX_SIZE characters
75
* \return psz_buffer is returned so this can be used as printf parameter.
66
77
char *mstrtime( char *psz_buffer, mtime_t date )
68
sprintf( psz_buffer, "%02d:%02d:%02d-%03d.%03d",
69
(int) (date / (I64C(1000) * I64C(1000) * I64C(60) * I64C(60)) % I64C(24)),
70
(int) (date / (I64C(1000) * I64C(1000) * I64C(60)) % I64C(60)),
71
(int) (date / (I64C(1000) * I64C(1000)) % I64C(60)),
72
(int) (date / I64C(1000) % I64C(1000)),
73
(int) (date % I64C(1000)) );
77
/*****************************************************************************
78
* mdate: return high precision date (inline function)
79
*****************************************************************************
79
static mtime_t ll1000 = 1000, ll60 = 60, ll24 = 24;
81
snprintf( psz_buffer, MSTRTIME_MAX_SIZE, "%02d:%02d:%02d-%03d.%03d",
82
(int) (date / (ll1000 * ll1000 * ll60 * ll60) % ll24),
83
(int) (date / (ll1000 * ll1000 * ll60) % ll60),
84
(int) (date / (ll1000 * ll1000) % ll60),
85
(int) (date / ll1000 % ll1000),
86
(int) (date % ll1000) );
91
* Convert seconds to a time in the format h:mm:ss.
93
* This function is provided for any interface function which need to print a
94
* time string in the format h:mm:ss
96
* \param secs the date to be converted
97
* \param psz_buffer should be a buffer at least MSTRTIME_MAX_SIZE characters
98
* \return psz_buffer is returned so this can be used as printf parameter.
100
char *secstotimestr( char *psz_buffer, int i_seconds )
102
snprintf( psz_buffer, MSTRTIME_MAX_SIZE, "%d:%2.2d:%2.2d",
103
(int) (i_seconds / (60 *60)),
104
(int) ((i_seconds / 60) % 60),
105
(int) (i_seconds % 60) );
106
return( psz_buffer );
110
* Return high precision date
80
112
* Uses the gettimeofday() function when possible (1 MHz resolution) or the
81
113
* ftime() function (1 kHz resolution).
82
*****************************************************************************/
83
115
mtime_t mdate( void )
85
117
#if defined( HAVE_KERNEL_OS_H )
86
118
return( real_time_clock_usecs() );
88
#elif defined( WIN32 )
89
/* We don't get the real date, just the value of a high precision timer.
90
* this is because the usual time functions have at best only a milisecond
92
mtime_t freq, usec_time;
94
if( QueryPerformanceFrequency( (LARGE_INTEGER *)&freq ) )
120
#elif defined( WIN32 ) || defined( UNDER_CE )
121
/* We don't need the real date, just the value of a high precision timer */
122
static mtime_t freq = I64C(-1);
125
if( freq == I64C(-1) )
127
/* Extract from the Tcl source code:
128
* (http://www.cs.man.ac.uk/fellowsd-bin/TIP/7.html)
130
* Some hardware abstraction layers use the CPU clock
131
* in place of the real-time clock as a performance counter
132
* reference. This results in:
133
* - inconsistent results among the processors on
134
* multi-processor systems.
135
* - unpredictable changes in performance counter frequency
136
* on "gearshift" processors such as Transmeta and
138
* There seems to be no way to test whether the performance
139
* counter is reliable, but a useful heuristic is that
140
* if its frequency is 1.193182 MHz or 3.579545 MHz, it's
141
* derived from a colorburst crystal and is therefore
142
* the RTC rather than the TSC. If it's anything else, we
143
* presume that the performance counter is unreliable.
146
freq = ( QueryPerformanceFrequency( (LARGE_INTEGER *)&freq ) &&
147
(freq == I64C(1193182) || freq == I64C(3579545) ) )
96
153
/* Microsecond resolution */
97
154
QueryPerformanceCounter( (LARGE_INTEGER *)&usec_time );
102
/* Milisecond resolution */
103
return 1000 * GetTickCount();
159
/* Fallback on GetTickCount() which has a milisecond resolution
160
* (actually, best case is about 10 ms resolution)
161
* GetTickCount() only returns a DWORD thus will wrap after
162
* about 49.7 days so we try to detect the wrapping. */
164
static CRITICAL_SECTION date_lock;
165
static mtime_t i_previous_time = I64C(-1);
166
static int i_wrap_counts = -1;
168
if( i_wrap_counts == -1 )
171
i_previous_time = I64C(1000) * GetTickCount();
172
InitializeCriticalSection( &date_lock );
176
EnterCriticalSection( &date_lock );
177
usec_time = I64C(1000) *
178
(i_wrap_counts * I64C(0x100000000) + GetTickCount());
179
if( i_previous_time > usec_time )
181
/* Counter wrapped */
183
usec_time += I64C(0x100000000000);
185
i_previous_time = usec_time;
186
LeaveCriticalSection( &date_lock );
172
254
# if defined( PTH_INIT_IN_PTH_H )
173
255
pth_usleep( delay );
175
# elif defined( HAVE_USLEEP )
257
# elif defined( ST_INIT_IN_ST_H )
179
tv_delay.tv_sec = delay / 1000000;
180
tv_delay.tv_usec = delay % 1000000;
262
# if defined( HAVE_NANOSLEEP )
264
struct timespec ts_delay;
265
ts_delay.tv_sec = delay / 1000000;
266
ts_delay.tv_nsec = (delay % 1000000) * 1000;
268
nanosleep( &ts_delay, NULL );
272
tv_date.tv_sec = delay / 1000000;
273
tv_date.tv_usec = delay % 1000000;
181
274
/* see msleep() about select() errors */
182
select( 0, NULL, NULL, NULL, &tv_delay );
275
select( 0, NULL, NULL, NULL, &tv_date );
189
/*****************************************************************************
190
* msleep: more precise sleep() (inline function) (ok ?)
191
*****************************************************************************
284
* More precise sleep()
192
286
* Portable usleep() function.
193
*****************************************************************************/
287
* \param delay the amount of time to sleep
194
289
void msleep( mtime_t delay )
196
291
#if defined( HAVE_KERNEL_OS_H )
199
294
#elif defined( PTH_INIT_IN_PTH_H )
200
struct timeval tv_delay;
201
tv_delay.tv_sec = delay / 1000000;
202
tv_delay.tv_usec = delay % 1000000;
203
pth_select( 0, NULL, NULL, NULL, &tv_delay );
205
#elif defined( HAVE_USLEEP )
208
#elif defined( WIN32 )
297
#elif defined( ST_INIT_IN_ST_H )
300
#elif defined( WIN32 ) || defined( UNDER_CE )
209
301
Sleep( (int) (delay / 1000) );
303
#elif defined( HAVE_NANOSLEEP )
304
struct timespec ts_delay;
306
ts_delay.tv_sec = delay / 1000000;
307
ts_delay.tv_nsec = (delay % 1000000) * 1000;
309
nanosleep( &ts_delay, NULL );
212
312
struct timeval tv_delay;
214
314
tv_delay.tv_sec = delay / 1000000;
215
315
tv_delay.tv_usec = delay % 1000000;
216
317
/* select() return value should be tested, since several possible errors
217
318
* can occur. However, they should only happen in very particular occasions
218
319
* (i.e. when a signal is sent to the thread, or when memory is full), and
219
* can be ingnored. */
220
321
select( 0, NULL, NULL, NULL, &tv_delay );