"Fossies" - the Fresh Open Source Software Archive

Member "gnuastro-0.8/bootstrapped/tests/nap.h" (28 Dec 2018, 4233 Bytes) of package /linux/privat/gnuastro-0.8.tar.lz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "nap.h": 0.7_vs_0.8.

    1 /* Assist in file system timestamp tests.
    2    Copyright (C) 2009-2018 Free Software Foundation, Inc.
    3 
    4    This program is free software: you can redistribute it and/or modify
    5    it under the terms of the GNU General Public License as published by
    6    the Free Software Foundation; either version 3 of the License, or
    7    (at your option) any later version.
    8 
    9    This program is distributed in the hope that it will be useful,
   10    but WITHOUT ANY WARRANTY; without even the implied warranty of
   11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12    GNU General Public License for more details.
   13 
   14    You should have received a copy of the GNU General Public License
   15    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
   16 
   17 /* Written by Eric Blake <ebb9@byu.net>, 2009.  */
   18 
   19 #ifndef GLTEST_NAP_H
   20 # define GLTEST_NAP_H
   21 
   22 # include <limits.h>
   23 # include <stdbool.h>
   24 
   25 # include <intprops.h>
   26 
   27 /* Name of the witness file.  */
   28 #define TEMPFILE BASE "nap.tmp"
   29 
   30 /* File descriptor used for the witness file.  */
   31 static int nap_fd = -1;
   32 
   33 /* Return A - B, in ns.
   34    Return 0 if the true result would be negative.
   35    Return INT_MAX if the true result would be greater than INT_MAX.  */
   36 static int
   37 diff_timespec (struct timespec a, struct timespec b)
   38 {
   39   time_t as = a.tv_sec;
   40   time_t bs = b.tv_sec;
   41   int ans = a.tv_nsec;
   42   int bns = b.tv_nsec;
   43   int sdiff;
   44 
   45   ASSERT (0 <= ans && ans < 2000000000);
   46   ASSERT (0 <= bns && bns < 2000000000);
   47 
   48   if (! (bs < as || (bs == as && bns < ans)))
   49     return 0;
   50 
   51   if (INT_SUBTRACT_WRAPV (as, bs, &sdiff)
   52       || INT_MULTIPLY_WRAPV (sdiff, 1000000000, &sdiff)
   53       || INT_ADD_WRAPV (sdiff, ans - bns, &sdiff))
   54     return INT_MAX;
   55 
   56   return sdiff;
   57 }
   58 
   59 /* If DO_WRITE, bump the modification time of the file designated by NAP_FD.
   60    Then fetch the new STAT information of NAP_FD.  */
   61 static void
   62 nap_get_stat (struct stat *st, int do_write)
   63 {
   64   if (do_write)
   65     {
   66       ASSERT (write (nap_fd, "\n", 1) == 1);
   67 #if defined _WIN32 || defined __CYGWIN__
   68       /* On Windows, the modification times are not changed until NAP_FD
   69          is closed. See
   70          https://msdn.microsoft.com/en-us/library/windows/desktop/aa365747(v=vs.85).aspx */
   71       close (nap_fd);
   72       nap_fd = open (TEMPFILE, O_RDWR, 0600);
   73       ASSERT (nap_fd != -1);
   74       lseek (nap_fd, 0, SEEK_END);
   75 #endif
   76     }
   77   ASSERT (fstat (nap_fd, st) == 0);
   78 }
   79 
   80 /* Given a file whose descriptor is FD, see whether delaying by DELAY
   81    nanoseconds causes a change in a file's mtime.
   82    OLD_ST is the file's status, recently gotten.  */
   83 static bool
   84 nap_works (int delay, struct stat old_st)
   85 {
   86   struct stat st;
   87   struct timespec delay_spec;
   88   delay_spec.tv_sec = delay / 1000000000;
   89   delay_spec.tv_nsec = delay % 1000000000;
   90   ASSERT (nanosleep (&delay_spec, 0) == 0);
   91   nap_get_stat (&st, 1);
   92 
   93   if (diff_timespec (get_stat_mtime (&st), get_stat_mtime (&old_st)))
   94     return true;
   95 
   96   return false;
   97 }
   98 
   99 static void
  100 clear_temp_file (void)
  101 {
  102   if (0 <= nap_fd)
  103     {
  104       ASSERT (close (nap_fd) != -1);
  105       ASSERT (unlink (TEMPFILE) != -1);
  106     }
  107 }
  108 
  109 /* Sleep long enough to notice a timestamp difference on the file
  110    system in the current directory.  Use an adaptive approach, trying
  111    to find the smallest delay which works on the current file system
  112    to make the timestamp difference appear.  Assert a maximum delay of
  113    ~2 seconds, more precisely sum(2^n) from 0 to 30 = 2^31 - 1 = 2.1s.
  114    Assumes that BASE is defined, and requires that the test module
  115    depends on nanosleep.  */
  116 static void
  117 nap (void)
  118 {
  119   struct stat old_st;
  120   static int delay = 1;
  121 
  122   if (-1 == nap_fd)
  123     {
  124       atexit (clear_temp_file);
  125       ASSERT ((nap_fd = creat (TEMPFILE, 0600)) != -1);
  126       nap_get_stat (&old_st, 0);
  127     }
  128   else
  129     {
  130       ASSERT (0 <= nap_fd);
  131       nap_get_stat (&old_st, 1);
  132     }
  133 
  134   if (1 < delay)
  135     delay = delay / 2;  /* Try half of the previous delay.  */
  136   ASSERT (0 < delay);
  137 
  138   for (;;)
  139     {
  140       if (nap_works (delay, old_st))
  141         return;
  142       if (delay <= (2147483647 - 1) / 2)
  143         {
  144           delay = delay * 2 + 1;
  145           continue;
  146         }
  147       else
  148         break;
  149     }
  150 
  151   /* Bummer: even the highest nap delay didn't work. */
  152   ASSERT (0);
  153 }
  154 
  155 #endif /* GLTEST_NAP_H */