(root)/
coreutils-9.4/
lib/
gettime-res.c
       1  /* Get the system clock resolution.
       2  
       3     Copyright 2021-2023 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 3 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 Paul Eggert.  */
      19  
      20  #include <config.h>
      21  
      22  #include "timespec.h"
      23  
      24  static long int _GL_ATTRIBUTE_CONST
      25  gcd (long int a, long int b)
      26  {
      27    while (b != 0)
      28      {
      29        long int r = a % b;
      30        a = b;
      31        b = r;
      32      }
      33    return a;
      34  }
      35  
      36  /* Return the system time resolution in nanoseconds.  */
      37  
      38  long int
      39  gettime_res (void)
      40  {
      41    struct timespec res;
      42  #if defined CLOCK_REALTIME && HAVE_CLOCK_GETRES
      43    clock_getres (CLOCK_REALTIME, &res);
      44  #elif defined HAVE_TIMESPEC_GETRES
      45    timespec_getres (&res, TIME_UTC);
      46  #else
      47    /* Guess high and let the later code deduce better.  */
      48    res.tv_sec = 1;
      49    res.tv_nsec = 0;
      50  #endif
      51  
      52    /* On all Gnulib platforms the following calculations do not overflow.  */
      53  
      54    long int hz = TIMESPEC_HZ;
      55    long int r = res.tv_nsec <= 0 ? hz : res.tv_nsec;
      56    struct timespec earlier = { .tv_nsec = -1 };
      57  
      58    /* On some platforms, clock_getres (CLOCK_REALTIME, ...) yields a
      59       too-large resolution, under the mistaken theory that it should
      60       return the timer interval.  For example, on AIX 7.2 POWER8
      61       clock_getres yields 10 ms even though clock_gettime yields 1 μs
      62       resolution.  Work around the problem with high probability by
      63       trying clock_gettime several times and observing the resulting
      64       bounds on resolution.  */
      65    int nsamples = 32;
      66    for (int i = 0; 1 < r && i < nsamples; i++)
      67      {
      68        /* If successive timestamps disagree the clock resolution must
      69           be small, so exit the inner loop to check this sample.
      70           Otherwise, arrange for the outer loop to exit but continue
      71           the inner-loop search for a differing timestamp sample.  */
      72        struct timespec now;
      73        for (;; i = nsamples)
      74          {
      75            now = current_timespec ();
      76            if (earlier.tv_nsec != now.tv_nsec || earlier.tv_sec != now.tv_sec)
      77              break;
      78          }
      79        earlier = now;
      80  
      81        if (0 < now.tv_nsec)
      82          r = gcd (r, now.tv_nsec);
      83      }
      84  
      85    return r;
      86  }
      87  
      88  /*
      89   * Hey Emacs!
      90   * Local Variables:
      91   * coding: utf-8
      92   * End:
      93   */