This source file includes following definitions.
- nanosleep
- nanosleep
- sighandler
- my_usleep
- nanosleep
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 #include <config.h>
22
23 #include <time.h>
24
25 #include "intprops.h"
26 #include "sig-handler.h"
27 #include "verify.h"
28
29 #include <stdbool.h>
30 #include <stdio.h>
31 #include <sys/types.h>
32 #include <sys/select.h>
33 #include <signal.h>
34
35 #include <sys/time.h>
36 #include <errno.h>
37
38 #include <unistd.h>
39
40
41 enum { BILLION = 1000 * 1000 * 1000 };
42
43 #if HAVE_BUG_BIG_NANOSLEEP
44
45 int
46 nanosleep (const struct timespec *requested_delay,
47 struct timespec *remaining_delay)
48 # undef nanosleep
49 {
50
51
52
53
54
55
56 if (requested_delay->tv_nsec < 0 || BILLION <= requested_delay->tv_nsec)
57 {
58 errno = EINVAL;
59 return -1;
60 }
61
62 {
63
64 verify (TYPE_MAXIMUM (time_t) / 24 / 24 / 60 / 60);
65 const time_t limit = 24 * 24 * 60 * 60;
66 time_t seconds = requested_delay->tv_sec;
67 struct timespec intermediate;
68 intermediate.tv_nsec = requested_delay->tv_nsec;
69
70 while (limit < seconds)
71 {
72 int result;
73 intermediate.tv_sec = limit;
74 result = nanosleep (&intermediate, remaining_delay);
75 seconds -= limit;
76 if (result)
77 {
78 if (remaining_delay)
79 remaining_delay->tv_sec += seconds;
80 return result;
81 }
82 intermediate.tv_nsec = 0;
83 }
84 intermediate.tv_sec = seconds;
85 return nanosleep (&intermediate, remaining_delay);
86 }
87 }
88
89 #elif defined _WIN32 && ! defined __CYGWIN__
90
91
92 # define WIN32_LEAN_AND_MEAN
93 # include <windows.h>
94
95
96
97
98
99
100
101 int
102 nanosleep (const struct timespec *requested_delay,
103 struct timespec *remaining_delay)
104 {
105 static bool initialized;
106
107
108 static double ticks_per_nanosecond;
109
110 if (requested_delay->tv_nsec < 0 || BILLION <= requested_delay->tv_nsec)
111 {
112 errno = EINVAL;
113 return -1;
114 }
115
116
117
118 if (requested_delay->tv_sec == 0)
119 {
120 if (!initialized)
121 {
122
123 LARGE_INTEGER ticks_per_second;
124
125 if (QueryPerformanceFrequency (&ticks_per_second))
126 ticks_per_nanosecond =
127 (double) ticks_per_second.QuadPart / 1000000000.0;
128
129 initialized = true;
130 }
131 if (ticks_per_nanosecond)
132 {
133
134
135
136
137
138
139 int sleep_millis = (int) requested_delay->tv_nsec / 1000000 - 10;
140
141 LONGLONG wait_ticks = requested_delay->tv_nsec * ticks_per_nanosecond;
142
143 LARGE_INTEGER counter_before;
144 if (QueryPerformanceCounter (&counter_before))
145 {
146
147
148
149
150 LONGLONG wait_until = counter_before.QuadPart + wait_ticks;
151
152 if (sleep_millis > 0)
153 Sleep (sleep_millis);
154
155 for (;;)
156 {
157 LARGE_INTEGER counter_after;
158 if (!QueryPerformanceCounter (&counter_after))
159
160
161 break;
162 if (counter_after.QuadPart >= wait_until)
163
164 break;
165 }
166 goto done;
167 }
168 }
169 }
170
171 Sleep (requested_delay->tv_sec * 1000 + requested_delay->tv_nsec / 1000000);
172
173 done:
174
175 if (remaining_delay != NULL)
176 {
177 remaining_delay->tv_sec = 0;
178 remaining_delay->tv_nsec = 0;
179 }
180 return 0;
181 }
182
183 #else
184
185
186
187
188
189 # ifndef SIGCONT
190 # define SIGCONT SIGTERM
191 # endif
192
193 static sig_atomic_t volatile suspended;
194
195
196
197 static _GL_ASYNC_SAFE void
198 sighandler (int sig)
199 {
200 suspended = 1;
201 }
202
203
204
205 static int
206 my_usleep (const struct timespec *ts_delay)
207 {
208 struct timeval tv_delay;
209 tv_delay.tv_sec = ts_delay->tv_sec;
210 tv_delay.tv_usec = (ts_delay->tv_nsec + 999) / 1000;
211 if (tv_delay.tv_usec == 1000000)
212 {
213 if (tv_delay.tv_sec == TYPE_MAXIMUM (time_t))
214 tv_delay.tv_usec = 1000000 - 1;
215 else
216 {
217 tv_delay.tv_sec++;
218 tv_delay.tv_usec = 0;
219 }
220 }
221 return select (0, NULL, NULL, NULL, &tv_delay);
222 }
223
224
225
226
227 int
228 nanosleep (const struct timespec *requested_delay,
229 struct timespec *remaining_delay)
230 {
231 static bool initialized;
232
233 if (requested_delay->tv_nsec < 0 || BILLION <= requested_delay->tv_nsec)
234 {
235 errno = EINVAL;
236 return -1;
237 }
238
239
240 if (! initialized)
241 {
242 struct sigaction oldact;
243
244 sigaction (SIGCONT, NULL, &oldact);
245 if (get_handler (&oldact) != SIG_IGN)
246 {
247 struct sigaction newact;
248
249 newact.sa_handler = sighandler;
250 sigemptyset (&newact.sa_mask);
251 newact.sa_flags = 0;
252 sigaction (SIGCONT, &newact, NULL);
253 }
254 initialized = true;
255 }
256
257 suspended = 0;
258
259 if (my_usleep (requested_delay) == -1)
260 {
261 if (suspended)
262 {
263
264
265
266
267 errno = EINTR;
268 }
269 return -1;
270 }
271
272
273
274 return 0;
275 }
276 #endif