VirtualBox

source: kBuild/vendor/grep/current/gnulib-tests/nap.h@ 3630

Last change on this file since 3630 was 3529, checked in by bird, 3 years ago

Imported grep 3.7 from grep-3.7.tar.gz (sha256: c22b0cf2d4f6bbe599c902387e8058990e1eee99aef333a203829e5fd3dbb342), applying minimal auto-props.

  • Property svn:eol-style set to native
File size: 4.4 KB
Line 
1/* Assist in file system timestamp tests.
2 Copyright (C) 2009-2021 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 <[email protected]>, 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/* Avoid a conflict with a function called nap() on UnixWare. */
28# if defined _SCO_DS || (defined __SCO_VERSION__ || defined __sysv5__) /* OpenServer, UnixWare */
29# include <unistd.h>
30# undef nap
31# define nap gl_nap
32# endif
33
34/* Name of the witness file. */
35#define TEMPFILE BASE "nap.tmp"
36
37/* File descriptor used for the witness file. */
38static int nap_fd = -1;
39
40/* Return A - B, in ns.
41 Return 0 if the true result would be negative.
42 Return INT_MAX if the true result would be greater than INT_MAX. */
43static int
44diff_timespec (struct timespec a, struct timespec b)
45{
46 time_t as = a.tv_sec;
47 time_t bs = b.tv_sec;
48 int ans = a.tv_nsec;
49 int bns = b.tv_nsec;
50 int sdiff;
51
52 ASSERT (0 <= ans && ans < 2000000000);
53 ASSERT (0 <= bns && bns < 2000000000);
54
55 if (! (bs < as || (bs == as && bns < ans)))
56 return 0;
57
58 if (INT_SUBTRACT_WRAPV (as, bs, &sdiff)
59 || INT_MULTIPLY_WRAPV (sdiff, 1000000000, &sdiff)
60 || INT_ADD_WRAPV (sdiff, ans - bns, &sdiff))
61 return INT_MAX;
62
63 return sdiff;
64}
65
66/* If DO_WRITE, bump the modification time of the file designated by NAP_FD.
67 Then fetch the new STAT information of NAP_FD. */
68static void
69nap_get_stat (struct stat *st, int do_write)
70{
71 if (do_write)
72 {
73 ASSERT (write (nap_fd, "\n", 1) == 1);
74#if defined _WIN32 || defined __CYGWIN__
75 /* On Windows, the modification times are not changed until NAP_FD
76 is closed. See
77 <https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-writefile> */
78 close (nap_fd);
79 nap_fd = open (TEMPFILE, O_RDWR, 0600);
80 ASSERT (nap_fd != -1);
81 lseek (nap_fd, 0, SEEK_END);
82#endif
83 }
84 ASSERT (fstat (nap_fd, st) == 0);
85}
86
87/* Given a file whose descriptor is FD, see whether delaying by DELAY
88 nanoseconds causes a change in a file's mtime.
89 OLD_ST is the file's status, recently gotten. */
90static bool
91nap_works (int delay, struct stat old_st)
92{
93 struct stat st;
94 struct timespec delay_spec;
95 delay_spec.tv_sec = delay / 1000000000;
96 delay_spec.tv_nsec = delay % 1000000000;
97 ASSERT (nanosleep (&delay_spec, 0) == 0);
98 nap_get_stat (&st, 1);
99
100 if (diff_timespec (get_stat_mtime (&st), get_stat_mtime (&old_st)))
101 return true;
102
103 return false;
104}
105
106static void
107clear_temp_file (void)
108{
109 if (0 <= nap_fd)
110 {
111 ASSERT (close (nap_fd) != -1);
112 ASSERT (unlink (TEMPFILE) != -1);
113 }
114}
115
116/* Sleep long enough to notice a timestamp difference on the file
117 system in the current directory. Use an adaptive approach, trying
118 to find the smallest delay which works on the current file system
119 to make the timestamp difference appear. Assert a maximum delay of
120 ~2 seconds, more precisely sum(2^n) from 0 to 30 = 2^31 - 1 = 2.1s.
121 Assumes that BASE is defined, and requires that the test module
122 depends on nanosleep. */
123static void
124nap (void)
125{
126 struct stat old_st;
127 static int delay = 1;
128
129 if (-1 == nap_fd)
130 {
131 atexit (clear_temp_file);
132 ASSERT ((nap_fd = creat (TEMPFILE, 0600)) != -1);
133 nap_get_stat (&old_st, 0);
134 }
135 else
136 {
137 ASSERT (0 <= nap_fd);
138 nap_get_stat (&old_st, 1);
139 }
140
141 if (1 < delay)
142 delay = delay / 2; /* Try half of the previous delay. */
143 ASSERT (0 < delay);
144
145 for (;;)
146 {
147 if (nap_works (delay, old_st))
148 return;
149 if (delay <= (2147483647 - 1) / 2)
150 {
151 delay = delay * 2 + 1;
152 continue;
153 }
154 else
155 break;
156 }
157
158 /* Bummer: even the highest nap delay didn't work. */
159 ASSERT (0);
160}
161
162#endif /* GLTEST_NAP_H */
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette