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