OpenCoverage

nanosleep.c

Absolute File Name:/home/opencoverage/opencoverage/guest-scripts/coreutils/src/gnulib/lib/nanosleep.c
Source codeSwitch to Preprocessed file
LineSourceCount
1/* Provide a replacement for the POSIX nanosleep function.-
2-
3 Copyright (C) 1999-2000, 2002, 2004-2018 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 <https://www.gnu.org/licenses/>. */-
17-
18/* written by Jim Meyering-
19 and Bruno Haible for the native Windows 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-
41enum { BILLION = 1000 * 1000 * 1000 };-
42-
43#if HAVE_BUG_BIG_NANOSLEEP-
44-
45int-
46nanosleep (const struct timespec *requested_delay,-
47 struct timespec *remaining_delay)-
48# undef nanosleep-
49{-
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. */-
55-
56 if (requested_delay->tv_nsec < 0 || BILLION <= requested_delay->tv_nsec)
requested_delay->tv_nsec < 0Description
TRUEnever evaluated
FALSEevaluated 459 times by 2 tests
Evaluated by:
  • sleep
  • tail
BILLION <= req...delay->tv_nsecDescription
TRUEnever evaluated
FALSEevaluated 459 times by 2 tests
Evaluated by:
  • sleep
  • tail
0-459
57 {-
58 errno = EINVAL;-
59 return -1;
never executed: return -1;
0
60 }-
61-
62 {-
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;-
69-
70 while (limit < seconds)
limit < secondsDescription
TRUEevaluated 2 times by 1 test
Evaluated by:
  • sleep
FALSEevaluated 457 times by 2 tests
Evaluated by:
  • sleep
  • tail
2-457
71 {-
72 int result;-
73 intermediate.tv_sec = limit;-
74 result = nanosleep (&intermediate, remaining_delay);-
75 seconds -= limit;-
76 if (result)
resultDescription
TRUEnever evaluated
FALSEnever evaluated
0
77 {-
78 if (remaining_delay)
remaining_delayDescription
TRUEnever evaluated
FALSEnever evaluated
0
79 remaining_delay->tv_sec += seconds;
never executed: remaining_delay->tv_sec += seconds;
0
80 return result;
never executed: return result;
0
81 }-
82 intermediate.tv_nsec = 0;-
83 }
never executed: end of block
0
84 intermediate.tv_sec = seconds;-
85 return nanosleep (&intermediate, remaining_delay);
executed 457 times by 2 tests: return nanosleep (&intermediate, remaining_delay);
Executed by:
  • sleep
  • tail
457
86 }-
87}-
88-
89#elif (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__-
90/* Native Windows platforms. */-
91-
92# define WIN32_LEAN_AND_MEAN-
93# include <windows.h>-
94-
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. */-
100-
101int-
102nanosleep (const struct timespec *requested_delay,-
103 struct timespec *remaining_delay)-
104{-
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;-
109-
110 if (requested_delay->tv_nsec < 0 || BILLION <= requested_delay->tv_nsec)-
111 {-
112 errno = EINVAL;-
113 return -1;-
114 }-
115-
116 /* For requested delays of one second or more, 15ms resolution is-
117 sufficient. */-
118 if (requested_delay->tv_sec == 0)-
119 {-
120 if (!initialized)-
121 {-
122 /* Initialize ticks_per_nanosecond. */-
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 /* QueryPerformanceFrequency worked. We can use-
134 QueryPerformanceCounter. Use a combination of Sleep and-
135 busy-looping. */-
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;-
142 /* Start. */-
143 LARGE_INTEGER counter_before;-
144 if (QueryPerformanceCounter (&counter_before))-
145 {-
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. */-
155 for (;;)-
156 {-
157 LARGE_INTEGER counter_after;-
158 if (!QueryPerformanceCounter (&counter_after))-
159 /* QueryPerformanceCounter failed, but succeeded earlier.-
160 Should not happen. */-
161 break;-
162 if (counter_after.QuadPart >= wait_until)-
163 /* The requested time has elapsed. */-
164 break;-
165 }-
166 goto done;-
167 }-
168 }-
169 }-
170 /* Implementation for long delays and as fallback. */-
171 Sleep (requested_delay->tv_sec * 1000 + requested_delay->tv_nsec / 1000000);-
172-
173 done:-
174 /* Sleep is not interruptible. So there is no remaining delay. */-
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/* Unix platforms lacking nanosleep. */-
185-
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. */-
189# ifndef SIGCONT-
190# define SIGCONT SIGTERM-
191# endif-
192-
193static sig_atomic_t volatile suspended;-
194-
195/* Handle SIGCONT. */-
196-
197static void-
198sighandler (int sig)-
199{-
200 suspended = 1;-
201}-
202-
203/* Suspend execution for at least *TS_DELAY seconds. */-
204-
205static int-
206my_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; /* close enough */-
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/* Suspend execution for at least *REQUESTED_DELAY seconds. The-
225 *REMAINING_DELAY part isn't implemented yet. */-
226-
227int-
228nanosleep (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 /* set up sig handler */-
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 /* Calculate time remaining. */-
264 /* FIXME: the code in sleep doesn't use this, so there's no-
265 rush to implement it. */-
266-
267 errno = EINTR;-
268 }-
269 return -1;-
270 }-
271-
272 /* FIXME: Restore sig handler? */-
273-
274 return 0;-
275}-
276#endif-
Source codeSwitch to Preprocessed file

Generated by Squish Coco 4.1.2