Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/tests/sys/kqueue/libkqueue/timer.c
39566 views
1
/*
2
* Copyright (c) 2009 Mark Heily <[email protected]>
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, 495, 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
}
765
766