nanosleep: Make replacement POSIX compliant.
[gnulib.git] / lib / nanosleep.c
1 /* Provide a replacement for the POSIX nanosleep function.
2
3    Copyright (C) 1999-2000, 2002, 2004-2010 Free Software Foundation, Inc.
4
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.
9
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.
14
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/>.  */
17
18 /* written by Jim Meyering
19    and Bruno Haible for the Woe32 part */
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   /* 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.  */
54
55   if (requested_delay->tv_nsec < 0 || BILLION <= requested_delay->tv_nsec)
56     {
57       errno = EINVAL;
58       return -1;
59     }
60
61   {
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;
68
69     while (limit < seconds)
70       {
71         int result;
72         intermediate.tv_sec = limit;
73         result = nanosleep (&intermediate, remaining_delay);
74         seconds -= limit;
75         if (result)
76           {
77             if (remaining_delay)
78               {
79                 remaining_delay->tv_sec += seconds;
80                 remaining_delay->tv_nsec += requested_delay->tv_nsec;
81                 if (BILLION <= requested_delay->tv_nsec)
82                   {
83                     remaining_delay->tv_sec++;
84                     remaining_delay->tv_nsec -= BILLION;
85                   }
86               }
87             return result;
88           }
89       }
90     intermediate.tv_sec = seconds;
91     intermediate.tv_nsec = requested_delay->tv_nsec;
92     return nanosleep (&intermediate, remaining_delay);
93   }
94 }
95
96 #elif (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
97 /* Windows platforms.  */
98
99 # define WIN32_LEAN_AND_MEAN
100 # include <windows.h>
101
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.  */
107
108 int
109 nanosleep (const struct timespec *requested_delay,
110            struct timespec *remaining_delay)
111 {
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;
116
117   if (requested_delay->tv_nsec < 0 || BILLION <= requested_delay->tv_nsec)
118     {
119       errno = EINVAL;
120       return -1;
121     }
122
123   /* For requested delays of one second or more, 15ms resolution is
124      sufficient.  */
125   if (requested_delay->tv_sec == 0)
126     {
127       if (!initialized)
128         {
129           /* Initialize ticks_per_nanosecond.  */
130           LARGE_INTEGER ticks_per_second;
131
132           if (QueryPerformanceFrequency (&ticks_per_second))
133             ticks_per_nanosecond =
134               (double) ticks_per_second.QuadPart / 1000000000.0;
135
136           initialized = true;
137         }
138       if (ticks_per_nanosecond)
139         {
140           /* QueryPerformanceFrequency worked.  We can use
141              QueryPerformanceCounter.  Use a combination of Sleep and
142              busy-looping.  */
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;
149           /* Start.  */
150           LARGE_INTEGER counter_before;
151           if (QueryPerformanceCounter (&counter_before))
152             {
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.  */
162               for (;;)
163                 {
164                   LARGE_INTEGER counter_after;
165                   if (!QueryPerformanceCounter (&counter_after))
166                     /* QueryPerformanceCounter failed, but succeeded earlier.
167                        Should not happen.  */
168                     break;
169                   if (counter_after.QuadPart >= wait_until)
170                     /* The requested time has elapsed.  */
171                     break;
172                 }
173               goto done;
174             }
175         }
176     }
177   /* Implementation for long delays and as fallback.  */
178   Sleep (requested_delay->tv_sec * 1000 + requested_delay->tv_nsec / 1000000);
179
180  done:
181   /* Sleep is not interruptible.  So there is no remaining delay.  */
182   if (remaining_delay != NULL)
183     {
184       remaining_delay->tv_sec = 0;
185       remaining_delay->tv_nsec = 0;
186     }
187   return 0;
188 }
189
190 #else
191 /* Unix platforms lacking nanosleep. */
192
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. */
196 # ifndef SIGCONT
197 #  define SIGCONT SIGTERM
198 # endif
199
200 static sig_atomic_t volatile suspended;
201
202 /* Handle SIGCONT. */
203
204 static void
205 sighandler (int sig)
206 {
207   suspended = 1;
208 }
209
210 /* Suspend execution for at least *TS_DELAY seconds.  */
211
212 static void
213 my_usleep (const struct timespec *ts_delay)
214 {
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)
219     {
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 */
223       else
224         {
225           tv_delay.tv_sec = t1;
226           tv_delay.tv_usec = 0;
227         }
228     }
229   select (0, NULL, NULL, NULL, &tv_delay);
230 }
231
232 /* Suspend execution for at least *REQUESTED_DELAY seconds.  The
233    *REMAINING_DELAY part isn't implemented yet.  */
234
235 int
236 nanosleep (const struct timespec *requested_delay,
237            struct timespec *remaining_delay)
238 {
239   static bool initialized;
240
241   if (requested_delay->tv_nsec < 0 || BILLION <= requested_delay->tv_nsec)
242     {
243       errno = EINVAL;
244       return -1;
245     }
246
247   /* set up sig handler */
248   if (! initialized)
249     {
250       struct sigaction oldact;
251
252       sigaction (SIGCONT, NULL, &oldact);
253       if (get_handler (&oldact) != SIG_IGN)
254         {
255           struct sigaction newact;
256
257           newact.sa_handler = sighandler;
258           sigemptyset (&newact.sa_mask);
259           newact.sa_flags = 0;
260           sigaction (SIGCONT, &newact, NULL);
261         }
262       initialized = true;
263     }
264
265   suspended = 0;
266
267   my_usleep (requested_delay);
268
269   if (suspended)
270     {
271       /* Calculate time remaining.  */
272       /* FIXME: the code in sleep doesn't use this, so there's no
273          rush to implement it.  */
274
275       errno = EINTR;
276     }
277
278   /* FIXME: Restore sig handler?  */
279
280   return suspended;
281 }
282 #endif