1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
|
#include "posix_time.h"
#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
#include <cerrno>
int
nanosleep( const struct timespec *requested_delay,
struct timespec *remaining_delay )
{
static bool initialized;
/* Number of performance counter increments per nanosecond,
or zero if it could not be determined. */
static double ticks_per_nanosecond;
if( requested_delay->tv_nsec < 0 || BILLION <= requested_delay->tv_nsec ) {
errno = EINVAL;
return -1;
}
/* For requested delays of one second or more, 15ms resolution is
sufficient. */
if( requested_delay->tv_sec == 0 ) {
if( !initialized ) {
/* Initialize ticks_per_nanosecond. */
LARGE_INTEGER ticks_per_second;
if( QueryPerformanceFrequency( &ticks_per_second ) )
ticks_per_nanosecond =
( double ) ticks_per_second.QuadPart / 1000000000.0;
initialized = true;
}
if( ticks_per_nanosecond ) {
/* QueryPerformanceFrequency worked. We can use
QueryPerformanceCounter. Use a combination of Sleep and
busy-looping. */
/* Number of milliseconds to pass to the Sleep function.
Since Sleep can take up to 8 ms less or 8 ms more than requested
(or maybe more if the system is loaded), we subtract 10 ms. */
int sleep_millis = static_cast<int>( requested_delay->tv_nsec ) / 1000000 - 10;
/* Determine how many ticks to delay. */
LONGLONG wait_ticks = requested_delay->tv_nsec * ticks_per_nanosecond;
/* Start. */
LARGE_INTEGER counter_before;
if( QueryPerformanceCounter( &counter_before ) ) {
/* Wait until the performance counter has reached this value.
We don't need to worry about overflow, because the performance
counter is reset at reboot, and with a frequency of 3.6E6
ticks per second 63 bits suffice for over 80000 years. */
LONGLONG wait_until = counter_before.QuadPart + wait_ticks;
/* Use Sleep for the longest part. */
if( sleep_millis > 0 ) {
Sleep( sleep_millis );
}
/* Busy-loop for the rest. */
for( ;; ) {
LARGE_INTEGER counter_after;
if( !QueryPerformanceCounter( &counter_after ) )
/* QueryPerformanceCounter failed, but succeeded earlier.
Should not happen. */
{
break;
}
if( counter_after.QuadPart >= wait_until )
/* The requested time has elapsed. */
{
break;
}
}
goto done;
}
}
}
/* Implementation for long delays and as fallback. */
Sleep( requested_delay->tv_sec * 1000 + requested_delay->tv_nsec / 1000000 );
done:
/* Sleep is not interruptible. So there is no remaining delay. */
if( remaining_delay != NULL ) {
remaining_delay->tv_sec = 0;
remaining_delay->tv_nsec = 0;
}
return 0;
}
#endif
|