/src/wget2/lib/nanosleep.c
Line  | Count  | Source (jump to first uncovered line)  | 
1  |  | /* Provide a replacement for the POSIX nanosleep function.  | 
2  |  |  | 
3  |  |    Copyright (C) 1999-2000, 2002, 2004-2025 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  |  |  | 
27  |  | #include <stdio.h>  | 
28  |  | #include <sys/types.h>  | 
29  |  | #include <sys/select.h>  | 
30  |  | #include <signal.h>  | 
31  |  |  | 
32  |  | #include <errno.h>  | 
33  |  |  | 
34  |  | #include <unistd.h>  | 
35  |  |  | 
36  |  |  | 
37  |  | enum { BILLION = 1000 * 1000 * 1000 }; | 
38  |  |  | 
39  |  | #if HAVE_BUG_BIG_NANOSLEEP  | 
40  |  |  | 
41  |  | int  | 
42  |  | nanosleep (const struct timespec *requested_delay,  | 
43  |  |            struct timespec *remaining_delay)  | 
44  |  | # undef nanosleep  | 
45  | 0  | { | 
46  |  |   /* nanosleep mishandles large sleeps due to internal overflow problems.  | 
47  |  |      The worst known case of this is Linux 2.6.9 with glibc 2.3.4, which  | 
48  |  |      can't sleep more than 24.85 days (2^31 milliseconds).  Similarly,  | 
49  |  |      cygwin 1.5.x, which can't sleep more than 49.7 days (2^32 milliseconds).  | 
50  |  |      Solve this by breaking the sleep up into smaller chunks.  */  | 
51  |  | 
  | 
52  | 0  |   if (requested_delay->tv_nsec < 0 || BILLION <= requested_delay->tv_nsec)  | 
53  | 0  |     { | 
54  | 0  |       errno = EINVAL;  | 
55  | 0  |       return -1;  | 
56  | 0  |     }  | 
57  |  |  | 
58  | 0  |   { | 
59  |  |     /* Verify that time_t is large enough.  */  | 
60  | 0  |     static_assert (TYPE_MAXIMUM (time_t) / 24 / 24 / 60 / 60);  | 
61  | 0  |     const time_t limit = 24 * 24 * 60 * 60;  | 
62  | 0  |     time_t seconds = requested_delay->tv_sec;  | 
63  | 0  |     struct timespec intermediate = *requested_delay;  | 
64  |  | 
  | 
65  | 0  |     while (limit < seconds)  | 
66  | 0  |       { | 
67  | 0  |         int result;  | 
68  | 0  |         intermediate.tv_sec = limit;  | 
69  | 0  |         result = nanosleep (&intermediate, remaining_delay);  | 
70  | 0  |         seconds -= limit;  | 
71  | 0  |         if (result)  | 
72  | 0  |           { | 
73  | 0  |             if (remaining_delay)  | 
74  | 0  |               remaining_delay->tv_sec += seconds;  | 
75  | 0  |             return result;  | 
76  | 0  |           }  | 
77  | 0  |         intermediate.tv_nsec = 0;  | 
78  | 0  |       }  | 
79  | 0  |     intermediate.tv_sec = seconds;  | 
80  | 0  |     return nanosleep (&intermediate, remaining_delay);  | 
81  | 0  |   }  | 
82  | 0  | }  | 
83  |  |  | 
84  |  | #elif defined _WIN32 && ! defined __CYGWIN__  | 
85  |  | /* Native Windows platforms.  */  | 
86  |  |  | 
87  |  | # define WIN32_LEAN_AND_MEAN  | 
88  |  | # include <windows.h>  | 
89  |  |  | 
90  |  | /* The Windows API function Sleep() has a resolution of about 15 ms and takes  | 
91  |  |    at least 5 ms to execute.  We use this function for longer time periods.  | 
92  |  |    Additionally, we use busy-looping over short time periods, to get a  | 
93  |  |    resolution of about 0.01 ms.  In order to measure such short timespans,  | 
94  |  |    we use the QueryPerformanceCounter() function.  */  | 
95  |  |  | 
96  |  | int  | 
97  |  | nanosleep (const struct timespec *requested_delay,  | 
98  |  |            struct timespec *remaining_delay)  | 
99  |  | { | 
100  |  |   static bool initialized;  | 
101  |  |   /* Number of performance counter increments per nanosecond,  | 
102  |  |      or zero if it could not be determined.  */  | 
103  |  |   static double ticks_per_nanosecond;  | 
104  |  |  | 
105  |  |   if (requested_delay->tv_nsec < 0 || BILLION <= requested_delay->tv_nsec)  | 
106  |  |     { | 
107  |  |       errno = EINVAL;  | 
108  |  |       return -1;  | 
109  |  |     }  | 
110  |  |  | 
111  |  |   /* For requested delays of one second or more, 15ms resolution is  | 
112  |  |      sufficient.  */  | 
113  |  |   if (requested_delay->tv_sec == 0)  | 
114  |  |     { | 
115  |  |       if (!initialized)  | 
116  |  |         { | 
117  |  |           /* Initialize ticks_per_nanosecond.  */  | 
118  |  |           LARGE_INTEGER ticks_per_second;  | 
119  |  |  | 
120  |  |           if (QueryPerformanceFrequency (&ticks_per_second))  | 
121  |  |             ticks_per_nanosecond =  | 
122  |  |               (double) ticks_per_second.QuadPart / 1000000000.0;  | 
123  |  |  | 
124  |  |           initialized = true;  | 
125  |  |         }  | 
126  |  |       if (ticks_per_nanosecond)  | 
127  |  |         { | 
128  |  |           /* QueryPerformanceFrequency worked.  We can use  | 
129  |  |              QueryPerformanceCounter.  Use a combination of Sleep and  | 
130  |  |              busy-looping.  */  | 
131  |  |           /* Number of milliseconds to pass to the Sleep function.  | 
132  |  |              Since Sleep can take up to 8 ms less or 8 ms more than requested  | 
133  |  |              (or maybe more if the system is loaded), we subtract 10 ms.  */  | 
134  |  |           int sleep_millis = (int) requested_delay->tv_nsec / 1000000 - 10;  | 
135  |  |           /* Determine how many ticks to delay.  */  | 
136  |  |           LONGLONG wait_ticks = requested_delay->tv_nsec * ticks_per_nanosecond;  | 
137  |  |           /* Start.  */  | 
138  |  |           LARGE_INTEGER counter_before;  | 
139  |  |           if (QueryPerformanceCounter (&counter_before))  | 
140  |  |             { | 
141  |  |               /* Wait until the performance counter has reached this value.  | 
142  |  |                  We don't need to worry about overflow, because the performance  | 
143  |  |                  counter is reset at reboot, and with a frequency of 3.6E6  | 
144  |  |                  ticks per second 63 bits suffice for over 80000 years.  */  | 
145  |  |               LONGLONG wait_until = counter_before.QuadPart + wait_ticks;  | 
146  |  |               /* Use Sleep for the longest part.  */  | 
147  |  |               if (sleep_millis > 0)  | 
148  |  |                 Sleep (sleep_millis);  | 
149  |  |               /* Busy-loop for the rest.  */  | 
150  |  |               for (;;)  | 
151  |  |                 { | 
152  |  |                   LARGE_INTEGER counter_after;  | 
153  |  |                   if (!QueryPerformanceCounter (&counter_after))  | 
154  |  |                     /* QueryPerformanceCounter failed, but succeeded earlier.  | 
155  |  |                        Should not happen.  */  | 
156  |  |                     break;  | 
157  |  |                   if (counter_after.QuadPart >= wait_until)  | 
158  |  |                     /* The requested time has elapsed.  */  | 
159  |  |                     break;  | 
160  |  |                 }  | 
161  |  |               goto done;  | 
162  |  |             }  | 
163  |  |         }  | 
164  |  |     }  | 
165  |  |   /* Implementation for long delays and as fallback.  */  | 
166  |  |   Sleep (requested_delay->tv_sec * 1000 + requested_delay->tv_nsec / 1000000);  | 
167  |  |  | 
168  |  |  done:  | 
169  |  |   /* Sleep is not interruptible.  So there is no remaining delay.  */  | 
170  |  |   if (remaining_delay != NULL)  | 
171  |  |     { | 
172  |  |       remaining_delay->tv_sec = 0;  | 
173  |  |       remaining_delay->tv_nsec = 0;  | 
174  |  |     }  | 
175  |  |   return 0;  | 
176  |  | }  | 
177  |  |  | 
178  |  | #else  | 
179  |  | /* Other platforms lacking nanosleep.  | 
180  |  |    It's not clear whether these are still practical porting targets.  | 
181  |  |    For now, just fall back on pselect.  */  | 
182  |  |  | 
183  |  | /* Suspend execution for at least *REQUESTED_DELAY seconds.  The  | 
184  |  |    *REMAINING_DELAY part isn't implemented yet.  */  | 
185  |  |  | 
186  |  | int  | 
187  |  | nanosleep (const struct timespec *requested_delay,  | 
188  |  |            struct timespec *remaining_delay)  | 
189  |  | { | 
190  |  |   return pselect (0, NULL, NULL, NULL, requested_delay, NULL);  | 
191  |  | }  | 
192  |  | #endif  |