master
1/**
2 * This file has no copyright assigned and is placed in the Public Domain.
3 * This file is part of the w64 mingw-runtime package.
4 * No warranty is given; refer to the file DISCLAIMER.PD within this package.
5 */
6
7#ifdef HAVE_CONFIG_H
8#include "config.h"
9#endif
10
11#include <assert.h>
12#include <errno.h>
13#include <time.h>
14
15#define WIN32_LEAN_AND_MEAN
16#include <windows.h>
17
18#define WINPTHREAD_NANOSLEEP_DECL WINPTHREAD_API
19
20/* public header files */
21#include "pthread.h"
22#include "pthread_time.h"
23/* internal header files */
24#include "thread.h"
25
26#define POW10_3 1000
27#define POW10_4 10000
28#define POW10_6 1000000
29#define POW10_9 1000000000
30#define MAX_SLEEP_IN_MS 4294967294UL
31
32/**
33 * Sleep for the specified time.
34 * @param request The desired amount of time to sleep.
35 * @param remain The remain amount of time to sleep.
36 * @return If the function succeeds, the return value is 0.
37 * If the function fails, the return value is -1,
38 * with errno set to indicate the error.
39 */
40static int __nanosleep(const struct _timespec64 *request, struct _timespec64 *remain)
41{
42 unsigned long ms, rc = 0;
43 unsigned __int64 u64, want, real;
44
45 union {
46 unsigned __int64 ns100;
47 FILETIME ft;
48 } _start, _end;
49
50 if (request->tv_sec < 0 || request->tv_nsec < 0 || request->tv_nsec >= POW10_9) {
51 errno = EINVAL;
52 return -1;
53 }
54
55 if (remain != NULL) GetSystemTimeAsFileTime(&_start.ft);
56
57 want = u64 = request->tv_sec * POW10_3 + request->tv_nsec / POW10_6;
58 while (u64 > 0 && rc == 0) {
59 if (u64 >= MAX_SLEEP_IN_MS) ms = MAX_SLEEP_IN_MS;
60 else ms = (unsigned long) u64;
61
62 u64 -= ms;
63 rc = _pthread_delay_np_ms(ms);
64 }
65
66 if (rc != 0) { /* WAIT_IO_COMPLETION (192) */
67 if (remain != NULL) {
68 GetSystemTimeAsFileTime(&_end.ft);
69 real = (_end.ns100 - _start.ns100) / POW10_4;
70
71 if (real >= want) u64 = 0;
72 else u64 = want - real;
73
74 remain->tv_sec = u64 / POW10_3;
75 remain->tv_nsec = (long) (u64 % POW10_3) * POW10_6;
76 }
77
78 errno = EINTR;
79 return -1;
80 }
81
82 return 0;
83}
84
85int nanosleep64(const struct _timespec64 *request, struct _timespec64 *remain)
86{
87 return __nanosleep (request, remain);
88}
89
90int nanosleep32(const struct _timespec32 *request, struct _timespec32 *remain)
91{
92 struct _timespec64 request64 = {
93 .tv_sec = request->tv_sec,
94 .tv_nsec = request->tv_nsec
95 };
96 struct _timespec64 remain64 = {0};
97
98 if (__nanosleep (&request64, &remain64) == -1)
99 return -1;
100
101 assert (remain64.tv_sec <= INT_MAX);
102
103 if (remain != NULL) {
104 remain->tv_sec = (__time32_t)remain64.tv_sec;
105 remain->tv_nsec = remain64.tv_nsec;
106 }
107
108 return 0;
109}