/** * 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. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #define WIN32_LEAN_AND_MEAN #include #define WINPTHREAD_NANOSLEEP_DECL WINPTHREAD_API /* public header files */ #include "pthread.h" #include "pthread_time.h" /* internal header files */ #include "thread.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. */ static int __nanosleep(const struct _timespec64 *request, struct _timespec64 *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; } int nanosleep64(const struct _timespec64 *request, struct _timespec64 *remain) { return __nanosleep (request, remain); } int nanosleep32(const struct _timespec32 *request, struct _timespec32 *remain) { struct _timespec64 request64 = { .tv_sec = request->tv_sec, .tv_nsec = request->tv_nsec }; struct _timespec64 remain64 = {0}; if (__nanosleep (&request64, &remain64) == -1) return -1; assert (remain64.tv_sec <= INT_MAX); if (remain != NULL) { remain->tv_sec = (__time32_t)remain64.tv_sec; remain->tv_nsec = remain64.tv_nsec; } return 0; }