/** * 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 #include #include #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; }