1 /* A variant of nanosleep that takes a 'double' argument and handles EINTR. 2 3 Copyright (C) 2002-2007, 2009-2021 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 /* Mostly written (for sleep.c) by Paul Eggert. 19 Factored out (creating this file) by Jim Meyering. */ 20 21 #include <config.h> 22 23 #include "xnanosleep.h" 24 25 #include <intprops.h> 26 #include <timespec.h> 27 28 #include <errno.h> 29 #include <time.h> 30 #include <unistd.h> 31 32 /* Sleep until the time (call it WAKE_UP_TIME) specified as 33 SECONDS seconds after the time this function is called. 34 SECONDS must be non-negative. If SECONDS is so large that 35 it is not representable as a 'struct timespec', then use 36 the maximum value for that interval. Return -1 on failure 37 (setting errno), 0 on success. */ 38 39 int 40 xnanosleep (double seconds) /* */ 41 { 42 #if HAVE_PAUSE 43 if (1.0 + TYPE_MAXIMUM (time_t) <= seconds) 44 { 45 do 46 pause (); 47 while (errno == EINTR); 48 49 /* pause failed (!); fall back on repeated nanosleep calls. */ 50 } 51 #endif 52 53 struct timespec ts_sleep = dtotimespec (seconds); 54 55 for (;;) 56 { 57 /* Linux-2.6.8.1's nanosleep returns -1, but doesn't set errno 58 when resumed after being suspended. Earlier versions would 59 set errno to EINTR. nanosleep from linux-2.6.10, as well as 60 implementations by (all?) other vendors, doesn't return -1 61 in that case; either it continues sleeping (if time remains) 62 or it returns zero (if the wake-up time has passed). 63 64 Gnulib's replacement nanosleep sometimes does not update 65 TS_SLEEP, and it is possible some kernels have a similar bug. 66 However, this merely causes xnanosleep to sleep longer than 67 necessary, which is not a correctness bug. */ 68 errno = 0; 69 if (nanosleep (&ts_sleep, &ts_sleep) == 0) 70 break; 71 if (errno != EINTR && errno != 0) 72 return -1; 73 } 74 75 return 0; 76 }