1 /* Provide a replacement for the POSIX nanosleep function.
3 Copyright (C) 1999-2000, 2002, 2004-2010 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 <http://www.gnu.org/licenses/>. */
18 /* written by Jim Meyering
19 and Bruno Haible for the Woe32 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
51 problems. The worst known case of this is cygwin 1.5.x, which
52 can't sleep more than 49.7 days (2**32 milliseconds). Solve this
53 by breaking the sleep up into smaller chunks. */
55 if (requested_delay->tv_nsec < 0 || BILLION <= requested_delay->tv_nsec)
62 /* Verify that time_t is large enough. */
63 verify (TYPE_MAXIMUM (time_t) / 49 / 24 / 60 / 60);
64 const time_t limit = 49 * 24 * 60 * 60;
65 time_t seconds = requested_delay->tv_sec;
66 struct timespec intermediate;
67 intermediate.tv_nsec = 0;
69 while (limit < seconds)
72 intermediate.tv_sec = limit;
73 result = nanosleep (&intermediate, remaining_delay);
79 remaining_delay->tv_sec += seconds;
80 remaining_delay->tv_nsec += requested_delay->tv_nsec;
81 if (BILLION <= requested_delay->tv_nsec)
83 remaining_delay->tv_sec++;
84 remaining_delay->tv_nsec -= BILLION;
90 intermediate.tv_sec = seconds;
91 intermediate.tv_nsec = requested_delay->tv_nsec;
92 return nanosleep (&intermediate, remaining_delay);
96 #elif (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
97 /* Windows platforms. */
99 # define WIN32_LEAN_AND_MEAN
100 # include <windows.h>
102 /* The Win32 function Sleep() has a resolution of about 15 ms and takes
103 at least 5 ms to execute. We use this function for longer time periods.
104 Additionally, we use busy-looping over short time periods, to get a
105 resolution of about 0.01 ms. In order to measure such short timespans,
106 we use the QueryPerformanceCounter() function. */
109 nanosleep (const struct timespec *requested_delay,
110 struct timespec *remaining_delay)
112 static bool initialized;
113 /* Number of performance counter increments per nanosecond,
114 or zero if it could not be determined. */
115 static double ticks_per_nanosecond;
117 if (requested_delay->tv_nsec < 0 || BILLION <= requested_delay->tv_nsec)
123 /* For requested delays of one second or more, 15ms resolution is
125 if (requested_delay->tv_sec == 0)
129 /* Initialize ticks_per_nanosecond. */
130 LARGE_INTEGER ticks_per_second;
132 if (QueryPerformanceFrequency (&ticks_per_second))
133 ticks_per_nanosecond =
134 (double) ticks_per_second.QuadPart / 1000000000.0;
138 if (ticks_per_nanosecond)
140 /* QueryPerformanceFrequency worked. We can use
141 QueryPerformanceCounter. Use a combination of Sleep and
143 /* Number of milliseconds to pass to the Sleep function.
144 Since Sleep can take up to 8 ms less or 8 ms more than requested
145 (or maybe more if the system is loaded), we subtract 10 ms. */
146 int sleep_millis = (int) requested_delay->tv_nsec / 1000000 - 10;
147 /* Determine how many ticks to delay. */
148 LONGLONG wait_ticks = requested_delay->tv_nsec * ticks_per_nanosecond;
150 LARGE_INTEGER counter_before;
151 if (QueryPerformanceCounter (&counter_before))
153 /* Wait until the performance counter has reached this value.
154 We don't need to worry about overflow, because the performance
155 counter is reset at reboot, and with a frequency of 3.6E6
156 ticks per second 63 bits suffice for over 80000 years. */
157 LONGLONG wait_until = counter_before.QuadPart + wait_ticks;
158 /* Use Sleep for the longest part. */
159 if (sleep_millis > 0)
160 Sleep (sleep_millis);
161 /* Busy-loop for the rest. */
164 LARGE_INTEGER counter_after;
165 if (!QueryPerformanceCounter (&counter_after))
166 /* QueryPerformanceCounter failed, but succeeded earlier.
167 Should not happen. */
169 if (counter_after.QuadPart >= wait_until)
170 /* The requested time has elapsed. */
177 /* Implementation for long delays and as fallback. */
178 Sleep (requested_delay->tv_sec * 1000 + requested_delay->tv_nsec / 1000000);
181 /* Sleep is not interruptible. So there is no remaining delay. */
182 if (remaining_delay != NULL)
184 remaining_delay->tv_sec = 0;
185 remaining_delay->tv_nsec = 0;
191 /* Unix platforms lacking nanosleep. */
193 /* Some systems (MSDOS) don't have SIGCONT.
194 Using SIGTERM here turns the signal-handling code below
195 into a no-op on such systems. */
197 # define SIGCONT SIGTERM
200 static sig_atomic_t volatile suspended;
202 /* Handle SIGCONT. */
210 /* Suspend execution for at least *TS_DELAY seconds. */
213 my_usleep (const struct timespec *ts_delay)
215 struct timeval tv_delay;
216 tv_delay.tv_sec = ts_delay->tv_sec;
217 tv_delay.tv_usec = (ts_delay->tv_nsec + 999) / 1000;
218 if (tv_delay.tv_usec == 1000000)
220 time_t t1 = tv_delay.tv_sec + 1;
221 if (t1 < tv_delay.tv_sec)
222 tv_delay.tv_usec = 1000000 - 1; /* close enough */
225 tv_delay.tv_sec = t1;
226 tv_delay.tv_usec = 0;
229 select (0, NULL, NULL, NULL, &tv_delay);
232 /* Suspend execution for at least *REQUESTED_DELAY seconds. The
233 *REMAINING_DELAY part isn't implemented yet. */
236 nanosleep (const struct timespec *requested_delay,
237 struct timespec *remaining_delay)
239 static bool initialized;
241 if (requested_delay->tv_nsec < 0 || BILLION <= requested_delay->tv_nsec)
247 /* set up sig handler */
250 struct sigaction oldact;
252 sigaction (SIGCONT, NULL, &oldact);
253 if (get_handler (&oldact) != SIG_IGN)
255 struct sigaction newact;
257 newact.sa_handler = sighandler;
258 sigemptyset (&newact.sa_mask);
260 sigaction (SIGCONT, &newact, NULL);
267 my_usleep (requested_delay);
271 /* Calculate time remaining. */
272 /* FIXME: the code in sleep doesn't use this, so there's no
273 rush to implement it. */
278 /* FIXME: Restore sig handler? */