(root)/
coreutils-9.4/
lib/
xnanosleep.c
       1  /* A variant of nanosleep that takes a 'double' argument and handles EINTR.
       2  
       3     Copyright (C) 2002-2007, 2009-2023 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  }