]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tests/sys/kqueue/libkqueue/timer.c
ena: Upgrade ena-com to freebsd v2.7.0
[FreeBSD/FreeBSD.git] / tests / sys / kqueue / libkqueue / timer.c
1 /*
2  * Copyright (c) 2009 Mark Heily <mark@heily.com>
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 #include "common.h"
18 #include <sys/time.h>
19
20 #define MILLION 1000000
21 #define THOUSAND 1000
22 #define SEC_TO_MS(t) ((t) * THOUSAND)   /* Convert seconds to milliseconds. */
23 #define SEC_TO_US(t) ((t) * MILLION)    /* Convert seconds to microseconds. */
24 #define MS_TO_US(t)  ((t) * THOUSAND)   /* Convert milliseconds to microseconds. */
25 #define US_TO_NS(t)  ((t) * THOUSAND)   /* Convert microseconds to nanoseconds. */
26
27
28 /* Get the current time with microsecond precision. Used for
29  * sub-second timing to make some timer tests run faster.
30  */
31 static uint64_t
32 now(void)
33 {
34     struct timeval tv;
35
36     gettimeofday(&tv, NULL);
37     /* Promote potentially 32-bit time_t to uint64_t before conversion. */
38     return SEC_TO_US((uint64_t)tv.tv_sec) + tv.tv_usec;
39 }
40
41 /* Sleep for a given number of milliseconds. The timeout is assumed to
42  * be less than 1 second.
43  */
44 static void
45 mssleep(int t)
46 {
47     struct timespec stime = {
48         .tv_sec = 0,
49         .tv_nsec = US_TO_NS(MS_TO_US(t)),
50     };
51
52     nanosleep(&stime, NULL);
53 }
54
55 /* Sleep for a given number of microseconds. The timeout is assumed to
56  * be less than 1 second.
57  */
58 static void
59 ussleep(int t)
60 {
61     struct timespec stime = {
62         .tv_sec = 0,
63         .tv_nsec = US_TO_NS(t),
64     };
65
66     nanosleep(&stime, NULL);
67 }
68
69 static void
70 test_kevent_timer_add(void)
71 {
72     const char *test_id = "kevent(EVFILT_TIMER, EV_ADD)";
73     struct kevent kev;
74
75     test_begin(test_id);
76
77     EV_SET(&kev, 1, EVFILT_TIMER, EV_ADD, 0, 1000, NULL);
78     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
79         err(1, "%s", test_id);
80
81     success();
82 }
83
84 static void
85 test_kevent_timer_del(void)
86 {
87     const char *test_id = "kevent(EVFILT_TIMER, EV_DELETE)";
88     struct kevent kev;
89
90     test_begin(test_id);
91
92     EV_SET(&kev, 1, EVFILT_TIMER, EV_DELETE, 0, 0, NULL);
93     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
94         err(1, "%s", test_id);
95
96     test_no_kevents();
97
98     success();
99 }
100
101 static void
102 test_kevent_timer_get(void)
103 {
104     const char *test_id = "kevent(EVFILT_TIMER, wait)";
105     struct kevent kev;
106
107     test_begin(test_id);
108
109     EV_SET(&kev, 1, EVFILT_TIMER, EV_ADD, 0, 1000, NULL);
110     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
111         err(1, "%s", test_id);
112
113     kev.flags |= EV_CLEAR;
114     kev.data = 1; 
115     kevent_cmp(&kev, kevent_get(kqfd));
116
117     EV_SET(&kev, 1, EVFILT_TIMER, EV_DELETE, 0, 0, NULL);
118     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
119         err(1, "%s", test_id);
120
121     success();
122 }
123
124 static void
125 test_oneshot(void)
126 {
127     const char *test_id = "kevent(EVFILT_TIMER, EV_ONESHOT)";
128     struct kevent kev;
129
130     test_begin(test_id);
131
132     test_no_kevents();
133
134     EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 500,NULL);
135     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
136         err(1, "%s", test_id);
137
138     /* Retrieve the event */
139     kev.flags = EV_ADD | EV_CLEAR | EV_ONESHOT;
140     kev.data = 1; 
141     kevent_cmp(&kev, kevent_get(kqfd));
142
143     /* Check if the event occurs again */
144     sleep(3);
145     test_no_kevents();
146
147
148     success();
149 }
150
151 static void
152 test_periodic(void)
153 {
154     const char *test_id = "kevent(EVFILT_TIMER, periodic)";
155     struct kevent kev;
156
157     test_begin(test_id);
158
159     test_no_kevents();
160
161     EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD, 0, 1000,NULL);
162     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
163         err(1, "%s", test_id);
164
165     /* Retrieve the event */
166     kev.flags = EV_ADD | EV_CLEAR;
167     kev.data = 1; 
168     kevent_cmp(&kev, kevent_get(kqfd));
169
170     /* Check if the event occurs again */
171     sleep(1);
172     kevent_cmp(&kev, kevent_get(kqfd));
173
174     /* Delete the event */
175     kev.flags = EV_DELETE;
176     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
177         err(1, "%s", test_id);
178
179     success();
180 }
181
182 static void
183 test_periodic_modify(void)
184 {
185     const char *test_id = "kevent(EVFILT_TIMER, periodic_modify)";
186     struct kevent kev;
187
188     test_begin(test_id);
189
190     test_no_kevents();
191
192     EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD, 0, 1000, NULL);
193     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
194         err(1, "%s", test_id);
195
196     /* Retrieve the event */
197     kev.flags = EV_ADD | EV_CLEAR;
198     kev.data = 1;
199     kevent_cmp(&kev, kevent_get(kqfd));
200
201     /* Check if the event occurs again */
202     EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD, 0, 500, NULL);
203     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
204         err(1, "%s", test_id);
205
206     kev.flags = EV_ADD | EV_CLEAR;
207     sleep(1);
208     kev.data = 2;       /* Should have fired twice */
209
210     kevent_cmp(&kev, kevent_get(kqfd));
211
212     /* Delete the event */
213     kev.flags = EV_DELETE;
214     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
215         err(1, "%s", test_id);
216
217     success();
218 }
219
220 #if WITH_NATIVE_KQUEUE_BUGS
221 static void
222 test_periodic_to_oneshot(void)
223 {
224     const char *test_id = "kevent(EVFILT_TIMER, period_to_oneshot)";
225     struct kevent kev;
226
227     test_begin(test_id);
228
229     test_no_kevents();
230
231     EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD, 0, 1000, NULL);
232     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
233         err(1, "%s", test_id);
234
235     /* Retrieve the event */
236     kev.flags = EV_ADD | EV_CLEAR;
237     kev.data = 1;
238     kevent_cmp(&kev, kevent_get(kqfd));
239
240     /* Check if the event occurs again */
241     sleep(1);
242     kevent_cmp(&kev, kevent_get(kqfd));
243
244     /* Switch to oneshot */
245     EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 500, NULL);
246     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
247         err(1, "%s", test_id);
248     kev.flags = EV_ADD | EV_CLEAR | EV_ONESHOT;
249
250     sleep(1);
251     kev.data = 1;       /* Should have fired once */
252
253     kevent_cmp(&kev, kevent_get(kqfd));
254
255     success();
256 }
257 #endif
258
259 static void
260 test_disable_and_enable(void)
261 {
262     const char *test_id = "kevent(EVFILT_TIMER, EV_DISABLE and EV_ENABLE)";
263     struct kevent kev;
264
265     test_begin(test_id);
266
267     test_no_kevents();
268
269     /* Add the watch and immediately disable it */
270     EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 2000,NULL);
271     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
272         err(1, "%s", test_id);
273     kev.flags = EV_DISABLE;
274     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
275         err(1, "%s", test_id);
276     test_no_kevents();
277
278     /* Re-enable and check again */
279     kev.flags = EV_ENABLE;
280     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
281         err(1, "%s", test_id);
282
283     kev.flags = EV_ADD | EV_CLEAR | EV_ONESHOT;
284     kev.data = 1; 
285     kevent_cmp(&kev, kevent_get(kqfd));
286
287     success();
288 }
289
290 static void
291 test_abstime(void)
292 {
293     const char *test_id = "kevent(EVFILT_TIMER, EV_ONESHOT, NOTE_ABSTIME)";
294     struct kevent kev;
295     uint64_t end, start, stop;
296     const int timeout_sec = 3;
297
298     test_begin(test_id);
299
300     test_no_kevents();
301
302     start = now();
303     end = start + SEC_TO_US(timeout_sec);
304     EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD | EV_ONESHOT,
305       NOTE_ABSTIME | NOTE_USECONDS, end, NULL);
306     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
307         err(1, "%s", test_id);
308
309     /* Retrieve the event */
310     kev.flags = EV_ADD | EV_ONESHOT;
311     kev.data = 1;
312     kev.fflags = 0;
313     kevent_cmp(&kev, kevent_get(kqfd));
314
315     stop = now();
316     if (stop < end)
317         err(1, "too early %jd %jd", (intmax_t)stop, (intmax_t)end);
318     /* Check if the event occurs again */
319     sleep(3);
320     test_no_kevents();
321
322     success();
323 }
324
325 static void
326 test_abstime_epoch(void)
327 {
328     const char *test_id = "kevent(EVFILT_TIMER (EPOCH), NOTE_ABSTIME)";
329     struct kevent kev;
330
331     test_begin(test_id);
332
333     test_no_kevents();
334
335     EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD, NOTE_ABSTIME, 0,
336         NULL);
337     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
338         err(1, "%s", test_id);
339
340     /* Retrieve the event */
341     kev.flags = EV_ADD;
342     kev.data = 1;
343     kev.fflags = 0;
344     kevent_cmp(&kev, kevent_get(kqfd));
345
346     /* Delete the event */
347     kev.flags = EV_DELETE;
348     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
349         err(1, "%s", test_id);
350
351     success();
352 }
353
354 static void
355 test_abstime_preboot(void)
356 {
357     const char *test_id = "kevent(EVFILT_TIMER (PREBOOT), EV_ONESHOT, NOTE_ABSTIME)";
358     struct kevent kev;
359     struct timespec btp;
360     uint64_t end, start, stop;
361
362     test_begin(test_id);
363
364     test_no_kevents();
365
366     /*
367      * We'll expire it at just before system boot (roughly) with the hope that
368      * we'll get an ~immediate expiration, just as we do for any value specified
369      * between system boot and now.
370      */
371     start = now();
372     if (clock_gettime(CLOCK_BOOTTIME, &btp) != 0)
373       err(1, "%s", test_id);
374
375     end = start - SEC_TO_US(btp.tv_sec + 1);
376     EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD | EV_ONESHOT,
377       NOTE_ABSTIME | NOTE_USECONDS, end, NULL);
378     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
379         err(1, "%s", test_id);
380
381     /* Retrieve the event */
382     kev.flags = EV_ADD | EV_ONESHOT;
383     kev.data = 1;
384     kev.fflags = 0;
385     kevent_cmp(&kev, kevent_get(kqfd));
386
387     stop = now();
388     if (stop < end)
389         err(1, "too early %jd %jd", (intmax_t)stop, (intmax_t)end);
390     /* Check if the event occurs again */
391     sleep(3);
392     test_no_kevents();
393
394     success();
395 }
396
397 static void
398 test_abstime_postboot(void)
399 {
400     const char *test_id = "kevent(EVFILT_TIMER (POSTBOOT), EV_ONESHOT, NOTE_ABSTIME)";
401     struct kevent kev;
402     uint64_t end, start, stop;
403     const int timeout_sec = 1;
404
405     test_begin(test_id);
406
407     test_no_kevents();
408
409     /*
410      * Set a timer for 1 second ago, it should fire immediately rather than
411      * being rejected.
412      */
413     start = now();
414     end = start - SEC_TO_US(timeout_sec);
415     EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD | EV_ONESHOT,
416       NOTE_ABSTIME | NOTE_USECONDS, end, NULL);
417     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
418         err(1, "%s", test_id);
419
420     /* Retrieve the event */
421     kev.flags = EV_ADD | EV_ONESHOT;
422     kev.data = 1;
423     kev.fflags = 0;
424     kevent_cmp(&kev, kevent_get(kqfd));
425
426     stop = now();
427     if (stop < end)
428         err(1, "too early %jd %jd", (intmax_t)stop, (intmax_t)end);
429     /* Check if the event occurs again */
430     sleep(3);
431     test_no_kevents();
432
433     success();
434 }
435
436 static void
437 test_update(void)
438 {
439     const char *test_id = "kevent(EVFILT_TIMER (UPDATE), EV_ADD | EV_ONESHOT)";
440     struct kevent kev;
441     long elapsed;
442     uint64_t start;
443
444     test_begin(test_id);
445
446     test_no_kevents();
447
448     /* First set the timer to 1 second */
449     EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD | EV_ONESHOT,
450         NOTE_USECONDS, SEC_TO_US(1), (void *)1);
451     start = now();
452     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
453         err(1, "%s", test_id);
454
455     /* Now reduce the timer to 1 ms */
456     EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD | EV_ONESHOT,
457         NOTE_USECONDS, MS_TO_US(1), (void *)2);
458     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
459         err(1, "%s", test_id);
460
461     /* Wait for the event */
462     kev.flags |= EV_CLEAR;
463     kev.fflags &= ~NOTE_USECONDS;
464     kev.data = 1;
465     kevent_cmp(&kev, kevent_get(kqfd));
466     elapsed = now() - start;
467
468     /* Check that the timer expired after at least 1 ms, but less than
469      * 1 second. This check is to make sure that the original 1 second
470      * timeout was not used.
471      */
472     printf("timer expired after %ld us\n", elapsed);
473     if (elapsed < MS_TO_US(1))
474         errx(1, "early timer expiration: %ld us", elapsed);
475     if (elapsed > SEC_TO_US(1))
476         errx(1, "late timer expiration: %ld us", elapsed);
477
478     success();
479 }
480
481 static void
482 test_update_equal(void)
483 {
484     const char *test_id = "kevent(EVFILT_TIMER (UPDATE=), EV_ADD | EV_ONESHOT)";
485     struct kevent kev;
486     long elapsed;
487     uint64_t start;
488
489     test_begin(test_id);
490
491     test_no_kevents();
492
493     /* First set the timer to 1 ms */
494     EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD | EV_ONESHOT,
495         NOTE_USECONDS, MS_TO_US(1), NULL);
496     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
497         err(1, "%s", test_id);
498
499     /* Sleep for a significant fraction of the timeout. */
500     ussleep(600);
501     
502     /* Now re-add the timer with the same parameters */
503     start = now();
504     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
505         err(1, "%s", test_id);
506
507     /* Wait for the event */
508     kev.flags |= EV_CLEAR;
509     kev.fflags &= ~NOTE_USECONDS;
510     kev.data = 1;
511     kevent_cmp(&kev, kevent_get(kqfd));
512     elapsed = now() - start;
513
514     /* Check that the timer expired after at least 1 ms. This check is
515      * to make sure that the timer re-started and that the event is
516      * not from the original add of the timer.
517      */
518     printf("timer expired after %ld us\n", elapsed);
519     if (elapsed < MS_TO_US(1))
520         errx(1, "early timer expiration: %ld us", elapsed);
521
522     success();
523 }
524
525 static void
526 test_update_expired(void)
527 {
528     const char *test_id = "kevent(EVFILT_TIMER (UPDATE EXP), EV_ADD | EV_ONESHOT)";
529     struct kevent kev;
530     long elapsed;
531     uint64_t start;
532
533     test_begin(test_id);
534
535     test_no_kevents();
536
537     /* Set the timer to 1ms */
538     EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD | EV_ONESHOT,
539         NOTE_USECONDS, MS_TO_US(1), NULL);
540     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
541         err(1, "%s", test_id);
542
543     /* Wait for 2 ms to give the timer plenty of time to expire. */
544     mssleep(2);
545     
546     /* Now re-add the timer */
547     start = now();
548     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
549         err(1, "%s", test_id);
550
551     /* Wait for the event */
552     kev.flags |= EV_CLEAR;
553     kev.fflags &= ~NOTE_USECONDS;
554     kev.data = 1;
555     kevent_cmp(&kev, kevent_get(kqfd));
556     elapsed = now() - start;
557     
558     /* Check that the timer expired after at least 1 ms.  This check
559      * is to make sure that the timer re-started and that the event is
560      * not from the original add (and expiration) of the timer.
561      */
562     printf("timer expired after %ld us\n", elapsed);
563     if (elapsed < MS_TO_US(1))
564         errx(1, "early timer expiration: %ld us", elapsed);
565
566     /* Make sure the re-added timer does not fire. In other words,
567      * test that the event received above was the only event from the
568      * add and re-add of the timer.
569      */
570     mssleep(2);
571     test_no_kevents();
572
573     success();
574 }
575
576 static void
577 test_update_periodic(void)
578 {
579     const char *test_id = "kevent(EVFILT_TIMER (UPDATE), periodic)";
580     struct kevent kev;
581     long elapsed;
582     uint64_t start, stop;
583
584     test_begin(test_id);
585
586     test_no_kevents();
587
588     EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD, 0, SEC_TO_MS(1), NULL);
589     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
590         err(1, "%s", test_id);
591
592     /* Retrieve the event */
593     kev.flags = EV_ADD | EV_CLEAR;
594     kev.data = 1; 
595     kevent_cmp(&kev, kevent_get(kqfd));
596
597     /* Check if the event occurs again */
598     sleep(1);
599     kevent_cmp(&kev, kevent_get(kqfd));
600
601     /* Re-add with new timeout. */
602     EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD, 0, SEC_TO_MS(2), NULL);
603     start = now();
604     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
605         err(1, "%s", test_id);
606
607     /* Retrieve the event */
608     kev.flags = EV_ADD | EV_CLEAR;
609     kev.data = 1; 
610     kevent_cmp(&kev, kevent_get(kqfd));
611
612     stop = now();
613     elapsed = stop - start;
614
615     /* Check that the timer expired after at least 2 ms.
616      */
617     printf("timer expired after %ld us\n", elapsed);
618     if (elapsed < MS_TO_US(2))
619         errx(1, "early timer expiration: %ld us", elapsed);
620
621     /* Delete the event */
622     kev.flags = EV_DELETE;
623     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
624         err(1, "%s", test_id);
625
626     success();
627 }
628
629 static void
630 test_update_timing(void)
631 {
632 #define MIN_SLEEP 500
633 #define MAX_SLEEP 1500
634     const char *test_id = "kevent(EVFILT_TIMER (UPDATE TIMING), EV_ADD | EV_ONESHOT)";
635     struct kevent kev;
636     int iteration;
637     int sleeptime;
638     long elapsed;
639     uint64_t start, stop;
640
641     test_begin(test_id);
642
643     test_no_kevents();
644
645     /* Re-try the update tests with a variety of delays between the
646      * original timer activation and the update of the timer. The goal
647      * is to show that in all cases the only timer event that is
648      * received is from the update and not the original timer add.
649      */
650     for (sleeptime = MIN_SLEEP, iteration = 1;
651          sleeptime < MAX_SLEEP;
652          ++sleeptime, ++iteration) {
653
654         /* First set the timer to 1 ms */
655         EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD | EV_ONESHOT,
656             NOTE_USECONDS, MS_TO_US(1), NULL);
657         if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
658             err(1, "%s", test_id);
659
660         /* Delay; the delay ranges from less than to greater than the
661          * timer period.
662          */
663         ussleep(sleeptime);
664     
665         /* Now re-add the timer with the same parameters */
666         start = now();
667         if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
668             err(1, "%s", test_id);
669
670         /* Wait for the event */
671         kev.flags |= EV_CLEAR;
672         kev.fflags &= ~NOTE_USECONDS;
673         kev.data = 1;
674         kevent_cmp(&kev, kevent_get(kqfd));
675         stop = now();
676         elapsed = stop - start;
677
678         /* Check that the timer expired after at least 1 ms. This
679          * check is to make sure that the timer re-started and that
680          * the event is not from the original add of the timer.
681          */
682         if (elapsed < MS_TO_US(1))
683             errx(1, "early timer expiration: %ld us", elapsed);
684
685         /* Make sure the re-added timer does not fire. In other words,
686          * test that the event received above was the only event from
687          * the add and re-add of the timer.
688          */
689         mssleep(2);
690         test_no_kevents_quietly();
691     }
692
693     success();
694 }
695
696 static void
697 test_dispatch(void)
698 {
699     const char *test_id = "kevent(EVFILT_TIMER, EV_ADD | EV_DISPATCH)";
700     struct kevent kev;
701
702     test_no_kevents();
703
704     EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD | EV_DISPATCH, 0, 200, NULL);
705     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
706         err(1, "%s", test_id);
707
708     /* Get one event */
709     kev.flags = EV_ADD | EV_CLEAR | EV_DISPATCH;
710     kev.data = 1;
711     kevent_cmp(&kev, kevent_get(kqfd));
712
713     /* Confirm that the knote is disabled due to EV_DISPATCH */
714     usleep(500000);
715     test_no_kevents();
716
717     /* Enable the knote and make sure no events are pending */
718     EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD | EV_ENABLE | EV_DISPATCH, 0, 200, NULL);
719     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
720         err(1, "%s", test_id);
721     test_no_kevents();
722
723     /* Get the next event */
724     usleep(1100000); /* 1100 ms */
725     kev.flags = EV_ADD | EV_CLEAR | EV_DISPATCH;
726     kev.data = 5;
727     kevent_cmp(&kev, kevent_get(kqfd));
728
729     /* Remove the knote and ensure the event no longer fires */
730     EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_DELETE, 0, 0, NULL);
731     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
732         err(1, "%s", test_id);
733     usleep(500000); /* 500ms */
734     test_no_kevents();
735
736     success();
737 }
738
739 void
740 test_evfilt_timer(void)
741 {
742     kqfd = kqueue();
743     test_kevent_timer_add();
744     test_kevent_timer_del();
745     test_kevent_timer_get();
746     test_oneshot();
747     test_periodic();
748     test_periodic_modify();
749 #if WITH_NATIVE_KQUEUE_BUGS
750     test_periodic_to_oneshot();
751 #endif
752     test_abstime();
753     test_abstime_epoch();
754     test_abstime_preboot();
755     test_abstime_postboot();
756     test_update();
757     test_update_equal();
758     test_update_expired();
759     test_update_timing();
760     test_update_periodic();
761     test_disable_and_enable();
762     test_dispatch();
763     close(kqfd);
764 }