16 struct timespec request;
17 volatile int *release, ready, entered, done;
18 int64_t deadline_delay, started, finished, realtime_started, realtime_finished;
20static void wait_done(
void* argument) {
21 __atomic_store_n((
volatile int*)argument, 1, __ATOMIC_RELEASE);
25 pthread_cleanup_push(wait_done, (
void*)&
waiter->done);
26 __atomic_store_n(&
waiter->ready, 1, __ATOMIC_RELEASE);
27 if (!
waiter->release || st_wait(
waiter->release, 5000) == 0) {
28 waiter->started = st_now(CLOCK_MONOTONIC);
29 waiter->realtime_started = st_now(CLOCK_REALTIME);
30 if (
waiter->deadline_delay)
31 waiter->request = st_timespec(
34 __atomic_store_n(&
waiter->entered, 1, __ATOMIC_RELEASE);
36 waiter->finished = st_now(CLOCK_MONOTONIC);
37 waiter->realtime_finished = st_now(CLOCK_REALTIME);
39 waiter->result = ETIMEDOUT;
41 pthread_cleanup_pop(1);
46 int64_t before_real, before_mono, target, after_real, after_mono, observed_real, observed_mono;
48static void diagnose_backward(
const char* stage,
const struct clock_wait waits[3],
51 "SIGNAL-TIMER-CONTRACT: clock backward stage=%s real=%lld mono=%lld "
52 "jump_before=%lld/%lld target=%lld jump_after=%lld/%lld observed=%lld/%lld\n",
53 stage, (
long long)st_now(CLOCK_REALTIME), (
long long)st_now(CLOCK_MONOTONIC),
54 (
long long)jump->before_real, (
long long)jump->before_mono, (
long long)jump->target,
55 (
long long)jump->after_real, (
long long)jump->after_mono, (
long long)jump->observed_real,
56 (
long long)jump->observed_mono);
57 for (
int n = 0; n < 3; ++n) {
58 const int entered = __atomic_load_n(&waits[n].entered, __ATOMIC_ACQUIRE);
59 const int done = __atomic_load_n(&waits[n].done, __ATOMIC_ACQUIRE);
63 "SIGNAL-TIMER-CONTRACT: clock worker=%d clock=%d flags=%d ready=%d entered=%d "
64 "done=%d result=%d start=%lld/%lld finish=%lld/%lld request=%lld.%09ld\n",
65 n, (
int)waits[n].clock, waits[n].flags, __atomic_load_n(&waits[n].ready, __ATOMIC_ACQUIRE),
66 entered, done, done ? waits[n].result : -1,
67 entered ? (long long)waits[n].realtime_started : -1,
68 entered ? (long long)waits[n].started : -1,
69 done ? (long long)waits[n].realtime_finished : -1, done ? (long long)waits[n].finished : -1,
70 entered ? (long long)waits[n].request.tv_sec : -1, entered ? waits[n].request.tv_nsec : 0L);
73static int restore_clock(int64_t realtime, int64_t monotonic) {
74 struct timespec target = st_timespec(realtime + st_now(CLOCK_MONOTONIC) - monotonic);
75 return clock_settime(CLOCK_REALTIME, &target);
80 int sending, result, error;
81 struct timespec deadline;
82 volatile int entered, done;
88 pthread_cleanup_push(wait_done, (
void*)&
waiter->done);
89 __atomic_store_n(&
waiter->entered, 1, __ATOMIC_RELEASE);
91 ? mq_timedsend(
waiter->queue,
"x", 1, 1, &
waiter->deadline)
92 : mq_timedreceive(
waiter->queue, &byte, 1, NULL, &
waiter->deadline);
94 waiter->finished = st_now(CLOCK_MONOTONIC);
95 pthread_cleanup_pop(1);
98static int mqueue_clock_change(
void) {
99 int failed = 0, changed = 0, active[2] = {0};
100 pthread_t workers[2];
101 struct mqueue_wait waits[2] = {{.queue = (mqd_t)-1}, {.queue = (mqd_t)-1, .sending = 1}};
103 struct mq_attr attributes = {.mq_maxmsg = 1, .mq_msgsize = 1}, observed;
104 const int64_t realtime = st_now(CLOCK_REALTIME), monotonic = st_now(CLOCK_MONOTONIC);
105 for (
int n = 0; n < 2; ++n)
106 snprintf(names[n],
sizeof(names[n]),
"/clock-contract-%ld-%d", (
long)getpid(), n);
107 for (
int n = 0; n < 2; ++n) {
108 waits[n].queue = mq_open(names[n], O_CREAT | O_EXCL | O_RDWR, 0600, &attributes);
109 CHECK(waits[n].queue != (mqd_t)-1);
110 waits[n].deadline = st_timespec(st_now(CLOCK_REALTIME) + 5000000000);
112 CHECK(mq_send(waits[n].queue,
"q", 1, 7) == 0);
113 CHECK(pthread_create(&workers[n], NULL,
mqueue_wait, &waits[n]) == 0);
115 CHECK(st_wait(&waits[n].entered, 1000) == 0);
118 CHECK(!__atomic_load_n(&waits[0].done, __ATOMIC_ACQUIRE) &&
119 !__atomic_load_n(&waits[1].done, __ATOMIC_ACQUIRE));
120 struct timespec target = st_timespec(st_now(CLOCK_REALTIME) + 10000000000);
121 const int64_t jumped = st_now(CLOCK_MONOTONIC);
122 CHECK(clock_settime(CLOCK_REALTIME, &target) == 0);
124 for (
int n = 0; n < 2; ++n) {
125 CHECK(st_wait(&waits[n].done, 500) == 0);
126 CHECK(waits[n].result == -1 && waits[n].error == ETIMEDOUT);
128 CHECK(waits[n].finished - jumped >= 0 && waits[n].finished - jumped < 500000000);
129 CHECK(pthread_join(workers[n], NULL) == 0);
131 CHECK(mq_getattr(waits[n].queue, &observed) == 0 && observed.mq_curmsgs == n);
132 attributes.mq_flags = O_NONBLOCK;
133 CHECK(mq_setattr(waits[n].queue, &attributes, NULL) == 0);
137 CHECK(mq_receive(waits[0].queue, &
byte, 1, NULL) == -1 && errno == EAGAIN);
138 CHECK(mq_receive(waits[1].queue, &
byte, 1, &priority) == 1 &&
byte ==
'q' && priority == 7);
139 CHECK(mq_receive(waits[1].queue, &
byte, 1, NULL) == -1 && errno == EAGAIN);
141 if (changed && restore_clock(realtime, monotonic))
143 for (
int n = 0; n < 2; ++n)
144 if (waits[n].queue != (mqd_t)-1)
146 for (
int n = 0; n < 2; ++n) {
148 pthread_cancel(workers[n]);
149 if (st_wait(&waits[n].done, 1000) == 0)
150 pthread_join(workers[n], NULL);
154 if (waits[n].queue != (mqd_t)-1)
155 mq_close(waits[n].queue);
160int signal_timer_test_clock(
void) {
161 int failed = 0, changed = 0, active[3] = {0}, timer_live[3] = {0};
162 volatile int release = 0;
163 const char* backward_stage = NULL;
165 pthread_t workers[3];
168 struct sigevent event = {.sigev_notify = SIGEV_NONE};
169 struct itimerspec setting = {0}, observed;
170 const int64_t realtime = st_now(CLOCK_REALTIME), monotonic = st_now(CLOCK_MONOTONIC);
171 struct timespec target = st_timespec(realtime), invalid = {0, 1000000000};
172 void* bad = mmap(NULL, 4096, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
173 CHECK(realtime > 20000000000 && monotonic >= 0 && bad != MAP_FAILED);
174 CHECK(clock_settime(CLOCK_MONOTONIC, &target) == -1 && errno == EINVAL);
175 CHECK(clock_settime(CLOCK_REALTIME, &invalid) == -1 && errno == EINVAL);
176 CHECK(clock_settime(CLOCK_REALTIME, bad) == -1 && errno == EFAULT);
177 if (geteuid() != 0) {
178 CHECK(clock_settime(CLOCK_REALTIME, &target) == -1 && errno == EPERM);
179 puts(
"SIGNAL-TIMER-CONTRACT: SKIP clock changes require uid 0");
182 pid_t child = fork();
188 _exit(clock_settime(CLOCK_REALTIME, &target) == -1 && errno == EPERM ? 0 : 11);
190 CHECK(st_reap(child, 6000) == 0);
191 CHECK(mqueue_clock_change() == 0);
193 int64_t before_real = st_now(CLOCK_REALTIME), before_mono = st_now(CLOCK_MONOTONIC);
194 target = st_timespec(before_real + 10000000000);
195 CHECK(clock_settime(CLOCK_REALTIME, &target) == 0);
197 CHECK(st_now(CLOCK_REALTIME) >= before_real + 10000000000 &&
198 st_now(CLOCK_REALTIME) < before_real + 12000000000);
199 CHECK(st_now(CLOCK_MONOTONIC) >= before_mono &&
200 st_now(CLOCK_MONOTONIC) - before_mono < 2000000000);
201 target = st_timespec(before_real - 10000000000);
202 CHECK(clock_settime(CLOCK_REALTIME, &target) == 0);
203 CHECK(st_now(CLOCK_REALTIME) >= before_real - 10000000000 &&
204 st_now(CLOCK_REALTIME) < before_real - 8000000000);
205 CHECK(restore_clock(realtime, monotonic) == 0);
208 target = (
struct timespec){9223372036, 250000000};
209 CHECK(clock_settime(CLOCK_REALTIME, &target) == 0);
210 struct timespec past = {9223372036, 0};
211 before_mono = st_now(CLOCK_MONOTONIC);
212 CHECK(clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &past, NULL) == 0);
213 CHECK(st_now(CLOCK_MONOTONIC) - before_mono < 300000000);
214 CHECK(restore_clock(realtime, monotonic) == 0);
216 backward_stage =
"prepare";
218 .clock = CLOCK_REALTIME, .flags = TIMER_ABSTIME, .deadline_delay = 1000000000};
220 .clock = CLOCK_MONOTONIC, .flags = TIMER_ABSTIME, .deadline_delay = 250000000};
221 waits[2] = (
struct clock_wait){.clock = CLOCK_REALTIME, .request = {0, 250000000}};
222 for (
int n = 0; n < 3; ++n) {
223 waits[n].release = &release;
224 CHECK(pthread_create(&workers[n], NULL,
clock_wait, &waits[n]) == 0);
226 CHECK(st_wait(&waits[n].ready, 1000) == 0);
230 backward_stage =
"start";
231 __atomic_store_n(&release, 1, __ATOMIC_RELEASE);
232 for (
int n = 0; n < 3; ++n)
233 CHECK(st_wait(&waits[n].entered, 1000) == 0);
235 backward_stage =
"before-jump";
236 jump.before_real = st_now(CLOCK_REALTIME);
237 jump.before_mono = st_now(CLOCK_MONOTONIC);
238 const int64_t original_deadline =
239 (int64_t)waits[0].request.tv_sec * 1000000000 + waits[0].request.tv_nsec;
240 CHECK(original_deadline - jump.before_real >= 500000000);
241 CHECK(__atomic_load_n(&waits[0].done, __ATOMIC_ACQUIRE) == 0);
242 jump.target = jump.before_real - 3000000000;
243 target = st_timespec(jump.target);
244 CHECK(clock_settime(CLOCK_REALTIME, &target) == 0);
245 jump.after_real = st_now(CLOCK_REALTIME);
246 jump.after_mono = st_now(CLOCK_MONOTONIC);
247 backward_stage =
"after-jump";
249 jump.observed_real = st_now(CLOCK_REALTIME);
250 jump.observed_mono = st_now(CLOCK_MONOTONIC);
253 CHECK(jump.observed_mono - waits[0].started >= waits[0].deadline_delay);
254 CHECK(jump.observed_real < original_deadline);
255 CHECK(__atomic_load_n(&waits[0].done, __ATOMIC_ACQUIRE) == 0);
256 backward_stage =
"unaffected-waits";
257 for (
int n = 1; n < 3; ++n) {
258 CHECK(st_wait(&waits[n].done, 1000) == 0 && waits[n].result == 0);
259 CHECK(waits[n].finished - waits[n].started >= 200000000 &&
260 waits[n].finished - waits[n].started < 2000000000);
262 backward_stage =
"restore";
263 CHECK(restore_clock(realtime, monotonic) == 0);
264 CHECK(st_wait(&waits[0].done, 1500) == 0 && waits[0].result == 0);
265 for (
int n = 0; n < 3; ++n) {
266 CHECK(pthread_join(workers[n], NULL) == 0);
269 backward_stage = NULL;
271 waits[0] = (
struct clock_wait){.clock = CLOCK_REALTIME,
272 .flags = TIMER_ABSTIME,
273 .request = st_timespec(st_now(CLOCK_REALTIME) + 5000000000)};
274 CHECK(pthread_create(&workers[0], NULL,
clock_wait, &waits[0]) == 0);
276 CHECK(st_wait(&waits[0].entered, 1000) == 0);
277 for (
int n = 0; n < 3; ++n) {
278 CHECK(timer_create(n == 2 ? CLOCK_MONOTONIC : CLOCK_REALTIME, &event, &timers[n]) == 0);
280 setting.it_value = n == 0 ? waits[0].request : (
struct timespec){3, 0};
281 CHECK(timer_settime(timers[n], n == 0 ? TIMER_ABSTIME : 0, &setting, NULL) == 0);
284 target = st_timespec(st_now(CLOCK_REALTIME) + 10000000000);
285 before_mono = st_now(CLOCK_MONOTONIC);
286 CHECK(clock_settime(CLOCK_REALTIME, &target) == 0);
287 CHECK(st_wait(&waits[0].done, 1500) == 0 && waits[0].result == 0);
288 CHECK(st_now(CLOCK_MONOTONIC) - before_mono < 1500000000);
289 CHECK(pthread_join(workers[0], NULL) == 0);
291 CHECK(timer_gettime(timers[0], &observed) == 0 && observed.it_value.tv_sec == 0 &&
292 observed.it_value.tv_nsec == 0);
293 for (
int n = 1; n < 3; ++n)
294 CHECK(timer_gettime(timers[n], &observed) == 0 && observed.it_value.tv_sec >= 1);
297 if (failed && backward_stage)
298 diagnose_backward(backward_stage, waits, &jump);
299 if (changed && restore_clock(realtime, monotonic))
301 for (
int n = 0; n < 3; ++n) {
303 timer_delete(timers[n]);
305 pthread_cancel(workers[n]);
306 if (st_wait(&waits[n].done, 1000) == 0)
307 pthread_join(workers[n], NULL);
312 if (bad != MAP_FAILED)