xref: /src/tests/sys/kern/timerfd.c (revision 4b16ff49bf4bf875997fe4c80a0afc0d440b7aac)
1834c1ba7SJake Freeland /*-
2834c1ba7SJake Freeland  * SPDX-License-Identifier: MIT
3834c1ba7SJake Freeland  *
4834c1ba7SJake Freeland  * Copyright (c) 2016 Jan Kokemüller
5834c1ba7SJake Freeland  *
6834c1ba7SJake Freeland  * Permission is hereby granted, free of charge, to any person obtaining a copy
7834c1ba7SJake Freeland  * of this software and associated documentation files (the "Software"), to deal
8834c1ba7SJake Freeland  * in the Software without restriction, including without limitation the rights
9834c1ba7SJake Freeland  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10834c1ba7SJake Freeland  * copies of the Software, and to permit persons to whom the Software is
11834c1ba7SJake Freeland  * furnished to do so, subject to the following conditions:
12834c1ba7SJake Freeland  *
13834c1ba7SJake Freeland  * The above copyright notice and this permission notice shall be included in
14834c1ba7SJake Freeland  * all copies or substantial portions of the Software.
15834c1ba7SJake Freeland  *
16834c1ba7SJake Freeland  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17834c1ba7SJake Freeland  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18834c1ba7SJake Freeland  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19834c1ba7SJake Freeland  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20834c1ba7SJake Freeland  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21834c1ba7SJake Freeland  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22834c1ba7SJake Freeland  * THE SOFTWARE.
23834c1ba7SJake Freeland  */
24834c1ba7SJake Freeland 
25834c1ba7SJake Freeland #include <atf-c.h>
26834c1ba7SJake Freeland 
27834c1ba7SJake Freeland #include <sys/types.h>
28834c1ba7SJake Freeland #include <sys/event.h>
29834c1ba7SJake Freeland #include <sys/param.h>
30834c1ba7SJake Freeland #include <sys/select.h>
31834c1ba7SJake Freeland #include <sys/time.h>
32cb692380SJake Freeland #include <sys/timerfd.h>
33834c1ba7SJake Freeland 
34834c1ba7SJake Freeland #include <errno.h>
35834c1ba7SJake Freeland #include <signal.h>
36834c1ba7SJake Freeland #include <stdbool.h>
37834c1ba7SJake Freeland #include <stdint.h>
38834c1ba7SJake Freeland #include <stdio.h>
39834c1ba7SJake Freeland #include <stdlib.h>
40834c1ba7SJake Freeland 
41834c1ba7SJake Freeland #include <err.h>
42834c1ba7SJake Freeland #include <poll.h>
43834c1ba7SJake Freeland #include <pthread.h>
44834c1ba7SJake Freeland #include <time.h>
45834c1ba7SJake Freeland #include <unistd.h>
46834c1ba7SJake Freeland 
47834c1ba7SJake Freeland /* Time in ns that sleeps are allowed to take longer for in unit tests. */
48834c1ba7SJake Freeland #define TIMER_SLACK (90000000)
49834c1ba7SJake Freeland 
50834c1ba7SJake Freeland ATF_TC_WITHOUT_HEAD(timerfd__many_timers);
ATF_TC_BODY(timerfd__many_timers,tc)51834c1ba7SJake Freeland ATF_TC_BODY(timerfd__many_timers, tc)
52834c1ba7SJake Freeland {
53834c1ba7SJake Freeland 	int timer_fds[256];
54834c1ba7SJake Freeland 	int i;
55834c1ba7SJake Freeland 
56834c1ba7SJake Freeland 	for (i = 0; i < (int)nitems(timer_fds); ++i) {
57834c1ba7SJake Freeland 		timer_fds[i] = timerfd_create(CLOCK_MONOTONIC, /**/
58834c1ba7SJake Freeland 		    TFD_CLOEXEC | TFD_NONBLOCK);
59834c1ba7SJake Freeland 		if (timer_fds[i] < 0 && errno == EMFILE) {
60834c1ba7SJake Freeland 			atf_tc_skip("timerfd_create: EMFILE");
61834c1ba7SJake Freeland 		}
62834c1ba7SJake Freeland 		ATF_REQUIRE_MSG(timer_fds[i] >= 0, "errno: %d", errno);
63834c1ba7SJake Freeland 	}
64834c1ba7SJake Freeland }
65834c1ba7SJake Freeland 
66834c1ba7SJake Freeland static uint64_t
wait_for_timerfd(int timerfd)67834c1ba7SJake Freeland wait_for_timerfd(int timerfd)
68834c1ba7SJake Freeland {
69834c1ba7SJake Freeland 	struct pollfd pfd = { .fd = timerfd, .events = POLLIN };
70834c1ba7SJake Freeland 
71834c1ba7SJake Freeland 	ATF_REQUIRE(poll(&pfd, 1, -1) == 1);
72834c1ba7SJake Freeland 
73834c1ba7SJake Freeland 	uint64_t timeouts;
74834c1ba7SJake Freeland 	ssize_t r = read(timerfd, &timeouts, sizeof(timeouts));
75834c1ba7SJake Freeland 
76834c1ba7SJake Freeland 	ATF_REQUIRE_MSG(r == (ssize_t)sizeof(timeouts), "%d %d", (int)r, errno);
77834c1ba7SJake Freeland 	ATF_REQUIRE(timeouts > 0);
78834c1ba7SJake Freeland 	return timeouts;
79834c1ba7SJake Freeland }
80834c1ba7SJake Freeland 
81834c1ba7SJake Freeland ATF_TC_WITHOUT_HEAD(timerfd__simple_timer);
ATF_TC_BODY(timerfd__simple_timer,tc)82834c1ba7SJake Freeland ATF_TC_BODY(timerfd__simple_timer, tc)
83834c1ba7SJake Freeland {
84834c1ba7SJake Freeland 	int timerfd = timerfd_create(CLOCK_MONOTONIC, /**/
85834c1ba7SJake Freeland 	    TFD_CLOEXEC | TFD_NONBLOCK);
86834c1ba7SJake Freeland 
87834c1ba7SJake Freeland 	ATF_REQUIRE(timerfd >= 0);
88834c1ba7SJake Freeland 
89834c1ba7SJake Freeland 	struct itimerspec time = {
90834c1ba7SJake Freeland 		.it_value.tv_sec = 0,
91834c1ba7SJake Freeland 		.it_value.tv_nsec = 100000000,
92834c1ba7SJake Freeland 	};
93834c1ba7SJake Freeland 
94834c1ba7SJake Freeland 	struct timespec b, e;
95834c1ba7SJake Freeland 	ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &b) == 0);
96834c1ba7SJake Freeland 
97834c1ba7SJake Freeland 	ATF_REQUIRE(timerfd_settime(timerfd, 0, &time, NULL) == 0);
98834c1ba7SJake Freeland 	(void)wait_for_timerfd(timerfd);
99834c1ba7SJake Freeland 
100834c1ba7SJake Freeland 	ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &e) == 0);
101834c1ba7SJake Freeland 	timespecsub(&e, &b, &e);
102834c1ba7SJake Freeland 
103834c1ba7SJake Freeland 	ATF_REQUIRE((e.tv_sec == 0 && e.tv_nsec >= 100000000) || e.tv_sec > 0);
104834c1ba7SJake Freeland 	ATF_REQUIRE(e.tv_sec == 0 && e.tv_nsec < 100000000 + TIMER_SLACK);
105834c1ba7SJake Freeland 
106834c1ba7SJake Freeland 	ATF_REQUIRE(close(timerfd) == 0);
107834c1ba7SJake Freeland }
108834c1ba7SJake Freeland 
109834c1ba7SJake Freeland ATF_TC_WITHOUT_HEAD(timerfd__simple_periodic_timer);
ATF_TC_BODY(timerfd__simple_periodic_timer,tc)110834c1ba7SJake Freeland ATF_TC_BODY(timerfd__simple_periodic_timer, tc)
111834c1ba7SJake Freeland {
112834c1ba7SJake Freeland 	int timerfd = timerfd_create(CLOCK_MONOTONIC, /**/
113834c1ba7SJake Freeland 	    TFD_CLOEXEC | TFD_NONBLOCK);
114834c1ba7SJake Freeland 
115834c1ba7SJake Freeland 	ATF_REQUIRE(timerfd >= 0);
116834c1ba7SJake Freeland 
117834c1ba7SJake Freeland 	struct itimerspec time = {
118834c1ba7SJake Freeland 		.it_value.tv_sec = 0,
119834c1ba7SJake Freeland 		.it_value.tv_nsec = 200000000,
120834c1ba7SJake Freeland 		.it_interval.tv_sec = 0,
121834c1ba7SJake Freeland 		.it_interval.tv_nsec = 200000000,
122834c1ba7SJake Freeland 	};
123834c1ba7SJake Freeland 
124834c1ba7SJake Freeland 	struct timespec b, e;
125834c1ba7SJake Freeland 	ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &b) == 0);
126834c1ba7SJake Freeland 
127834c1ba7SJake Freeland 	ATF_REQUIRE(timerfd_settime(timerfd, 0, &time, NULL) == 0);
128834c1ba7SJake Freeland 	uint64_t timeouts = wait_for_timerfd(timerfd);
129834c1ba7SJake Freeland 
130834c1ba7SJake Freeland 	ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &e) == 0);
131834c1ba7SJake Freeland 	timespecsub(&e, &b, &e);
132834c1ba7SJake Freeland 
133834c1ba7SJake Freeland 	ATF_REQUIRE((e.tv_sec == 0 && e.tv_nsec >= 200000000) || e.tv_sec > 0);
134834c1ba7SJake Freeland 	ATF_REQUIRE(timeouts >= 1);
135834c1ba7SJake Freeland 	ATF_REQUIRE(e.tv_sec == 0 && e.tv_nsec < 200000000 + TIMER_SLACK);
136834c1ba7SJake Freeland 	ATF_REQUIRE(timeouts == 1);
137834c1ba7SJake Freeland 
138834c1ba7SJake Freeland 	usleep(400000);
139834c1ba7SJake Freeland 
140834c1ba7SJake Freeland 	ATF_REQUIRE(read(timerfd, &timeouts, sizeof(timeouts)) ==
141834c1ba7SJake Freeland 	    (ssize_t)sizeof(timeouts));
142834c1ba7SJake Freeland 	ATF_REQUIRE(timeouts >= 2);
143834c1ba7SJake Freeland 	ATF_REQUIRE(timeouts == 2);
144834c1ba7SJake Freeland 
145834c1ba7SJake Freeland 	ATF_REQUIRE(close(timerfd) == 0);
146834c1ba7SJake Freeland }
147834c1ba7SJake Freeland 
148834c1ba7SJake Freeland ATF_TC_WITHOUT_HEAD(timerfd__complex_periodic_timer);
ATF_TC_BODY(timerfd__complex_periodic_timer,tc)149834c1ba7SJake Freeland ATF_TC_BODY(timerfd__complex_periodic_timer, tc)
150834c1ba7SJake Freeland {
151834c1ba7SJake Freeland 	int timerfd = timerfd_create(CLOCK_MONOTONIC, /**/
152834c1ba7SJake Freeland 	    TFD_CLOEXEC | TFD_NONBLOCK);
153834c1ba7SJake Freeland 
154834c1ba7SJake Freeland 	ATF_REQUIRE(timerfd >= 0);
155834c1ba7SJake Freeland 
156834c1ba7SJake Freeland 	struct itimerspec time = {
157834c1ba7SJake Freeland 		.it_value.tv_sec = 0,
158834c1ba7SJake Freeland 		.it_value.tv_nsec = 100000000,
159834c1ba7SJake Freeland 		.it_interval.tv_sec = 0,
160834c1ba7SJake Freeland 		.it_interval.tv_nsec = 200000001,
161834c1ba7SJake Freeland 	};
162834c1ba7SJake Freeland 
163834c1ba7SJake Freeland 	struct timespec b, e;
164834c1ba7SJake Freeland 	ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &b) == 0);
165834c1ba7SJake Freeland 
166834c1ba7SJake Freeland 	ATF_REQUIRE(timerfd_settime(timerfd, 0, &time, NULL) == 0);
167834c1ba7SJake Freeland 	uint64_t timeouts = wait_for_timerfd(timerfd);
168834c1ba7SJake Freeland 
169834c1ba7SJake Freeland 	ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &e) == 0);
170834c1ba7SJake Freeland 	timespecsub(&e, &b, &e);
171834c1ba7SJake Freeland 
172834c1ba7SJake Freeland 	ATF_REQUIRE((e.tv_sec == 0 && e.tv_nsec >= 100000000) || e.tv_sec > 0);
173834c1ba7SJake Freeland 	ATF_REQUIRE(timeouts >= 1);
174834c1ba7SJake Freeland 	ATF_REQUIRE_MSG(e.tv_sec == 0 && e.tv_nsec >= 100000000 &&
175834c1ba7SJake Freeland 		e.tv_nsec < 100000000 + TIMER_SLACK,
176834c1ba7SJake Freeland 	    "%ld", (long)e.tv_nsec);
177834c1ba7SJake Freeland 	ATF_REQUIRE(timeouts == 1);
178834c1ba7SJake Freeland 
179834c1ba7SJake Freeland 	usleep(401000);
180834c1ba7SJake Freeland 
181834c1ba7SJake Freeland 	ATF_REQUIRE(read(timerfd, &timeouts, sizeof(timeouts)) ==
182834c1ba7SJake Freeland 	    (ssize_t)sizeof(timeouts));
183834c1ba7SJake Freeland 	ATF_REQUIRE_MSG(timeouts >= 2, "%d", (int)timeouts);
184834c1ba7SJake Freeland 	ATF_REQUIRE_MSG(timeouts == 2, "%d", (int)timeouts);
185834c1ba7SJake Freeland 
186834c1ba7SJake Freeland 	ATF_REQUIRE(close(timerfd) == 0);
187834c1ba7SJake Freeland }
188834c1ba7SJake Freeland 
189834c1ba7SJake Freeland ATF_TC_WITHOUT_HEAD(timerfd__reset_periodic_timer);
ATF_TC_BODY(timerfd__reset_periodic_timer,tc)190834c1ba7SJake Freeland ATF_TC_BODY(timerfd__reset_periodic_timer, tc)
191834c1ba7SJake Freeland {
192834c1ba7SJake Freeland 	int timerfd = timerfd_create(CLOCK_MONOTONIC, /**/
193834c1ba7SJake Freeland 	    TFD_CLOEXEC | TFD_NONBLOCK);
194834c1ba7SJake Freeland 
195834c1ba7SJake Freeland 	ATF_REQUIRE(timerfd >= 0);
196834c1ba7SJake Freeland 
197834c1ba7SJake Freeland 	struct itimerspec time = {
198834c1ba7SJake Freeland 		.it_value.tv_sec = 0,
199834c1ba7SJake Freeland 		.it_value.tv_nsec = 100000000,
200834c1ba7SJake Freeland 		.it_interval.tv_sec = 0,
201834c1ba7SJake Freeland 		.it_interval.tv_nsec = 100000000,
202834c1ba7SJake Freeland 	};
203834c1ba7SJake Freeland 
204834c1ba7SJake Freeland 	struct timespec b, e;
205834c1ba7SJake Freeland 	ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &b) == 0);
206834c1ba7SJake Freeland 
207834c1ba7SJake Freeland 	ATF_REQUIRE(timerfd_settime(timerfd, 0, &time, NULL) == 0);
208834c1ba7SJake Freeland 	(void)wait_for_timerfd(timerfd);
209834c1ba7SJake Freeland 
210834c1ba7SJake Freeland 	time = (struct itimerspec) {
211834c1ba7SJake Freeland 		.it_value.tv_sec = 0,
212834c1ba7SJake Freeland 		.it_value.tv_nsec = 50000000,
213834c1ba7SJake Freeland 		.it_interval.tv_sec = 0,
214834c1ba7SJake Freeland 		.it_interval.tv_nsec = 100000000,
215834c1ba7SJake Freeland 	};
216834c1ba7SJake Freeland 
217834c1ba7SJake Freeland 	ATF_REQUIRE(timerfd_settime(timerfd, 0, &time, NULL) == 0);
218834c1ba7SJake Freeland 
219834c1ba7SJake Freeland 	uint64_t timeouts = wait_for_timerfd(timerfd);
220834c1ba7SJake Freeland 	ATF_REQUIRE(timeouts >= 1);
221834c1ba7SJake Freeland 	ATF_REQUIRE(timeouts == 1);
222834c1ba7SJake Freeland 
223834c1ba7SJake Freeland 	ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &e) == 0);
224834c1ba7SJake Freeland 	timespecsub(&e, &b, &e);
225834c1ba7SJake Freeland 	ATF_REQUIRE((e.tv_sec == 0 && e.tv_nsec >= 150000000) || e.tv_sec > 0);
226834c1ba7SJake Freeland 	ATF_REQUIRE(e.tv_sec == 0 && e.tv_nsec >= 150000000 &&
227834c1ba7SJake Freeland 	    e.tv_nsec < 150000000 + TIMER_SLACK * 2);
228834c1ba7SJake Freeland 
229834c1ba7SJake Freeland 	ATF_REQUIRE(close(timerfd) == 0);
230834c1ba7SJake Freeland }
231834c1ba7SJake Freeland 
232834c1ba7SJake Freeland ATF_TC_WITHOUT_HEAD(timerfd__reenable_periodic_timer);
ATF_TC_BODY(timerfd__reenable_periodic_timer,tc)233834c1ba7SJake Freeland ATF_TC_BODY(timerfd__reenable_periodic_timer, tc)
234834c1ba7SJake Freeland {
235834c1ba7SJake Freeland 	int timerfd = timerfd_create(CLOCK_MONOTONIC, /**/
236834c1ba7SJake Freeland 	    TFD_CLOEXEC | TFD_NONBLOCK);
237834c1ba7SJake Freeland 
238834c1ba7SJake Freeland 	ATF_REQUIRE(timerfd >= 0);
239834c1ba7SJake Freeland 
240834c1ba7SJake Freeland 	struct itimerspec time = {
241834c1ba7SJake Freeland 		.it_value.tv_sec = 0,
242834c1ba7SJake Freeland 		.it_value.tv_nsec = 100000000,
243834c1ba7SJake Freeland 		.it_interval.tv_sec = 0,
244834c1ba7SJake Freeland 		.it_interval.tv_nsec = 100000000,
245834c1ba7SJake Freeland 	};
246834c1ba7SJake Freeland 
247834c1ba7SJake Freeland 	struct timespec b, e;
248834c1ba7SJake Freeland 	ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &b) == 0);
249834c1ba7SJake Freeland 
250834c1ba7SJake Freeland 	ATF_REQUIRE(timerfd_settime(timerfd, 0, &time, NULL) == 0);
251834c1ba7SJake Freeland 	uint64_t timeouts = wait_for_timerfd(timerfd);
252834c1ba7SJake Freeland 
253834c1ba7SJake Freeland 	ATF_REQUIRE(timeouts >= 1);
254834c1ba7SJake Freeland 	ATF_REQUIRE(timeouts == 1);
255834c1ba7SJake Freeland 
256834c1ba7SJake Freeland 	time = (struct itimerspec) {
257834c1ba7SJake Freeland 		.it_value.tv_sec = 0,
258834c1ba7SJake Freeland 		.it_value.tv_nsec = 0,
259834c1ba7SJake Freeland 		.it_interval.tv_sec = 0,
260834c1ba7SJake Freeland 		.it_interval.tv_nsec = 0,
261834c1ba7SJake Freeland 	};
262834c1ba7SJake Freeland 
263834c1ba7SJake Freeland 	ATF_REQUIRE(timerfd_settime(timerfd, 0, &time, NULL) == 0);
264834c1ba7SJake Freeland 
265834c1ba7SJake Freeland 	struct pollfd pfd = { .fd = timerfd, .events = POLLIN };
266834c1ba7SJake Freeland 	ATF_REQUIRE(poll(&pfd, 1, 250) == 0);
267834c1ba7SJake Freeland 
268834c1ba7SJake Freeland 	ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &e) == 0);
269834c1ba7SJake Freeland 	timespecsub(&e, &b, &e);
270834c1ba7SJake Freeland 
271834c1ba7SJake Freeland 	ATF_REQUIRE((e.tv_sec == 0 && e.tv_nsec >= 350000000) || e.tv_sec > 0);
272834c1ba7SJake Freeland 	ATF_REQUIRE(e.tv_sec == 0 && e.tv_nsec >= 350000000 &&
273834c1ba7SJake Freeland 	    e.tv_nsec < 350000000 + TIMER_SLACK * 2);
274834c1ba7SJake Freeland 
275834c1ba7SJake Freeland 	time = (struct itimerspec) {
276834c1ba7SJake Freeland 		.it_value.tv_sec = 1,
277834c1ba7SJake Freeland 		.it_value.tv_nsec = 0,
278834c1ba7SJake Freeland 		.it_interval.tv_sec = 1,
279834c1ba7SJake Freeland 		.it_interval.tv_nsec = 0,
280834c1ba7SJake Freeland 	};
281834c1ba7SJake Freeland 	ATF_REQUIRE(timerfd_settime(timerfd, 0, &time, NULL) == 0);
282834c1ba7SJake Freeland 
283834c1ba7SJake Freeland 	ATF_REQUIRE(close(timerfd) == 0);
284834c1ba7SJake Freeland }
285834c1ba7SJake Freeland 
286834c1ba7SJake Freeland /*
287834c1ba7SJake Freeland  * Adapted from sghctoma's example here:
288834c1ba7SJake Freeland  * https://github.com/jiixyj/epoll-shim/issues/2
289834c1ba7SJake Freeland  *
290834c1ba7SJake Freeland  * The SIGUSR1 signal should not kill the process.
291834c1ba7SJake Freeland  */
292834c1ba7SJake Freeland ATF_TC_WITHOUT_HEAD(timerfd__expire_five);
ATF_TC_BODY(timerfd__expire_five,tc)293834c1ba7SJake Freeland ATF_TC_BODY(timerfd__expire_five, tc)
294834c1ba7SJake Freeland {
295834c1ba7SJake Freeland 	int fd;
296834c1ba7SJake Freeland 	struct itimerspec value;
297834c1ba7SJake Freeland 	uint64_t total_exp = 0;
298834c1ba7SJake Freeland 
299834c1ba7SJake Freeland 	fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
300834c1ba7SJake Freeland 	ATF_REQUIRE(fd >= 0);
301834c1ba7SJake Freeland 
302834c1ba7SJake Freeland 	value.it_value.tv_sec = 3;
303834c1ba7SJake Freeland 	value.it_value.tv_nsec = 0;
304834c1ba7SJake Freeland 	value.it_interval.tv_sec = 1;
305834c1ba7SJake Freeland 	value.it_interval.tv_nsec = 0;
306834c1ba7SJake Freeland 
307834c1ba7SJake Freeland 	ATF_REQUIRE(timerfd_settime(fd, 0, &value, NULL) == 0);
308834c1ba7SJake Freeland 
309834c1ba7SJake Freeland 	sigset_t sigs;
310834c1ba7SJake Freeland 	sigemptyset(&sigs);
311834c1ba7SJake Freeland 	sigaddset(&sigs, SIGUSR1);
312834c1ba7SJake Freeland 	sigprocmask(SIG_BLOCK, &sigs, NULL);
313834c1ba7SJake Freeland 
314834c1ba7SJake Freeland 	kill(getpid(), SIGUSR1);
315834c1ba7SJake Freeland 
316834c1ba7SJake Freeland 	for (;;) {
317834c1ba7SJake Freeland 		uint64_t exp = wait_for_timerfd(fd);
318834c1ba7SJake Freeland 
319834c1ba7SJake Freeland 		printf("timer expired %u times\n", (unsigned)exp);
320834c1ba7SJake Freeland 
321834c1ba7SJake Freeland 		total_exp += exp;
322834c1ba7SJake Freeland 		if (total_exp >= 5) {
323834c1ba7SJake Freeland 			break;
324834c1ba7SJake Freeland 		}
325834c1ba7SJake Freeland 	}
326834c1ba7SJake Freeland 
327834c1ba7SJake Freeland 	ATF_REQUIRE(close(fd) == 0);
328834c1ba7SJake Freeland }
329834c1ba7SJake Freeland 
330834c1ba7SJake Freeland ATF_TC_WITHOUT_HEAD(timerfd__simple_gettime);
ATF_TC_BODY(timerfd__simple_gettime,tc)331834c1ba7SJake Freeland ATF_TC_BODY(timerfd__simple_gettime, tc)
332834c1ba7SJake Freeland {
333834c1ba7SJake Freeland 	struct itimerspec curr_value;
334834c1ba7SJake Freeland 
335834c1ba7SJake Freeland 	int fd = timerfd_create(CLOCK_MONOTONIC, 0);
336834c1ba7SJake Freeland 	ATF_REQUIRE(fd >= 0);
337834c1ba7SJake Freeland 
338834c1ba7SJake Freeland 	ATF_REQUIRE(timerfd_gettime(fd, &curr_value) == 0);
339834c1ba7SJake Freeland 
340834c1ba7SJake Freeland 	ATF_REQUIRE(curr_value.it_value.tv_sec == 0);
341834c1ba7SJake Freeland 	ATF_REQUIRE(curr_value.it_value.tv_nsec == 0);
342834c1ba7SJake Freeland 	ATF_REQUIRE(curr_value.it_interval.tv_sec == 0);
343834c1ba7SJake Freeland 	ATF_REQUIRE(curr_value.it_interval.tv_nsec == 0);
344834c1ba7SJake Freeland 
345834c1ba7SJake Freeland 	struct itimerspec time = {
346834c1ba7SJake Freeland 		.it_value.tv_sec = 0,
347834c1ba7SJake Freeland 		.it_value.tv_nsec = 100000000,
348834c1ba7SJake Freeland 		.it_interval.tv_sec = 0,
349834c1ba7SJake Freeland 		.it_interval.tv_nsec = 100000000,
350834c1ba7SJake Freeland 	};
351834c1ba7SJake Freeland 
352834c1ba7SJake Freeland 	curr_value = time;
353834c1ba7SJake Freeland 	ATF_REQUIRE(timerfd_settime(fd, 0, &time, &curr_value) == 0);
354834c1ba7SJake Freeland 	ATF_REQUIRE(curr_value.it_value.tv_sec == 0);
355834c1ba7SJake Freeland 	ATF_REQUIRE(curr_value.it_value.tv_nsec == 0);
356834c1ba7SJake Freeland 	ATF_REQUIRE(curr_value.it_interval.tv_sec == 0);
357834c1ba7SJake Freeland 	ATF_REQUIRE(curr_value.it_interval.tv_nsec == 0);
358834c1ba7SJake Freeland 
359834c1ba7SJake Freeland 	ATF_REQUIRE(close(fd) == 0);
360834c1ba7SJake Freeland }
361834c1ba7SJake Freeland 
362834c1ba7SJake Freeland ATF_TC_WITHOUT_HEAD(timerfd__simple_blocking_periodic_timer);
ATF_TC_BODY(timerfd__simple_blocking_periodic_timer,tc)363834c1ba7SJake Freeland ATF_TC_BODY(timerfd__simple_blocking_periodic_timer, tc)
364834c1ba7SJake Freeland {
365834c1ba7SJake Freeland 	int timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
366834c1ba7SJake Freeland 
367834c1ba7SJake Freeland 	ATF_REQUIRE(timerfd >= 0);
368834c1ba7SJake Freeland 
369834c1ba7SJake Freeland 	struct itimerspec time = {
370834c1ba7SJake Freeland 		.it_value.tv_sec = 0,
371834c1ba7SJake Freeland 		.it_value.tv_nsec = 100000000,
372834c1ba7SJake Freeland 		.it_interval.tv_sec = 0,
373834c1ba7SJake Freeland 		.it_interval.tv_nsec = 100000000,
374834c1ba7SJake Freeland 	};
375834c1ba7SJake Freeland 
376834c1ba7SJake Freeland 	struct timespec b, e;
377834c1ba7SJake Freeland 	ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &b) == 0);
378834c1ba7SJake Freeland 
379834c1ba7SJake Freeland 	ATF_REQUIRE(timerfd_settime(timerfd, 0, &time, NULL) == 0);
380834c1ba7SJake Freeland 
381834c1ba7SJake Freeland 	uint64_t timeouts = 0;
382834c1ba7SJake Freeland 	int num_loop_iterations = 0;
383834c1ba7SJake Freeland 
384834c1ba7SJake Freeland 	while (timeouts < 3) {
385834c1ba7SJake Freeland 		uint64_t timeouts_local;
386834c1ba7SJake Freeland 		ATF_REQUIRE(
387834c1ba7SJake Freeland 		    read(timerfd, &timeouts_local, sizeof(timeouts_local)) ==
388834c1ba7SJake Freeland 		    (ssize_t)sizeof(timeouts_local));
389834c1ba7SJake Freeland 		ATF_REQUIRE(timeouts_local > 0);
390834c1ba7SJake Freeland 
391834c1ba7SJake Freeland 		++num_loop_iterations;
392834c1ba7SJake Freeland 		timeouts += timeouts_local;
393834c1ba7SJake Freeland 	}
394834c1ba7SJake Freeland 
395834c1ba7SJake Freeland 	ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &e) == 0);
396834c1ba7SJake Freeland 	timespecsub(&e, &b, &e);
397834c1ba7SJake Freeland 
398834c1ba7SJake Freeland 	ATF_REQUIRE((e.tv_sec == 0 && e.tv_nsec >= 300000000) || e.tv_sec > 0);
399834c1ba7SJake Freeland 	ATF_REQUIRE(e.tv_sec == 0 && e.tv_nsec >= 300000000 &&
400834c1ba7SJake Freeland 	    e.tv_nsec < 300000000 + TIMER_SLACK);
401834c1ba7SJake Freeland 
402834c1ba7SJake Freeland 	ATF_REQUIRE(num_loop_iterations <= 3);
403834c1ba7SJake Freeland 
404834c1ba7SJake Freeland 	ATF_REQUIRE(close(timerfd) == 0);
405834c1ba7SJake Freeland }
406834c1ba7SJake Freeland 
407834c1ba7SJake Freeland ATF_TC_WITHOUT_HEAD(timerfd__argument_checks);
ATF_TC_BODY(timerfd__argument_checks,tc)408834c1ba7SJake Freeland ATF_TC_BODY(timerfd__argument_checks, tc)
409834c1ba7SJake Freeland {
410834c1ba7SJake Freeland 	int timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
411834c1ba7SJake Freeland 	ATF_REQUIRE(timerfd >= 0);
412834c1ba7SJake Freeland 
413834c1ba7SJake Freeland 	struct itimerspec time = {
414834c1ba7SJake Freeland 		.it_value.tv_sec = 0,
415834c1ba7SJake Freeland 		.it_value.tv_nsec = 100000000,
416834c1ba7SJake Freeland 		.it_interval.tv_sec = 0,
417834c1ba7SJake Freeland 		.it_interval.tv_nsec = 100000000,
418834c1ba7SJake Freeland 	};
419834c1ba7SJake Freeland 
420834c1ba7SJake Freeland 	ATF_REQUIRE_ERRNO(EFAULT, timerfd_settime(timerfd, 0, NULL, NULL) < 0);
421834c1ba7SJake Freeland 	ATF_REQUIRE_ERRNO(EFAULT, timerfd_settime(-2, 0, NULL, NULL) < 0);
422834c1ba7SJake Freeland 	ATF_REQUIRE_ERRNO(EBADF, timerfd_settime(-2, 0, &time, NULL) < 0);
423834c1ba7SJake Freeland 	ATF_REQUIRE_ERRNO(EFAULT, timerfd_settime(-2, 42, NULL, NULL) < 0);
424834c1ba7SJake Freeland 	ATF_REQUIRE_ERRNO(EINVAL, timerfd_settime(-2, 42, &time, NULL) < 0);
425834c1ba7SJake Freeland 	ATF_REQUIRE_ERRNO(EINVAL,
426834c1ba7SJake Freeland 	    timerfd_settime(timerfd, 42, &time, NULL) < 0);
427834c1ba7SJake Freeland 
428834c1ba7SJake Freeland 	{
429834c1ba7SJake Freeland 		time = (struct itimerspec) {
430834c1ba7SJake Freeland 			.it_value.tv_sec = -1,
431834c1ba7SJake Freeland 			.it_value.tv_nsec = 100000000,
432834c1ba7SJake Freeland 			.it_interval.tv_sec = 0,
433834c1ba7SJake Freeland 			.it_interval.tv_nsec = 100000000,
434834c1ba7SJake Freeland 		};
435834c1ba7SJake Freeland 		ATF_REQUIRE_ERRNO(EINVAL,
436834c1ba7SJake Freeland 		    timerfd_settime(timerfd, 0, &time, NULL) < 0);
437834c1ba7SJake Freeland 	}
438834c1ba7SJake Freeland 	{
439834c1ba7SJake Freeland 		time = (struct itimerspec) {
440834c1ba7SJake Freeland 			.it_value.tv_sec = 0,
441834c1ba7SJake Freeland 			.it_value.tv_nsec = -1,
442834c1ba7SJake Freeland 			.it_interval.tv_sec = 0,
443834c1ba7SJake Freeland 			.it_interval.tv_nsec = 100000000,
444834c1ba7SJake Freeland 		};
445834c1ba7SJake Freeland 		ATF_REQUIRE_ERRNO(EINVAL,
446834c1ba7SJake Freeland 		    timerfd_settime(timerfd, 0, &time, NULL) < 0);
447834c1ba7SJake Freeland 	}
448834c1ba7SJake Freeland 	{
449834c1ba7SJake Freeland 		time = (struct itimerspec) {
450834c1ba7SJake Freeland 			.it_value.tv_sec = 0,
451834c1ba7SJake Freeland 			.it_value.tv_nsec = 100000000,
452834c1ba7SJake Freeland 			.it_interval.tv_sec = -1,
453834c1ba7SJake Freeland 			.it_interval.tv_nsec = 100000000,
454834c1ba7SJake Freeland 		};
455834c1ba7SJake Freeland 		ATF_REQUIRE_ERRNO(EINVAL,
456834c1ba7SJake Freeland 		    timerfd_settime(timerfd, 0, &time, NULL) < 0);
457834c1ba7SJake Freeland 	}
458834c1ba7SJake Freeland 	{
459834c1ba7SJake Freeland 		time = (struct itimerspec) {
460834c1ba7SJake Freeland 			.it_value.tv_sec = 0,
461834c1ba7SJake Freeland 			.it_value.tv_nsec = 100000000,
462834c1ba7SJake Freeland 			.it_interval.tv_sec = 0,
463834c1ba7SJake Freeland 			.it_interval.tv_nsec = -1,
464834c1ba7SJake Freeland 		};
465834c1ba7SJake Freeland 		ATF_REQUIRE_ERRNO(EINVAL,
466834c1ba7SJake Freeland 		    timerfd_settime(timerfd, 0, &time, NULL) < 0);
467834c1ba7SJake Freeland 	}
468834c1ba7SJake Freeland 	{
469834c1ba7SJake Freeland 		time = (struct itimerspec) {
470834c1ba7SJake Freeland 			.it_value.tv_sec = 0,
471834c1ba7SJake Freeland 			.it_value.tv_nsec = 1000000000,
472834c1ba7SJake Freeland 			.it_interval.tv_sec = 0,
473834c1ba7SJake Freeland 			.it_interval.tv_nsec = 100000000,
474834c1ba7SJake Freeland 		};
475834c1ba7SJake Freeland 		ATF_REQUIRE_ERRNO(EINVAL,
476834c1ba7SJake Freeland 		    timerfd_settime(timerfd, 0, &time, NULL) < 0);
477834c1ba7SJake Freeland 	}
478834c1ba7SJake Freeland 	{
479834c1ba7SJake Freeland 		time = (struct itimerspec) {
480834c1ba7SJake Freeland 			.it_value.tv_sec = 0,
481834c1ba7SJake Freeland 			.it_value.tv_nsec = 100000000,
482834c1ba7SJake Freeland 			.it_interval.tv_sec = 0,
483834c1ba7SJake Freeland 			.it_interval.tv_nsec = 1000000000,
484834c1ba7SJake Freeland 		};
485834c1ba7SJake Freeland 		ATF_REQUIRE_ERRNO(EINVAL,
486834c1ba7SJake Freeland 		    timerfd_settime(timerfd, 0, &time, NULL) < 0);
487834c1ba7SJake Freeland 	}
488834c1ba7SJake Freeland 
489834c1ba7SJake Freeland 	ATF_REQUIRE_ERRNO(EINVAL,
490834c1ba7SJake Freeland 	    timerfd_create(CLOCK_MONOTONIC | 42, TFD_CLOEXEC));
491834c1ba7SJake Freeland 	ATF_REQUIRE_ERRNO(EINVAL,
492834c1ba7SJake Freeland 	    timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | 42));
493834c1ba7SJake Freeland 
494834c1ba7SJake Freeland 	ATF_REQUIRE(close(timerfd) == 0);
495834c1ba7SJake Freeland 
496834c1ba7SJake Freeland 	struct itimerspec itimerspec;
497834c1ba7SJake Freeland 	ATF_REQUIRE_ERRNO(EBADF, timerfd_gettime(timerfd, &itimerspec) < 0);
498834c1ba7SJake Freeland 	ATF_REQUIRE_ERRNO(EINVAL,
499834c1ba7SJake Freeland 	    timerfd_settime(timerfd, 0, &itimerspec, NULL) < 0);
500834c1ba7SJake Freeland }
501834c1ba7SJake Freeland 
502834c1ba7SJake Freeland ATF_TC_WITHOUT_HEAD(timerfd__upgrade_simple_to_complex);
ATF_TC_BODY(timerfd__upgrade_simple_to_complex,tc)503834c1ba7SJake Freeland ATF_TC_BODY(timerfd__upgrade_simple_to_complex, tc)
504834c1ba7SJake Freeland {
505834c1ba7SJake Freeland 	int timerfd = timerfd_create(CLOCK_MONOTONIC, /**/
506834c1ba7SJake Freeland 	    TFD_CLOEXEC | TFD_NONBLOCK);
507834c1ba7SJake Freeland 
508834c1ba7SJake Freeland 	ATF_REQUIRE(timerfd >= 0);
509834c1ba7SJake Freeland 
510834c1ba7SJake Freeland 	struct itimerspec time = {
511834c1ba7SJake Freeland 		.it_value.tv_sec = 0,
512834c1ba7SJake Freeland 		.it_value.tv_nsec = 100000000,
513834c1ba7SJake Freeland 		.it_interval.tv_sec = 0,
514834c1ba7SJake Freeland 		.it_interval.tv_nsec = 100000000,
515834c1ba7SJake Freeland 	};
516834c1ba7SJake Freeland 
517834c1ba7SJake Freeland 	ATF_REQUIRE(timerfd_settime(timerfd, 0, &time, NULL) == 0);
518834c1ba7SJake Freeland 	(void)wait_for_timerfd(timerfd);
519834c1ba7SJake Freeland 
520834c1ba7SJake Freeland 	time = (struct itimerspec) {
521834c1ba7SJake Freeland 		.it_value.tv_sec = 0,
522834c1ba7SJake Freeland 		.it_value.tv_nsec = 50000000,
523834c1ba7SJake Freeland 		.it_interval.tv_sec = 0,
524834c1ba7SJake Freeland 		.it_interval.tv_nsec = 95000000,
525834c1ba7SJake Freeland 	};
526834c1ba7SJake Freeland 
527834c1ba7SJake Freeland 	struct timespec b, e;
528834c1ba7SJake Freeland 	ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &b) == 0);
529834c1ba7SJake Freeland 
530834c1ba7SJake Freeland 	ATF_REQUIRE(timerfd_settime(timerfd, 0, &time, NULL) == 0);
531834c1ba7SJake Freeland 
532834c1ba7SJake Freeland 	uint64_t timeouts = wait_for_timerfd(timerfd);
533834c1ba7SJake Freeland 	ATF_REQUIRE(timeouts >= 1);
534834c1ba7SJake Freeland 	ATF_REQUIRE(timeouts == 1);
535834c1ba7SJake Freeland 
536834c1ba7SJake Freeland 	ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &e) == 0);
537834c1ba7SJake Freeland 	timespecsub(&e, &b, &e);
538834c1ba7SJake Freeland 	ATF_REQUIRE((e.tv_sec == 0 && e.tv_nsec >= 50000000) || e.tv_sec > 0);
539834c1ba7SJake Freeland 	ATF_REQUIRE_MSG(e.tv_sec == 0 && e.tv_nsec < 50000000 + TIMER_SLACK,
540834c1ba7SJake Freeland 	    "%ld", e.tv_nsec);
541834c1ba7SJake Freeland 
542834c1ba7SJake Freeland 	timeouts = wait_for_timerfd(timerfd);
543834c1ba7SJake Freeland 	ATF_REQUIRE(timeouts >= 1);
544834c1ba7SJake Freeland 	ATF_REQUIRE(timeouts == 1);
545834c1ba7SJake Freeland 
546834c1ba7SJake Freeland 	ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &e) == 0);
547834c1ba7SJake Freeland 	timespecsub(&e, &b, &e);
548834c1ba7SJake Freeland 	ATF_REQUIRE((e.tv_sec == 0 && e.tv_nsec >= 145000000) || e.tv_sec > 0);
549834c1ba7SJake Freeland 	ATF_REQUIRE(e.tv_sec == 0 && e.tv_nsec >= 145000000 &&
550834c1ba7SJake Freeland 	    e.tv_nsec < 145000000 + TIMER_SLACK);
551834c1ba7SJake Freeland 
552834c1ba7SJake Freeland 	ATF_REQUIRE(close(timerfd) == 0);
553834c1ba7SJake Freeland }
554834c1ba7SJake Freeland 
555834c1ba7SJake Freeland ATF_TC_WITHOUT_HEAD(timerfd__absolute_timer);
ATF_TC_BODY(timerfd__absolute_timer,tc)556834c1ba7SJake Freeland ATF_TC_BODY(timerfd__absolute_timer, tc)
557834c1ba7SJake Freeland {
558834c1ba7SJake Freeland 	int timerfd = timerfd_create(CLOCK_MONOTONIC, /**/
559834c1ba7SJake Freeland 	    TFD_CLOEXEC | TFD_NONBLOCK);
560834c1ba7SJake Freeland 
561834c1ba7SJake Freeland 	ATF_REQUIRE(timerfd >= 0);
562834c1ba7SJake Freeland 
563834c1ba7SJake Freeland 	struct timespec b, e;
564834c1ba7SJake Freeland 	ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &b) == 0);
565834c1ba7SJake Freeland 
566834c1ba7SJake Freeland 	struct itimerspec time = {
567834c1ba7SJake Freeland 		.it_value = b,
568834c1ba7SJake Freeland 		.it_interval.tv_sec = 0,
569834c1ba7SJake Freeland 		.it_interval.tv_nsec = 0,
570834c1ba7SJake Freeland 	};
571834c1ba7SJake Freeland 
572834c1ba7SJake Freeland 	struct timespec ts_600ms = {
573834c1ba7SJake Freeland 		.tv_sec = 0,
574834c1ba7SJake Freeland 		.tv_nsec = 600000000,
575834c1ba7SJake Freeland 	};
576834c1ba7SJake Freeland 
577834c1ba7SJake Freeland 	timespecadd(&time.it_value, &ts_600ms, &time.it_value);
578834c1ba7SJake Freeland 
579834c1ba7SJake Freeland 	ATF_REQUIRE(timerfd_settime(timerfd, /**/
580834c1ba7SJake Freeland 			TFD_TIMER_ABSTIME, &time, NULL) == 0);
581834c1ba7SJake Freeland 
582834c1ba7SJake Freeland 	struct pollfd pfd = { .fd = timerfd, .events = POLLIN };
583834c1ba7SJake Freeland 	ATF_REQUIRE(poll(&pfd, 1, -1) == 1);
584834c1ba7SJake Freeland 
585834c1ba7SJake Freeland 	// Don't read(2) here!
586834c1ba7SJake Freeland 
587834c1ba7SJake Freeland 	ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &e) == 0);
588834c1ba7SJake Freeland 	timespecsub(&e, &b, &e);
589834c1ba7SJake Freeland 	ATF_REQUIRE(e.tv_sec == 0 &&
590834c1ba7SJake Freeland 	    /* Don't check for this because of spurious wakeups. */
591834c1ba7SJake Freeland 	    /* e.tv_nsec >= 600000000 && */
592834c1ba7SJake Freeland 	    e.tv_nsec < 600000000 + TIMER_SLACK);
593834c1ba7SJake Freeland 
594834c1ba7SJake Freeland 	struct itimerspec zeroed_its = {
595834c1ba7SJake Freeland 		.it_value.tv_sec = 0,
596834c1ba7SJake Freeland 		.it_value.tv_nsec = 0,
597834c1ba7SJake Freeland 		.it_interval.tv_sec = 0,
598834c1ba7SJake Freeland 		.it_interval.tv_nsec = 0,
599834c1ba7SJake Freeland 	};
600834c1ba7SJake Freeland 	ATF_REQUIRE(timerfd_settime(timerfd, 0, &zeroed_its, NULL) == 0);
601834c1ba7SJake Freeland 
602834c1ba7SJake Freeland 	uint64_t timeouts;
603834c1ba7SJake Freeland 	ATF_REQUIRE_ERRNO(EAGAIN,
604834c1ba7SJake Freeland 	    read(timerfd, &timeouts, sizeof(timeouts)) < 0);
605834c1ba7SJake Freeland 
606834c1ba7SJake Freeland 	ATF_REQUIRE(poll(&pfd, 1, 0) == 0);
607834c1ba7SJake Freeland 
608834c1ba7SJake Freeland 	ATF_REQUIRE(close(timerfd) == 0);
609834c1ba7SJake Freeland }
610834c1ba7SJake Freeland 
611834c1ba7SJake Freeland ATF_TC_WITHOUT_HEAD(timerfd__absolute_timer_in_the_past);
ATF_TC_BODY(timerfd__absolute_timer_in_the_past,tc)612834c1ba7SJake Freeland ATF_TC_BODY(timerfd__absolute_timer_in_the_past, tc)
613834c1ba7SJake Freeland {
614834c1ba7SJake Freeland 	int timerfd = timerfd_create(CLOCK_MONOTONIC, /**/
615834c1ba7SJake Freeland 	    TFD_CLOEXEC | TFD_NONBLOCK);
616834c1ba7SJake Freeland 
617834c1ba7SJake Freeland 	ATF_REQUIRE(timerfd >= 0);
618834c1ba7SJake Freeland 
619834c1ba7SJake Freeland 	struct timespec b;
620834c1ba7SJake Freeland 	ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &b) == 0);
621834c1ba7SJake Freeland 
622834c1ba7SJake Freeland 	{
623834c1ba7SJake Freeland 		struct itimerspec time = {
624834c1ba7SJake Freeland 			.it_value = b,
625834c1ba7SJake Freeland 			.it_interval.tv_sec = 10,
626834c1ba7SJake Freeland 			.it_interval.tv_nsec = 0,
627834c1ba7SJake Freeland 		};
628834c1ba7SJake Freeland 		time.it_value.tv_sec -= 1;
629834c1ba7SJake Freeland 
630834c1ba7SJake Freeland 		ATF_REQUIRE(timerfd_settime(timerfd, /**/
631834c1ba7SJake Freeland 				TFD_TIMER_ABSTIME, &time, NULL) == 0);
632834c1ba7SJake Freeland 
633834c1ba7SJake Freeland 		struct pollfd pfd = { .fd = timerfd, .events = POLLIN };
634834c1ba7SJake Freeland 		ATF_REQUIRE(poll(&pfd, 1, 1000) == 1);
635834c1ba7SJake Freeland 	}
636834c1ba7SJake Freeland 
637834c1ba7SJake Freeland 	{
638834c1ba7SJake Freeland 		struct itimerspec time = {
639834c1ba7SJake Freeland 			.it_value = b,
640834c1ba7SJake Freeland 			.it_interval.tv_sec = 0,
641834c1ba7SJake Freeland 			.it_interval.tv_nsec = 10000000,
642834c1ba7SJake Freeland 		};
643834c1ba7SJake Freeland 		time.it_value.tv_sec -= 1;
644834c1ba7SJake Freeland 
645834c1ba7SJake Freeland 		ATF_REQUIRE(timerfd_settime(timerfd, /**/
646834c1ba7SJake Freeland 				TFD_TIMER_ABSTIME, &time, NULL) == 0);
647834c1ba7SJake Freeland 
648834c1ba7SJake Freeland 		struct pollfd pfd = { .fd = timerfd, .events = POLLIN };
649834c1ba7SJake Freeland 		ATF_REQUIRE(poll(&pfd, 1, -1) == 1);
650834c1ba7SJake Freeland 	}
651834c1ba7SJake Freeland 
652834c1ba7SJake Freeland 	uint64_t timeouts;
653834c1ba7SJake Freeland 	ATF_REQUIRE(read(timerfd, &timeouts, sizeof(timeouts)) ==
654834c1ba7SJake Freeland 	    (ssize_t)sizeof(timeouts));
655834c1ba7SJake Freeland 
656834c1ba7SJake Freeland 	ATF_REQUIRE_MSG(timeouts >= 101, "%d", (int)timeouts);
657834c1ba7SJake Freeland 
658834c1ba7SJake Freeland 	ATF_REQUIRE(close(timerfd) == 0);
659834c1ba7SJake Freeland }
660834c1ba7SJake Freeland 
661834c1ba7SJake Freeland ATF_TC_WITHOUT_HEAD(timerfd__reset_absolute);
ATF_TC_BODY(timerfd__reset_absolute,tc)662834c1ba7SJake Freeland ATF_TC_BODY(timerfd__reset_absolute, tc)
663834c1ba7SJake Freeland {
664834c1ba7SJake Freeland 	int timerfd = timerfd_create(CLOCK_MONOTONIC, /**/
665834c1ba7SJake Freeland 	    TFD_CLOEXEC | TFD_NONBLOCK);
666834c1ba7SJake Freeland 
667834c1ba7SJake Freeland 	ATF_REQUIRE(timerfd >= 0);
668834c1ba7SJake Freeland 
669834c1ba7SJake Freeland 	struct timespec b;
670834c1ba7SJake Freeland 	ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &b) == 0);
671834c1ba7SJake Freeland 
672834c1ba7SJake Freeland 	{
673834c1ba7SJake Freeland 		struct itimerspec time = {
674834c1ba7SJake Freeland 			.it_value = b,
675834c1ba7SJake Freeland 		};
676834c1ba7SJake Freeland 		time.it_value.tv_sec += 10;
677834c1ba7SJake Freeland 
678834c1ba7SJake Freeland 		ATF_REQUIRE(timerfd_settime(timerfd, /**/
679834c1ba7SJake Freeland 				TFD_TIMER_ABSTIME, &time, NULL) == 0);
680834c1ba7SJake Freeland 
681834c1ba7SJake Freeland 		struct pollfd pfd = { .fd = timerfd, .events = POLLIN };
682834c1ba7SJake Freeland 		ATF_REQUIRE(poll(&pfd, 1, 100) == 0);
683834c1ba7SJake Freeland 	}
684834c1ba7SJake Freeland 
685834c1ba7SJake Freeland 	{
686834c1ba7SJake Freeland 		struct itimerspec time = {
687834c1ba7SJake Freeland 			.it_value = b,
688834c1ba7SJake Freeland 		};
689834c1ba7SJake Freeland 		time.it_value.tv_nsec += 500000000;
690834c1ba7SJake Freeland 		if (time.it_value.tv_nsec >= 1000000000) {
691834c1ba7SJake Freeland 			time.it_value.tv_nsec -= 1000000000;
692834c1ba7SJake Freeland 			time.it_value.tv_sec += 1;
693834c1ba7SJake Freeland 		}
694834c1ba7SJake Freeland 
695834c1ba7SJake Freeland 		ATF_REQUIRE(timerfd_settime(timerfd, /**/
696834c1ba7SJake Freeland 				TFD_TIMER_ABSTIME, &time, NULL) == 0);
697834c1ba7SJake Freeland 
698834c1ba7SJake Freeland 		struct pollfd pfd = { .fd = timerfd, .events = POLLIN };
699834c1ba7SJake Freeland 		ATF_REQUIRE(poll(&pfd, 1, 1000) == 1);
700834c1ba7SJake Freeland 	}
701834c1ba7SJake Freeland 
702834c1ba7SJake Freeland 	uint64_t timeouts;
703834c1ba7SJake Freeland 	ATF_REQUIRE(read(timerfd, &timeouts, sizeof(timeouts)) ==
704834c1ba7SJake Freeland 	    (ssize_t)sizeof(timeouts));
705834c1ba7SJake Freeland 
706834c1ba7SJake Freeland 	ATF_REQUIRE_MSG(timeouts == 1, "%d", (int)timeouts);
707834c1ba7SJake Freeland 
708834c1ba7SJake Freeland 	ATF_REQUIRE(close(timerfd) == 0);
709834c1ba7SJake Freeland }
710834c1ba7SJake Freeland 
711834c1ba7SJake Freeland ATF_TC(timerfd__periodic_timer_performance);
ATF_TC_HEAD(timerfd__periodic_timer_performance,tc)712834c1ba7SJake Freeland ATF_TC_HEAD(timerfd__periodic_timer_performance, tc)
713834c1ba7SJake Freeland {
714834c1ba7SJake Freeland 	atf_tc_set_md_var(tc, "timeout", "1");
715834c1ba7SJake Freeland }
ATF_TC_BODY(timerfd__periodic_timer_performance,tc)716834c1ba7SJake Freeland ATF_TC_BODY(timerfd__periodic_timer_performance, tc)
717834c1ba7SJake Freeland {
718834c1ba7SJake Freeland 	int timerfd = timerfd_create(CLOCK_MONOTONIC, /**/
719834c1ba7SJake Freeland 	    TFD_CLOEXEC | TFD_NONBLOCK);
720834c1ba7SJake Freeland 
721834c1ba7SJake Freeland 	ATF_REQUIRE(timerfd >= 0);
722834c1ba7SJake Freeland 
723834c1ba7SJake Freeland 	struct itimerspec time = {
724834c1ba7SJake Freeland 		.it_value.tv_sec = 0,
725834c1ba7SJake Freeland 		.it_value.tv_nsec = 1,
726834c1ba7SJake Freeland 		.it_interval.tv_sec = 0,
727834c1ba7SJake Freeland 		.it_interval.tv_nsec = 1,
728834c1ba7SJake Freeland 	};
729834c1ba7SJake Freeland 
730834c1ba7SJake Freeland 	ATF_REQUIRE(timerfd_settime(timerfd, 0, &time, NULL) == 0);
731834c1ba7SJake Freeland 
732834c1ba7SJake Freeland 	usleep(400000);
733834c1ba7SJake Freeland 
734834c1ba7SJake Freeland 	struct pollfd pfd = { .fd = timerfd, .events = POLLIN };
735834c1ba7SJake Freeland 	ATF_REQUIRE(poll(&pfd, 1, -1) == 1);
736834c1ba7SJake Freeland 
737834c1ba7SJake Freeland 	uint64_t timeouts;
738834c1ba7SJake Freeland 	ATF_REQUIRE(read(timerfd, &timeouts, sizeof(timeouts)) ==
739834c1ba7SJake Freeland 	    (ssize_t)sizeof(timeouts));
740*4b16ff49SJake Freeland 	if (timeouts < 400000000)
741cb692380SJake Freeland 		atf_tc_expect_fail("https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=294053");
742834c1ba7SJake Freeland 	ATF_REQUIRE_MSG(timeouts >= 400000000, "%ld", (long)timeouts);
743834c1ba7SJake Freeland 
744834c1ba7SJake Freeland 	ATF_REQUIRE(close(timerfd) == 0);
745834c1ba7SJake Freeland }
746834c1ba7SJake Freeland 
747834c1ba7SJake Freeland ATF_TC_WITHOUT_HEAD(timerfd__argument_overflow);
ATF_TC_BODY(timerfd__argument_overflow,tc)748834c1ba7SJake Freeland ATF_TC_BODY(timerfd__argument_overflow, tc)
749834c1ba7SJake Freeland {
750834c1ba7SJake Freeland 	int timerfd = timerfd_create(CLOCK_MONOTONIC, /**/
751834c1ba7SJake Freeland 	    TFD_CLOEXEC | TFD_NONBLOCK);
752834c1ba7SJake Freeland 	ATF_REQUIRE(timerfd >= 0);
753834c1ba7SJake Freeland 	{
754834c1ba7SJake Freeland 		struct itimerspec time = {
755834c1ba7SJake Freeland 			.it_value.tv_sec = 0,
756834c1ba7SJake Freeland 			.it_value.tv_nsec = 1,
757834c1ba7SJake Freeland 		};
758834c1ba7SJake Freeland 
759834c1ba7SJake Freeland 		ATF_REQUIRE(timerfd_settime(timerfd, /**/
760834c1ba7SJake Freeland 				TFD_TIMER_ABSTIME, &time, NULL) == 0);
761834c1ba7SJake Freeland 
762834c1ba7SJake Freeland 		struct pollfd pfd = { .fd = timerfd, .events = POLLIN };
763834c1ba7SJake Freeland 		ATF_REQUIRE(poll(&pfd, 1, -1) == 1);
764834c1ba7SJake Freeland 
765834c1ba7SJake Freeland 		uint64_t timeouts;
766834c1ba7SJake Freeland 		ATF_REQUIRE(read(timerfd, &timeouts, sizeof(timeouts)) ==
767834c1ba7SJake Freeland 		    (ssize_t)sizeof(timeouts));
768834c1ba7SJake Freeland 		ATF_REQUIRE(timeouts == 1);
769834c1ba7SJake Freeland 
770834c1ba7SJake Freeland 		ATF_REQUIRE(read(timerfd, &timeouts, sizeof(timeouts)) < 0);
771834c1ba7SJake Freeland 	}
772834c1ba7SJake Freeland 	{
773834c1ba7SJake Freeland 		struct itimerspec time = {
774834c1ba7SJake Freeland 			.it_value.tv_sec = LONG_MAX,
775834c1ba7SJake Freeland 			.it_value.tv_nsec = 999999999,
776834c1ba7SJake Freeland 		};
777834c1ba7SJake Freeland 
778834c1ba7SJake Freeland 		ATF_REQUIRE(timerfd_settime(timerfd, /**/
779834c1ba7SJake Freeland 				TFD_TIMER_ABSTIME, &time, NULL) == 0);
780834c1ba7SJake Freeland 
781834c1ba7SJake Freeland 		struct pollfd pfd = { .fd = timerfd, .events = POLLIN };
782834c1ba7SJake Freeland 		ATF_REQUIRE(poll(&pfd, 1, 500) == 0);
783834c1ba7SJake Freeland 
784834c1ba7SJake Freeland 		uint64_t timeouts;
785834c1ba7SJake Freeland 		ATF_REQUIRE(read(timerfd, &timeouts, sizeof(timeouts)) < 0);
786834c1ba7SJake Freeland 	}
787834c1ba7SJake Freeland 
788834c1ba7SJake Freeland 	ATF_REQUIRE(close(timerfd) == 0);
789834c1ba7SJake Freeland }
790834c1ba7SJake Freeland 
791834c1ba7SJake Freeland ATF_TC(timerfd__short_evfilt_timer_timeout);
ATF_TC_HEAD(timerfd__short_evfilt_timer_timeout,tc)792834c1ba7SJake Freeland ATF_TC_HEAD(timerfd__short_evfilt_timer_timeout, tc)
793834c1ba7SJake Freeland {
794834c1ba7SJake Freeland 	atf_tc_set_md_var(tc, "timeout", "30");
795834c1ba7SJake Freeland }
ATF_TC_BODY(timerfd__short_evfilt_timer_timeout,tc)796834c1ba7SJake Freeland ATF_TC_BODY(timerfd__short_evfilt_timer_timeout, tc)
797834c1ba7SJake Freeland {
798834c1ba7SJake Freeland 	int kq = kqueue();
799834c1ba7SJake Freeland 	ATF_REQUIRE(kq >= 0);
800834c1ba7SJake Freeland 
801834c1ba7SJake Freeland 	bool returns_early = false;
802834c1ba7SJake Freeland 
803834c1ba7SJake Freeland 	for (int l = 0; l < 10; ++l) {
804834c1ba7SJake Freeland 		for (int i = 1; i <= 17; ++i) {
805834c1ba7SJake Freeland 			struct kevent kev;
806834c1ba7SJake Freeland 			EV_SET(&kev, 0, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, i,
807834c1ba7SJake Freeland 			    0);
808834c1ba7SJake Freeland 
809834c1ba7SJake Freeland 			struct timespec b;
810834c1ba7SJake Freeland 			ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &b) == 0);
811834c1ba7SJake Freeland 
812834c1ba7SJake Freeland 			ATF_REQUIRE(kevent(kq, &kev, 1, NULL, 0, NULL) == 0);
813834c1ba7SJake Freeland 
814834c1ba7SJake Freeland 			ATF_REQUIRE(kevent(kq, NULL, 0, &kev, 1, NULL) == 1);
815834c1ba7SJake Freeland 
816834c1ba7SJake Freeland 			struct timespec e;
817834c1ba7SJake Freeland 			ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &e) == 0);
818834c1ba7SJake Freeland 
819834c1ba7SJake Freeland 			struct timespec diff;
820834c1ba7SJake Freeland 			timespecsub(&e, &b, &diff);
821834c1ba7SJake Freeland 
822834c1ba7SJake Freeland 			if (diff.tv_sec != 0 || diff.tv_nsec < i * 1000000) {
823834c1ba7SJake Freeland 				fprintf(stderr,
824834c1ba7SJake Freeland 				    "expected: %lldns, got: %lldns\n",
825834c1ba7SJake Freeland 				    (long long)(i * 1000000LL),
826834c1ba7SJake Freeland 				    (long long)diff.tv_nsec);
827834c1ba7SJake Freeland 				returns_early = true;
828834c1ba7SJake Freeland 				goto check;
829834c1ba7SJake Freeland 			}
830834c1ba7SJake Freeland 		}
831834c1ba7SJake Freeland 	}
832834c1ba7SJake Freeland 
833834c1ba7SJake Freeland check:
834834c1ba7SJake Freeland 	ATF_REQUIRE(!returns_early);
835834c1ba7SJake Freeland 
836834c1ba7SJake Freeland 	ATF_REQUIRE(close(kq) == 0);
837834c1ba7SJake Freeland 
838834c1ba7SJake Freeland 	/*
839834c1ba7SJake Freeland 	 * timerfd's should never return early, regardless of how
840834c1ba7SJake Freeland 	 * EVFILT_TIMER behaves.
841834c1ba7SJake Freeland 	 */
842834c1ba7SJake Freeland 
843834c1ba7SJake Freeland 	int timerfd = timerfd_create(CLOCK_MONOTONIC, /**/
844834c1ba7SJake Freeland 	    TFD_CLOEXEC | TFD_NONBLOCK);
845834c1ba7SJake Freeland 
846834c1ba7SJake Freeland 	ATF_REQUIRE(timerfd >= 0);
847834c1ba7SJake Freeland 
848834c1ba7SJake Freeland 	for (int l = 0; l < 10; ++l) {
849834c1ba7SJake Freeland 		for (int i = 1; i <= 17; ++i) {
850834c1ba7SJake Freeland 			struct itimerspec time = {
851834c1ba7SJake Freeland 				.it_value.tv_sec = 0,
852834c1ba7SJake Freeland 				.it_value.tv_nsec = i * 1000000,
853834c1ba7SJake Freeland 			};
854834c1ba7SJake Freeland 
855834c1ba7SJake Freeland 			struct timespec b;
856834c1ba7SJake Freeland 			ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &b) == 0);
857834c1ba7SJake Freeland 
858834c1ba7SJake Freeland 			ATF_REQUIRE(
859834c1ba7SJake Freeland 			    timerfd_settime(timerfd, 0, &time, NULL) == 0);
860834c1ba7SJake Freeland 			(void)wait_for_timerfd(timerfd);
861834c1ba7SJake Freeland 
862834c1ba7SJake Freeland 			struct timespec e;
863834c1ba7SJake Freeland 			ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &e) == 0);
864834c1ba7SJake Freeland 
865834c1ba7SJake Freeland 			struct timespec diff;
866834c1ba7SJake Freeland 			timespecsub(&e, &b, &diff);
867834c1ba7SJake Freeland 
868834c1ba7SJake Freeland 			ATF_REQUIRE(
869834c1ba7SJake Freeland 			    diff.tv_sec == 0 && diff.tv_nsec >= i * 1000000);
870834c1ba7SJake Freeland 			fprintf(stderr, "%dms, waited %lldns\n", i,
871834c1ba7SJake Freeland 			    (long long)diff.tv_nsec);
872834c1ba7SJake Freeland 		}
873834c1ba7SJake Freeland 	}
874834c1ba7SJake Freeland 
875834c1ba7SJake Freeland 	ATF_REQUIRE(close(timerfd) == 0);
876834c1ba7SJake Freeland }
877834c1ba7SJake Freeland 
878834c1ba7SJake Freeland ATF_TC_WITHOUT_HEAD(timerfd__unmodified_errno);
ATF_TC_BODY(timerfd__unmodified_errno,tc)879834c1ba7SJake Freeland ATF_TC_BODY(timerfd__unmodified_errno, tc)
880834c1ba7SJake Freeland {
881834c1ba7SJake Freeland 	ATF_REQUIRE(errno == 0);
882834c1ba7SJake Freeland 	int timerfd = timerfd_create(CLOCK_MONOTONIC, /**/
883834c1ba7SJake Freeland 	    TFD_CLOEXEC | TFD_NONBLOCK);
884834c1ba7SJake Freeland 	ATF_REQUIRE(timerfd >= 0);
885834c1ba7SJake Freeland 	ATF_REQUIRE(errno == 0);
886834c1ba7SJake Freeland 
887834c1ba7SJake Freeland 	ATF_REQUIRE(timerfd_settime(timerfd, 0,
888834c1ba7SJake Freeland 			&(struct itimerspec) {
889834c1ba7SJake Freeland 			    .it_value.tv_sec = 0,
890834c1ba7SJake Freeland 			    .it_value.tv_nsec = 100000000,
891834c1ba7SJake Freeland 			},
892834c1ba7SJake Freeland 			NULL) == 0);
893834c1ba7SJake Freeland 	ATF_REQUIRE(errno == 0);
894834c1ba7SJake Freeland 	(void)wait_for_timerfd(timerfd);
895834c1ba7SJake Freeland 	ATF_REQUIRE(errno == 0);
896834c1ba7SJake Freeland 
897834c1ba7SJake Freeland 	ATF_REQUIRE(timerfd_settime(timerfd, 0,
898834c1ba7SJake Freeland 			&(struct itimerspec) {
899834c1ba7SJake Freeland 			    .it_value.tv_sec = 0,
900834c1ba7SJake Freeland 			    .it_value.tv_nsec = 0,
901834c1ba7SJake Freeland 			},
902834c1ba7SJake Freeland 			NULL) == 0);
903834c1ba7SJake Freeland 	ATF_REQUIRE(errno == 0);
904834c1ba7SJake Freeland 
905834c1ba7SJake Freeland 	ATF_REQUIRE(timerfd_settime(timerfd, 0,
906834c1ba7SJake Freeland 			&(struct itimerspec) {
907834c1ba7SJake Freeland 			    .it_value.tv_sec = 0,
908834c1ba7SJake Freeland 			    .it_value.tv_nsec = 0,
909834c1ba7SJake Freeland 			},
910834c1ba7SJake Freeland 			NULL) == 0);
911834c1ba7SJake Freeland 	ATF_REQUIRE(errno == 0);
912834c1ba7SJake Freeland 
913834c1ba7SJake Freeland 	ATF_REQUIRE(close(timerfd) == 0);
914834c1ba7SJake Freeland 	ATF_REQUIRE(errno == 0);
915834c1ba7SJake Freeland }
916834c1ba7SJake Freeland 
917834c1ba7SJake Freeland ATF_TC_WITHOUT_HEAD(timerfd__reset_to_very_long);
ATF_TC_BODY(timerfd__reset_to_very_long,tc)918834c1ba7SJake Freeland ATF_TC_BODY(timerfd__reset_to_very_long, tc)
919834c1ba7SJake Freeland {
920834c1ba7SJake Freeland 	ATF_REQUIRE(errno == 0);
921834c1ba7SJake Freeland 	int timerfd = timerfd_create(CLOCK_MONOTONIC, /**/
922834c1ba7SJake Freeland 	    TFD_CLOEXEC | TFD_NONBLOCK);
923834c1ba7SJake Freeland 	ATF_REQUIRE(timerfd >= 0);
924834c1ba7SJake Freeland 	ATF_REQUIRE(errno == 0);
925834c1ba7SJake Freeland 
926834c1ba7SJake Freeland 	ATF_REQUIRE(timerfd_settime(timerfd, 0,
927834c1ba7SJake Freeland 			&(struct itimerspec) {
928834c1ba7SJake Freeland 			    .it_value.tv_sec = 0,
929834c1ba7SJake Freeland 			    .it_value.tv_nsec = 100000000,
930834c1ba7SJake Freeland 			},
931834c1ba7SJake Freeland 			NULL) == 0);
932834c1ba7SJake Freeland 	ATF_REQUIRE(errno == 0);
933834c1ba7SJake Freeland 
934834c1ba7SJake Freeland 	ATF_REQUIRE(timerfd_settime(timerfd, 0,
935834c1ba7SJake Freeland 			&(struct itimerspec) {
936834c1ba7SJake Freeland 			    .it_value.tv_sec = 630720000,
937834c1ba7SJake Freeland 			    .it_value.tv_nsec = 0,
938834c1ba7SJake Freeland 			},
939834c1ba7SJake Freeland 			NULL) == 0);
940834c1ba7SJake Freeland 	ATF_REQUIRE(errno == 0);
941834c1ba7SJake Freeland 
942834c1ba7SJake Freeland 	struct pollfd pfd = { .fd = timerfd, .events = POLLIN };
943834c1ba7SJake Freeland 	ATF_REQUIRE(poll(&pfd, 1, 500) == 0);
944834c1ba7SJake Freeland 	uint64_t timeouts;
945834c1ba7SJake Freeland 	ssize_t r = read(timerfd, &timeouts, sizeof(timeouts));
946834c1ba7SJake Freeland 	ATF_REQUIRE_ERRNO(EAGAIN, r < 0);
947834c1ba7SJake Freeland 
948834c1ba7SJake Freeland 	ATF_REQUIRE(close(timerfd) == 0);
949834c1ba7SJake Freeland 	ATF_REQUIRE(errno == EAGAIN);
950834c1ba7SJake Freeland }
951834c1ba7SJake Freeland 
95285c0f1a8SJake Freeland ATF_TC_WITHOUT_HEAD(timerfd__missed_events);
ATF_TC_BODY(timerfd__missed_events,tc)95385c0f1a8SJake Freeland ATF_TC_BODY(timerfd__missed_events, tc)
95485c0f1a8SJake Freeland {
95585c0f1a8SJake Freeland 	struct itimerspec its = { };
95685c0f1a8SJake Freeland 	uint64_t timeouts;
95785c0f1a8SJake Freeland 	int timerfd;
95885c0f1a8SJake Freeland 
95985c0f1a8SJake Freeland 	timerfd = timerfd_create(CLOCK_REALTIME, TFD_CLOEXEC);
96085c0f1a8SJake Freeland 	ATF_REQUIRE(timerfd >= 0);
96185c0f1a8SJake Freeland 
96285c0f1a8SJake Freeland 	ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &its.it_value) == 0);
96385c0f1a8SJake Freeland 	its.it_value.tv_sec -= 1000;
96485c0f1a8SJake Freeland 	its.it_interval.tv_sec = 1;
96585c0f1a8SJake Freeland 
96685c0f1a8SJake Freeland 	ATF_REQUIRE(timerfd_settime(timerfd, TFD_TIMER_ABSTIME, &its,
96785c0f1a8SJake Freeland 	    NULL) == 0);
96885c0f1a8SJake Freeland 
96985c0f1a8SJake Freeland 	ATF_REQUIRE(read(timerfd, &timeouts, sizeof(timeouts)) ==
97085c0f1a8SJake Freeland 	    sizeof(timeouts));
97185c0f1a8SJake Freeland 	ATF_REQUIRE_MSG(timeouts == 1001, "%ld", (long)timeouts);
97285c0f1a8SJake Freeland 
97385c0f1a8SJake Freeland 	ATF_REQUIRE(read(timerfd, &timeouts, sizeof(timeouts)) ==
97485c0f1a8SJake Freeland 	    sizeof(timeouts));
97585c0f1a8SJake Freeland 	ATF_REQUIRE_MSG(timeouts == 1, "%ld", (long)timeouts);
97685c0f1a8SJake Freeland 
97785c0f1a8SJake Freeland 	ATF_REQUIRE(close(timerfd) == 0);
97885c0f1a8SJake Freeland }
97985c0f1a8SJake Freeland 
980834c1ba7SJake Freeland /*
981834c1ba7SJake Freeland  * Tests requiring root (clock_settime on CLOCK_REALTIME).
982834c1ba7SJake Freeland  * Tests gracefully skip if not running as root.
983834c1ba7SJake Freeland  */
984834c1ba7SJake Freeland 
985834c1ba7SJake Freeland static struct timespec current_time;
986834c1ba7SJake Freeland static void
reset_time(void)987834c1ba7SJake Freeland reset_time(void)
988834c1ba7SJake Freeland {
989834c1ba7SJake Freeland 	(void)clock_settime(CLOCK_REALTIME, &current_time);
990834c1ba7SJake Freeland }
991834c1ba7SJake Freeland 
992834c1ba7SJake Freeland static void
clock_settime_or_skip_test(clockid_t clockid,struct timespec const * ts)993834c1ba7SJake Freeland clock_settime_or_skip_test(clockid_t clockid, struct timespec const *ts)
994834c1ba7SJake Freeland {
995834c1ba7SJake Freeland 	int r = clock_settime(clockid, ts);
996834c1ba7SJake Freeland 	if (r < 0 && errno == EPERM) {
997834c1ba7SJake Freeland 		atf_tc_skip("root required");
998834c1ba7SJake Freeland 	}
999834c1ba7SJake Freeland 	ATF_REQUIRE(r == 0);
1000834c1ba7SJake Freeland }
1001834c1ba7SJake Freeland 
1002834c1ba7SJake Freeland ATF_TC_WITHOUT_HEAD(timerfd_root__zero_read_on_abs_realtime);
ATF_TC_BODY(timerfd_root__zero_read_on_abs_realtime,tc)1003834c1ba7SJake Freeland ATF_TC_BODY(timerfd_root__zero_read_on_abs_realtime, tc)
1004834c1ba7SJake Freeland {
1005834c1ba7SJake Freeland 	int tfd = timerfd_create(CLOCK_REALTIME, TFD_CLOEXEC);
1006834c1ba7SJake Freeland 	ATF_REQUIRE(tfd >= 0);
1007834c1ba7SJake Freeland 
1008834c1ba7SJake Freeland 	ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &current_time) == 0);
1009834c1ba7SJake Freeland 	ATF_REQUIRE(atexit(reset_time) == 0);
1010834c1ba7SJake Freeland 
1011834c1ba7SJake Freeland 	ATF_REQUIRE(timerfd_settime(tfd, TFD_TIMER_ABSTIME,
1012834c1ba7SJake Freeland 			&(struct itimerspec) {
1013834c1ba7SJake Freeland 			    .it_value = current_time,
1014834c1ba7SJake Freeland 			    .it_interval.tv_sec = 1,
1015834c1ba7SJake Freeland 			    .it_interval.tv_nsec = 0,
1016834c1ba7SJake Freeland 			},
1017834c1ba7SJake Freeland 			NULL) == 0);
1018834c1ba7SJake Freeland 
1019834c1ba7SJake Freeland 	ATF_REQUIRE(
1020834c1ba7SJake Freeland 	    poll(&(struct pollfd) { .fd = tfd, .events = POLLIN }, 1, -1) == 1);
1021834c1ba7SJake Freeland 
1022834c1ba7SJake Freeland 	clock_settime_or_skip_test(CLOCK_REALTIME,
1023834c1ba7SJake Freeland 	    &(struct timespec) {
1024834c1ba7SJake Freeland 		.tv_sec = current_time.tv_sec - 1,
1025834c1ba7SJake Freeland 		.tv_nsec = current_time.tv_nsec,
1026834c1ba7SJake Freeland 	    });
1027834c1ba7SJake Freeland 
1028834c1ba7SJake Freeland 	uint64_t exp;
1029834c1ba7SJake Freeland 	ssize_t r = read(tfd, &exp, sizeof(exp));
1030834c1ba7SJake Freeland 	ATF_REQUIRE_MSG(r == 0, "r: %d, errno: %d", (int)r, errno);
1031834c1ba7SJake Freeland 
1032834c1ba7SJake Freeland 	{
1033834c1ba7SJake Freeland 		int r = fcntl(tfd, F_GETFL);
1034834c1ba7SJake Freeland 		ATF_REQUIRE(r >= 0);
1035834c1ba7SJake Freeland 		r = fcntl(tfd, F_SETFL, r | O_NONBLOCK);
1036834c1ba7SJake Freeland 		ATF_REQUIRE(r >= 0);
1037834c1ba7SJake Freeland 	}
1038834c1ba7SJake Freeland 
1039834c1ba7SJake Freeland 	r = read(tfd, &exp, sizeof(exp));
1040834c1ba7SJake Freeland 	ATF_REQUIRE_ERRNO(EAGAIN, r < 0);
1041834c1ba7SJake Freeland 
1042834c1ba7SJake Freeland 	current_time.tv_sec += 1;
1043834c1ba7SJake Freeland 	ATF_REQUIRE(poll(&(struct pollfd) { .fd = tfd, .events = POLLIN }, 1,
1044834c1ba7SJake Freeland 			1800) == 1);
1045834c1ba7SJake Freeland 	r = read(tfd, &exp, sizeof(exp));
1046834c1ba7SJake Freeland 	ATF_REQUIRE(r == (ssize_t)sizeof(exp));
1047834c1ba7SJake Freeland 	ATF_REQUIRE(exp == 1);
1048834c1ba7SJake Freeland 
1049834c1ba7SJake Freeland 	ATF_REQUIRE(close(tfd) == 0);
1050834c1ba7SJake Freeland }
1051834c1ba7SJake Freeland 
1052834c1ba7SJake Freeland ATF_TC_WITHOUT_HEAD(timerfd_root__read_on_abs_realtime_no_interval);
ATF_TC_BODY(timerfd_root__read_on_abs_realtime_no_interval,tc)1053834c1ba7SJake Freeland ATF_TC_BODY(timerfd_root__read_on_abs_realtime_no_interval, tc)
1054834c1ba7SJake Freeland {
1055834c1ba7SJake Freeland 	int tfd = timerfd_create(CLOCK_REALTIME, TFD_CLOEXEC);
1056834c1ba7SJake Freeland 	ATF_REQUIRE(tfd >= 0);
1057834c1ba7SJake Freeland 
1058834c1ba7SJake Freeland 	ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &current_time) == 0);
1059834c1ba7SJake Freeland 	ATF_REQUIRE(atexit(reset_time) == 0);
1060834c1ba7SJake Freeland 
1061834c1ba7SJake Freeland 	ATF_REQUIRE(timerfd_settime(tfd, TFD_TIMER_ABSTIME,
1062834c1ba7SJake Freeland 			&(struct itimerspec) {
1063834c1ba7SJake Freeland 			    .it_value = current_time,
1064834c1ba7SJake Freeland 			    .it_interval.tv_sec = 0,
1065834c1ba7SJake Freeland 			    .it_interval.tv_nsec = 0,
1066834c1ba7SJake Freeland 			},
1067834c1ba7SJake Freeland 			NULL) == 0);
1068834c1ba7SJake Freeland 
1069834c1ba7SJake Freeland 	ATF_REQUIRE(
1070834c1ba7SJake Freeland 	    poll(&(struct pollfd) { .fd = tfd, .events = POLLIN }, 1, -1) == 1);
1071834c1ba7SJake Freeland 
1072834c1ba7SJake Freeland 	clock_settime_or_skip_test(CLOCK_REALTIME,
1073834c1ba7SJake Freeland 	    &(struct timespec) {
1074834c1ba7SJake Freeland 		.tv_sec = current_time.tv_sec - 1,
1075834c1ba7SJake Freeland 		.tv_nsec = current_time.tv_nsec,
1076834c1ba7SJake Freeland 	    });
1077834c1ba7SJake Freeland 
1078834c1ba7SJake Freeland 	uint64_t exp;
1079834c1ba7SJake Freeland 	ssize_t r = read(tfd, &exp, sizeof(exp));
1080834c1ba7SJake Freeland 	ATF_REQUIRE(r == (ssize_t)sizeof(exp));
1081834c1ba7SJake Freeland 	ATF_REQUIRE(exp == 1);
1082834c1ba7SJake Freeland 
1083834c1ba7SJake Freeland 	ATF_REQUIRE(close(tfd) == 0);
1084834c1ba7SJake Freeland }
1085834c1ba7SJake Freeland 
1086834c1ba7SJake Freeland ATF_TC_WITHOUT_HEAD(timerfd_root__cancel_on_set);
ATF_TC_BODY(timerfd_root__cancel_on_set,tc)1087834c1ba7SJake Freeland ATF_TC_BODY(timerfd_root__cancel_on_set, tc)
1088834c1ba7SJake Freeland {
1089834c1ba7SJake Freeland 	int tfd = timerfd_create(CLOCK_REALTIME, TFD_CLOEXEC);
1090834c1ba7SJake Freeland 	ATF_REQUIRE(tfd >= 0);
1091834c1ba7SJake Freeland 
1092834c1ba7SJake Freeland 	ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &current_time) == 0);
1093834c1ba7SJake Freeland 	ATF_REQUIRE(atexit(reset_time) == 0);
1094834c1ba7SJake Freeland 
1095834c1ba7SJake Freeland 	ATF_REQUIRE(
1096834c1ba7SJake Freeland 	    timerfd_settime(tfd, TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET,
1097834c1ba7SJake Freeland 		&(struct itimerspec) {
1098834c1ba7SJake Freeland 		    .it_value.tv_sec = current_time.tv_sec + 10,
1099834c1ba7SJake Freeland 		    .it_value.tv_nsec = current_time.tv_nsec,
1100834c1ba7SJake Freeland 		    .it_interval.tv_sec = 0,
1101834c1ba7SJake Freeland 		    .it_interval.tv_nsec = 0,
1102834c1ba7SJake Freeland 		},
1103834c1ba7SJake Freeland 		NULL) == 0);
1104834c1ba7SJake Freeland 
1105834c1ba7SJake Freeland 	clock_settime_or_skip_test(CLOCK_REALTIME, &current_time);
1106834c1ba7SJake Freeland 
1107834c1ba7SJake Freeland 	ATF_REQUIRE(
1108834c1ba7SJake Freeland 	    poll(&(struct pollfd) { .fd = tfd, .events = POLLIN }, 1, -1) == 1);
1109834c1ba7SJake Freeland 
1110834c1ba7SJake Freeland 	{
1111834c1ba7SJake Freeland 		int r = timerfd_settime(tfd,
1112834c1ba7SJake Freeland 		    TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET,
1113834c1ba7SJake Freeland 		    &(struct itimerspec) {
1114834c1ba7SJake Freeland 			.it_value.tv_sec = current_time.tv_sec,
1115834c1ba7SJake Freeland 			.it_value.tv_nsec = current_time.tv_nsec,
1116834c1ba7SJake Freeland 			.it_interval.tv_sec = 0,
1117834c1ba7SJake Freeland 			.it_interval.tv_nsec = 0,
1118834c1ba7SJake Freeland 		    },
1119834c1ba7SJake Freeland 		    NULL);
1120834c1ba7SJake Freeland 		ATF_REQUIRE_ERRNO(ECANCELED, r < 0);
1121834c1ba7SJake Freeland 	}
1122834c1ba7SJake Freeland 
1123834c1ba7SJake Freeland 	ATF_REQUIRE(poll(&(struct pollfd) { .fd = tfd, .events = POLLIN }, 1,
1124834c1ba7SJake Freeland 			800) == 1);
1125834c1ba7SJake Freeland 
1126834c1ba7SJake Freeland 	uint64_t exp;
1127834c1ba7SJake Freeland 	ssize_t r;
1128834c1ba7SJake Freeland 
1129834c1ba7SJake Freeland 	r = read(tfd, &exp, sizeof(exp));
1130834c1ba7SJake Freeland 	ATF_REQUIRE(r == (ssize_t)sizeof(exp));
1131834c1ba7SJake Freeland 	ATF_REQUIRE(exp == 1);
1132834c1ba7SJake Freeland 
1133834c1ba7SJake Freeland 	ATF_REQUIRE(
1134834c1ba7SJake Freeland 	    timerfd_settime(tfd, TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET,
1135834c1ba7SJake Freeland 		&(struct itimerspec) {
1136834c1ba7SJake Freeland 		    .it_value.tv_sec = current_time.tv_sec + 1,
1137834c1ba7SJake Freeland 		    .it_value.tv_nsec = current_time.tv_nsec,
1138834c1ba7SJake Freeland 		    .it_interval.tv_sec = 1,
1139834c1ba7SJake Freeland 		    .it_interval.tv_nsec = 0,
1140834c1ba7SJake Freeland 		},
1141834c1ba7SJake Freeland 		NULL) == 0);
1142834c1ba7SJake Freeland 
1143834c1ba7SJake Freeland 	clock_settime_or_skip_test(CLOCK_REALTIME, &current_time);
1144834c1ba7SJake Freeland 
1145834c1ba7SJake Freeland 	ATF_REQUIRE(
1146834c1ba7SJake Freeland 	    poll(&(struct pollfd) { .fd = tfd, .events = POLLIN }, 1, -1) == 1);
1147834c1ba7SJake Freeland 
1148834c1ba7SJake Freeland 	r = read(tfd, &exp, sizeof(exp));
1149834c1ba7SJake Freeland 	ATF_REQUIRE_ERRNO(ECANCELED, r < 0);
1150834c1ba7SJake Freeland 
1151834c1ba7SJake Freeland 	r = read(tfd, &exp, sizeof(exp));
1152834c1ba7SJake Freeland 	current_time.tv_sec += 1;
1153834c1ba7SJake Freeland 	ATF_REQUIRE_MSG(r == (ssize_t)sizeof(exp), "%d %d", (int)r, errno);
1154834c1ba7SJake Freeland 	ATF_REQUIRE(exp == 1);
1155834c1ba7SJake Freeland 
1156834c1ba7SJake Freeland 	ATF_REQUIRE(
1157834c1ba7SJake Freeland 	    timerfd_settime(tfd, TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET,
1158834c1ba7SJake Freeland 		&(struct itimerspec) {
1159834c1ba7SJake Freeland 		    .it_value.tv_sec = current_time.tv_sec + 1,
1160834c1ba7SJake Freeland 		    .it_value.tv_nsec = current_time.tv_nsec,
1161834c1ba7SJake Freeland 		    .it_interval.tv_sec = 1,
1162834c1ba7SJake Freeland 		    .it_interval.tv_nsec = 0,
1163834c1ba7SJake Freeland 		},
1164834c1ba7SJake Freeland 		NULL) == 0);
1165834c1ba7SJake Freeland 
1166834c1ba7SJake Freeland 	clock_settime_or_skip_test(CLOCK_REALTIME, &current_time);
1167834c1ba7SJake Freeland 	current_time.tv_sec += 2;
1168834c1ba7SJake Freeland 	ATF_REQUIRE(nanosleep(&(struct timespec) { .tv_sec = 2 }, NULL) == 0);
1169834c1ba7SJake Freeland 
1170834c1ba7SJake Freeland 	r = read(tfd, &exp, sizeof(exp));
1171834c1ba7SJake Freeland 	ATF_REQUIRE_ERRNO(ECANCELED, r < 0);
1172834c1ba7SJake Freeland 
1173834c1ba7SJake Freeland 	r = poll(&(struct pollfd) { .fd = tfd, .events = POLLIN }, 1, 3000);
1174834c1ba7SJake Freeland 	ATF_REQUIRE(r == 0);
1175834c1ba7SJake Freeland 	current_time.tv_sec += 3;
1176834c1ba7SJake Freeland 
1177834c1ba7SJake Freeland 	ATF_REQUIRE(close(tfd) == 0);
1178834c1ba7SJake Freeland }
1179834c1ba7SJake Freeland 
1180834c1ba7SJake Freeland ATF_TC_WITHOUT_HEAD(timerfd_root__cancel_on_set_init);
ATF_TC_BODY(timerfd_root__cancel_on_set_init,tc)1181834c1ba7SJake Freeland ATF_TC_BODY(timerfd_root__cancel_on_set_init, tc)
1182834c1ba7SJake Freeland {
1183834c1ba7SJake Freeland 	int tfd = timerfd_create(CLOCK_REALTIME, TFD_CLOEXEC);
1184834c1ba7SJake Freeland 	ATF_REQUIRE(tfd >= 0);
1185834c1ba7SJake Freeland 
1186834c1ba7SJake Freeland 	ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &current_time) == 0);
1187834c1ba7SJake Freeland 	ATF_REQUIRE(atexit(reset_time) == 0);
1188834c1ba7SJake Freeland 
1189834c1ba7SJake Freeland 	clock_settime_or_skip_test(CLOCK_REALTIME, &current_time);
1190834c1ba7SJake Freeland 
1191834c1ba7SJake Freeland 	ATF_REQUIRE(
1192834c1ba7SJake Freeland 	    timerfd_settime(tfd, TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET,
1193834c1ba7SJake Freeland 		&(struct itimerspec) {
1194834c1ba7SJake Freeland 		    .it_value.tv_sec = current_time.tv_sec + 10,
1195834c1ba7SJake Freeland 		    .it_value.tv_nsec = current_time.tv_nsec,
1196834c1ba7SJake Freeland 		    .it_interval.tv_sec = 0,
1197834c1ba7SJake Freeland 		    .it_interval.tv_nsec = 0,
1198834c1ba7SJake Freeland 		},
1199834c1ba7SJake Freeland 		NULL) == 0);
1200834c1ba7SJake Freeland 
1201834c1ba7SJake Freeland 	clock_settime_or_skip_test(CLOCK_REALTIME, &current_time);
1202834c1ba7SJake Freeland 
1203834c1ba7SJake Freeland 	int r = timerfd_settime(tfd,
1204834c1ba7SJake Freeland 	    TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET,
1205834c1ba7SJake Freeland 	    &(struct itimerspec) {
1206834c1ba7SJake Freeland 		.it_value.tv_sec = current_time.tv_sec + 10,
1207834c1ba7SJake Freeland 		.it_value.tv_nsec = current_time.tv_nsec,
1208834c1ba7SJake Freeland 		.it_interval.tv_sec = 0,
1209834c1ba7SJake Freeland 		.it_interval.tv_nsec = 0,
1210834c1ba7SJake Freeland 	    },
1211834c1ba7SJake Freeland 	    NULL);
1212834c1ba7SJake Freeland 	ATF_REQUIRE_ERRNO(ECANCELED, r < 0);
1213834c1ba7SJake Freeland 	ATF_REQUIRE(close(tfd) == 0);
1214834c1ba7SJake Freeland }
1215834c1ba7SJake Freeland 
1216834c1ba7SJake Freeland static void *
clock_change_thread(void * arg)1217834c1ba7SJake Freeland clock_change_thread(void *arg)
1218834c1ba7SJake Freeland {
1219834c1ba7SJake Freeland 	(void)arg;
1220834c1ba7SJake Freeland 
1221834c1ba7SJake Freeland 	fprintf(stderr, "clock change\n");
1222834c1ba7SJake Freeland 	clock_settime_or_skip_test(CLOCK_REALTIME, &current_time);
1223834c1ba7SJake Freeland 
1224834c1ba7SJake Freeland 	current_time.tv_sec += 2;
1225834c1ba7SJake Freeland 	ATF_REQUIRE(nanosleep(&(struct timespec) { .tv_sec = 2 }, NULL) == 0);
1226834c1ba7SJake Freeland 
1227834c1ba7SJake Freeland 	fprintf(stderr, "clock change\n");
1228834c1ba7SJake Freeland 	clock_settime_or_skip_test(CLOCK_REALTIME, &current_time);
1229834c1ba7SJake Freeland 
1230834c1ba7SJake Freeland 	return NULL;
1231834c1ba7SJake Freeland }
1232834c1ba7SJake Freeland 
1233834c1ba7SJake Freeland ATF_TC(timerfd_root__clock_change_notification);
ATF_TC_HEAD(timerfd_root__clock_change_notification,tc)1234834c1ba7SJake Freeland ATF_TC_HEAD(timerfd_root__clock_change_notification, tc)
1235834c1ba7SJake Freeland {
1236834c1ba7SJake Freeland 	atf_tc_set_md_var(tc, "timeout", "10");
1237834c1ba7SJake Freeland }
ATF_TC_BODY(timerfd_root__clock_change_notification,tc)1238834c1ba7SJake Freeland ATF_TC_BODY(timerfd_root__clock_change_notification, tc)
1239834c1ba7SJake Freeland {
1240834c1ba7SJake Freeland 	ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &current_time) == 0);
1241834c1ba7SJake Freeland 	ATF_REQUIRE(atexit(reset_time) == 0);
1242834c1ba7SJake Freeland 
1243834c1ba7SJake Freeland 	clock_settime_or_skip_test(CLOCK_REALTIME, &current_time);
1244834c1ba7SJake Freeland 
1245834c1ba7SJake Freeland #define TIME_T_MAX (time_t)((UINTMAX_C(1) << ((sizeof(time_t) << 3) - 1)) - 1)
1246834c1ba7SJake Freeland 	struct itimerspec its = {
1247834c1ba7SJake Freeland 		.it_value.tv_sec = TIME_T_MAX,
1248834c1ba7SJake Freeland 	};
1249834c1ba7SJake Freeland #undef TIME_T_MAX
1250834c1ba7SJake Freeland 
1251834c1ba7SJake Freeland 	int tfd = timerfd_create(CLOCK_REALTIME, TFD_CLOEXEC);
1252834c1ba7SJake Freeland 	ATF_REQUIRE(tfd >= 0);
1253834c1ba7SJake Freeland 
1254834c1ba7SJake Freeland 	ATF_REQUIRE(
1255834c1ba7SJake Freeland 	    timerfd_settime(tfd, TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET,
1256834c1ba7SJake Freeland 		&its, NULL) == 0);
1257834c1ba7SJake Freeland 
1258834c1ba7SJake Freeland 	pthread_t clock_changer;
1259834c1ba7SJake Freeland 	ATF_REQUIRE(pthread_create(&clock_changer, NULL, /**/
1260834c1ba7SJake Freeland 			clock_change_thread, NULL) == 0);
1261834c1ba7SJake Freeland 
1262834c1ba7SJake Freeland 	uint64_t exp;
1263834c1ba7SJake Freeland 	ssize_t r;
1264834c1ba7SJake Freeland 
1265834c1ba7SJake Freeland 	r = read(tfd, &exp, sizeof(exp));
1266834c1ba7SJake Freeland 	ATF_REQUIRE_ERRNO(ECANCELED, r < 0);
1267834c1ba7SJake Freeland 	fprintf(stderr, "clock change detected\n");
1268834c1ba7SJake Freeland 
1269834c1ba7SJake Freeland 	r = read(tfd, &exp, sizeof(exp));
1270834c1ba7SJake Freeland 	ATF_REQUIRE_ERRNO(ECANCELED, r < 0);
1271834c1ba7SJake Freeland 	fprintf(stderr, "clock change detected\n");
1272834c1ba7SJake Freeland 
1273834c1ba7SJake Freeland 	ATF_REQUIRE(pthread_join(clock_changer, NULL) == 0);
1274834c1ba7SJake Freeland 
1275834c1ba7SJake Freeland 	ATF_REQUIRE(close(tfd) == 0);
1276834c1ba7SJake Freeland }
1277834c1ba7SJake Freeland 
1278834c1ba7SJake Freeland ATF_TC_WITHOUT_HEAD(timerfd_root__advance_time_no_cancel);
ATF_TC_BODY(timerfd_root__advance_time_no_cancel,tc)1279834c1ba7SJake Freeland ATF_TC_BODY(timerfd_root__advance_time_no_cancel, tc)
1280834c1ba7SJake Freeland {
1281834c1ba7SJake Freeland 	int tfd = timerfd_create(CLOCK_REALTIME, TFD_CLOEXEC);
1282834c1ba7SJake Freeland 	ATF_REQUIRE(tfd >= 0);
1283834c1ba7SJake Freeland 
1284834c1ba7SJake Freeland 	ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &current_time) == 0);
1285834c1ba7SJake Freeland 	ATF_REQUIRE(atexit(reset_time) == 0);
1286834c1ba7SJake Freeland 
1287834c1ba7SJake Freeland 	ATF_REQUIRE(timerfd_settime(tfd, TFD_TIMER_ABSTIME,
1288834c1ba7SJake Freeland 			&(struct itimerspec) {
1289834c1ba7SJake Freeland 			    .it_value.tv_sec = current_time.tv_sec + 10,
1290834c1ba7SJake Freeland 			    .it_value.tv_nsec = current_time.tv_nsec,
1291834c1ba7SJake Freeland 			    .it_interval.tv_sec = 0,
1292834c1ba7SJake Freeland 			    .it_interval.tv_nsec = 0,
1293834c1ba7SJake Freeland 			},
1294834c1ba7SJake Freeland 			NULL) == 0);
1295834c1ba7SJake Freeland 
1296834c1ba7SJake Freeland 	current_time.tv_sec += 9;
1297834c1ba7SJake Freeland 	clock_settime_or_skip_test(CLOCK_REALTIME, &current_time);
1298834c1ba7SJake Freeland 	current_time.tv_sec -= 8;
1299834c1ba7SJake Freeland 
1300834c1ba7SJake Freeland 	{
1301834c1ba7SJake Freeland 		int r = poll(&(struct pollfd) { .fd = tfd, .events = POLLIN },
1302834c1ba7SJake Freeland 		    1, 1800);
1303834c1ba7SJake Freeland 		ATF_REQUIRE(r == 1);
1304834c1ba7SJake Freeland 	}
1305834c1ba7SJake Freeland 
1306834c1ba7SJake Freeland 	uint64_t exp;
1307834c1ba7SJake Freeland 	ssize_t r;
1308834c1ba7SJake Freeland 
1309834c1ba7SJake Freeland 	r = read(tfd, &exp, sizeof(exp));
1310834c1ba7SJake Freeland 	ATF_REQUIRE(r == (ssize_t)sizeof(exp));
1311834c1ba7SJake Freeland 	ATF_REQUIRE(exp == 1);
1312834c1ba7SJake Freeland 
1313834c1ba7SJake Freeland 	ATF_REQUIRE(close(tfd) == 0);
1314834c1ba7SJake Freeland }
1315834c1ba7SJake Freeland 
ATF_TP_ADD_TCS(tp)1316834c1ba7SJake Freeland ATF_TP_ADD_TCS(tp)
1317834c1ba7SJake Freeland {
1318834c1ba7SJake Freeland 	ATF_TP_ADD_TC(tp, timerfd__many_timers);
1319834c1ba7SJake Freeland 	ATF_TP_ADD_TC(tp, timerfd__simple_timer);
1320834c1ba7SJake Freeland 	ATF_TP_ADD_TC(tp, timerfd__simple_periodic_timer);
1321834c1ba7SJake Freeland 	ATF_TP_ADD_TC(tp, timerfd__complex_periodic_timer);
1322834c1ba7SJake Freeland 	ATF_TP_ADD_TC(tp, timerfd__reset_periodic_timer);
1323834c1ba7SJake Freeland 	ATF_TP_ADD_TC(tp, timerfd__reenable_periodic_timer);
1324834c1ba7SJake Freeland 	ATF_TP_ADD_TC(tp, timerfd__expire_five);
1325834c1ba7SJake Freeland 	ATF_TP_ADD_TC(tp, timerfd__simple_gettime);
1326834c1ba7SJake Freeland 	ATF_TP_ADD_TC(tp, timerfd__simple_blocking_periodic_timer);
1327834c1ba7SJake Freeland 	ATF_TP_ADD_TC(tp, timerfd__argument_checks);
1328834c1ba7SJake Freeland 	ATF_TP_ADD_TC(tp, timerfd__upgrade_simple_to_complex);
1329834c1ba7SJake Freeland 	ATF_TP_ADD_TC(tp, timerfd__absolute_timer);
1330834c1ba7SJake Freeland 	ATF_TP_ADD_TC(tp, timerfd__absolute_timer_in_the_past);
1331834c1ba7SJake Freeland 	ATF_TP_ADD_TC(tp, timerfd__reset_absolute);
1332834c1ba7SJake Freeland 	ATF_TP_ADD_TC(tp, timerfd__periodic_timer_performance);
1333834c1ba7SJake Freeland 	ATF_TP_ADD_TC(tp, timerfd__argument_overflow);
1334834c1ba7SJake Freeland 	ATF_TP_ADD_TC(tp, timerfd__short_evfilt_timer_timeout);
1335834c1ba7SJake Freeland 	ATF_TP_ADD_TC(tp, timerfd__unmodified_errno);
1336834c1ba7SJake Freeland 	ATF_TP_ADD_TC(tp, timerfd__reset_to_very_long);
133785c0f1a8SJake Freeland 	ATF_TP_ADD_TC(tp, timerfd__missed_events);
1338834c1ba7SJake Freeland 
1339834c1ba7SJake Freeland 	ATF_TP_ADD_TC(tp, timerfd_root__zero_read_on_abs_realtime);
1340834c1ba7SJake Freeland 	ATF_TP_ADD_TC(tp, timerfd_root__read_on_abs_realtime_no_interval);
1341834c1ba7SJake Freeland 	ATF_TP_ADD_TC(tp, timerfd_root__cancel_on_set);
1342834c1ba7SJake Freeland 	ATF_TP_ADD_TC(tp, timerfd_root__cancel_on_set_init);
1343834c1ba7SJake Freeland 	ATF_TP_ADD_TC(tp, timerfd_root__clock_change_notification);
1344834c1ba7SJake Freeland 	ATF_TP_ADD_TC(tp, timerfd_root__advance_time_no_cancel);
1345834c1ba7SJake Freeland 
1346834c1ba7SJake Freeland 	return atf_no_error();
1347834c1ba7SJake Freeland }
1348