blob: 0cce4492e2965f592e8b2ac8bd5efe14f45e4cf4 [file] [log] [blame]
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the w64 mingw-runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*/
#include <errno.h>
#include <time.h>
#include <windows.h>
#include "pthread.h"
#include "pthread_time.h"
#include "winpthread_internal.h"
#define POW10_3 1000
#define POW10_4 10000
#define POW10_6 1000000
#define POW10_9 1000000000
#define MAX_SLEEP_IN_MS 4294967294UL
/**
* Sleep for the specified time.
* @param request The desired amount of time to sleep.
* @param remain The remain amount of time to sleep.
* @return If the function succeeds, the return value is 0.
* If the function fails, the return value is -1,
* with errno set to indicate the error.
*/
int nanosleep(const struct timespec *request, struct timespec *remain)
{
unsigned long ms, rc = 0;
unsigned __int64 u64, want, real;
union {
unsigned __int64 ns100;
FILETIME ft;
} _start, _end;
if (request->tv_sec < 0 || request->tv_nsec < 0 || request->tv_nsec >= POW10_9) {
errno = EINVAL;
return -1;
}
if (remain != NULL) GetSystemTimeAsFileTime(&_start.ft);
want = u64 = request->tv_sec * POW10_3 + request->tv_nsec / POW10_6;
while (u64 > 0 && rc == 0) {
if (u64 >= MAX_SLEEP_IN_MS) ms = MAX_SLEEP_IN_MS;
else ms = (unsigned long) u64;
u64 -= ms;
rc = pthread_delay_np_ms(ms);
}
if (rc != 0) { /* WAIT_IO_COMPLETION (192) */
if (remain != NULL) {
GetSystemTimeAsFileTime(&_end.ft);
real = (_end.ns100 - _start.ns100) / POW10_4;
if (real >= want) u64 = 0;
else u64 = want - real;
remain->tv_sec = u64 / POW10_3;
remain->tv_nsec = (long) (u64 % POW10_3) * POW10_6;
}
errno = EINTR;
return -1;
}
return 0;
}