This source file includes following definitions.
- diff_timespec
- nap_get_stat
- nap_works
- clear_temp_file
- nap
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
28 # if defined _SCO_DS || (defined __SCO_VERSION__ || defined __sysv5__)
29 # include <unistd.h>
30 # undef nap
31 # define nap gl_nap
32 # endif
33
34
35 #define TEMPFILE BASE "nap.tmp"
36
37
38 static int nap_fd = -1;
39
40
41
42
43 static int
44 diff_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
67
68 static void
69 nap_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
76
77
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
88
89
90 static bool
91 nap_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
106 static void
107 clear_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
117
118
119
120
121
122
123 static void
124 nap (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;
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
159 ASSERT (0);
160 }
161
162 #endif