VirtualBox

source: kBuild/vendor/grep/current/gnulib-tests/nanosleep.c

Last change on this file was 3529, checked in by bird, 3 years ago

Imported grep 3.7 from grep-3.7.tar.gz (sha256: c22b0cf2d4f6bbe599c902387e8058990e1eee99aef333a203829e5fd3dbb342), applying minimal auto-props.

  • Property svn:eol-style set to native
File size: 8.0 KB
Line 
1/* Provide a replacement for the POSIX nanosleep function.
2
3 Copyright (C) 1999-2000, 2002, 2004-2021 Free Software Foundation, Inc.
4
5 This file is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as
7 published by the Free Software Foundation; either version 2.1 of the
8 License, or (at your option) any later version.
9
10 This file 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 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser 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)
57 {
58 errno = EINVAL;
59 return -1;
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)
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/* 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 _GL_ASYNC_SAFE 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
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette