1 /* Provide a replacement for the POSIX nanosleep function.
3 Copyright (C) 1999-2000, 2002, 2004-2020 Free Software Foundation, Inc.
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>. */
18 /* written by Jim Meyering
19 and Bruno Haible for the native Windows part */
26 #include "sig-handler.h"
31 #include <sys/types.h>
32 #include <sys/select.h>
41 enum { BILLION
= 1000 * 1000 * 1000 };
43 #if HAVE_BUG_BIG_NANOSLEEP
46 nanosleep (const struct timespec
*requested_delay
,
47 struct timespec
*remaining_delay
)
50 /* nanosleep mishandles large sleeps due to internal overflow problems.
51 The worst known case of this is Linux 2.6.9 with glibc 2.3.4, which
52 can't sleep more than 24.85 days (2^31 milliseconds). Similarly,
53 cygwin 1.5.x, which can't sleep more than 49.7 days (2^32 milliseconds).
54 Solve this by breaking the sleep up into smaller chunks. */
56 if (requested_delay
->tv_nsec
< 0 || BILLION
<= requested_delay
->tv_nsec
)
63 /* Verify that time_t is large enough. */
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
;
70 while (limit
< seconds
)
73 intermediate
.tv_sec
= limit
;
74 result
= nanosleep (&intermediate
, remaining_delay
);
79 remaining_delay
->tv_sec
+= seconds
;
82 intermediate
.tv_nsec
= 0;
84 intermediate
.tv_sec
= seconds
;
85 return nanosleep (&intermediate
, remaining_delay
);
89 #elif defined _WIN32 && ! defined __CYGWIN__
90 /* Native Windows platforms. */
92 # define WIN32_LEAN_AND_MEAN
95 /* The Windows API function Sleep() has a resolution of about 15 ms and takes
96 at least 5 ms to execute. We use this function for longer time periods.
97 Additionally, we use busy-looping over short time periods, to get a
98 resolution of about 0.01 ms. In order to measure such short timespans,
99 we use the QueryPerformanceCounter() function. */
102 nanosleep (const struct timespec
*requested_delay
,
103 struct timespec
*remaining_delay
)
105 static bool initialized
;
106 /* Number of performance counter increments per nanosecond,
107 or zero if it could not be determined. */
108 static double ticks_per_nanosecond
;
110 if (requested_delay
->tv_nsec
< 0 || BILLION
<= requested_delay
->tv_nsec
)
116 /* For requested delays of one second or more, 15ms resolution is
118 if (requested_delay
->tv_sec
== 0)
122 /* Initialize ticks_per_nanosecond. */
123 LARGE_INTEGER ticks_per_second
;
125 if (QueryPerformanceFrequency (&ticks_per_second
))
126 ticks_per_nanosecond
=
127 (double) ticks_per_second
.QuadPart
/ 1000000000.0;
131 if (ticks_per_nanosecond
)
133 /* QueryPerformanceFrequency worked. We can use
134 QueryPerformanceCounter. Use a combination of Sleep and
136 /* Number of milliseconds to pass to the Sleep function.
137 Since Sleep can take up to 8 ms less or 8 ms more than requested
138 (or maybe more if the system is loaded), we subtract 10 ms. */
139 int sleep_millis
= (int) requested_delay
->tv_nsec
/ 1000000 - 10;
140 /* Determine how many ticks to delay. */
141 LONGLONG wait_ticks
= requested_delay
->tv_nsec
* ticks_per_nanosecond
;
143 LARGE_INTEGER counter_before
;
144 if (QueryPerformanceCounter (&counter_before
))
146 /* Wait until the performance counter has reached this value.
147 We don't need to worry about overflow, because the performance
148 counter is reset at reboot, and with a frequency of 3.6E6
149 ticks per second 63 bits suffice for over 80000 years. */
150 LONGLONG wait_until
= counter_before
.QuadPart
+ wait_ticks
;
151 /* Use Sleep for the longest part. */
152 if (sleep_millis
> 0)
153 Sleep (sleep_millis
);
154 /* Busy-loop for the rest. */
157 LARGE_INTEGER counter_after
;
158 if (!QueryPerformanceCounter (&counter_after
))
159 /* QueryPerformanceCounter failed, but succeeded earlier.
160 Should not happen. */
162 if (counter_after
.QuadPart
>= wait_until
)
163 /* The requested time has elapsed. */
170 /* Implementation for long delays and as fallback. */
171 Sleep (requested_delay
->tv_sec
* 1000 + requested_delay
->tv_nsec
/ 1000000);
174 /* Sleep is not interruptible. So there is no remaining delay. */
175 if (remaining_delay
!= NULL
)
177 remaining_delay
->tv_sec
= 0;
178 remaining_delay
->tv_nsec
= 0;
184 /* Unix platforms lacking nanosleep. */
186 /* Some systems (MSDOS) don't have SIGCONT.
187 Using SIGTERM here turns the signal-handling code below
188 into a no-op on such systems. */
190 # define SIGCONT SIGTERM
193 static sig_atomic_t volatile suspended
;
195 /* Handle SIGCONT. */
197 static _GL_ASYNC_SAFE
void
203 /* Suspend execution for at least *TS_DELAY seconds. */
206 my_usleep (const struct timespec
*ts_delay
)
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)
213 if (tv_delay
.tv_sec
== TYPE_MAXIMUM (time_t))
214 tv_delay
.tv_usec
= 1000000 - 1; /* close enough */
218 tv_delay
.tv_usec
= 0;
221 return select (0, NULL
, NULL
, NULL
, &tv_delay
);
224 /* Suspend execution for at least *REQUESTED_DELAY seconds. The
225 *REMAINING_DELAY part isn't implemented yet. */
228 nanosleep (const struct timespec
*requested_delay
,
229 struct timespec
*remaining_delay
)
231 static bool initialized
;
233 if (requested_delay
->tv_nsec
< 0 || BILLION
<= requested_delay
->tv_nsec
)
239 /* set up sig handler */
242 struct sigaction oldact
;
244 sigaction (SIGCONT
, NULL
, &oldact
);
245 if (get_handler (&oldact
) != SIG_IGN
)
247 struct sigaction newact
;
249 newact
.sa_handler
= sighandler
;
250 sigemptyset (&newact
.sa_mask
);
252 sigaction (SIGCONT
, &newact
, NULL
);
259 if (my_usleep (requested_delay
) == -1)
263 /* Calculate time remaining. */
264 /* FIXME: the code in sleep doesn't use this, so there's no
265 rush to implement it. */
272 /* FIXME: Restore sig handler? */