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