Remove building with NOCRYPTO option
[minix.git] / external / bsd / bind / dist / bin / tests / timers / t_timers.c
blob66cf77e525c95ba390b063427655f015f7f95068
1 /* $NetBSD: t_timers.c,v 1.6 2014/12/10 04:37:54 christos Exp $ */
3 /*
4 * Copyright (C) 2004, 2007-2009, 2011, 2013 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1999-2001 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: t_timers.c,v 1.33 2011/03/14 14:13:10 fdupont Exp */
22 #include <config.h>
24 #include <stdlib.h>
26 #include <isc/condition.h>
27 #include <isc/mem.h>
28 #include <isc/platform.h>
29 #include <isc/task.h>
30 #include <isc/time.h>
31 #include <isc/timer.h>
32 #include <isc/util.h>
34 #include <tests/t_api.h>
36 #ifdef ISC_PLATFORM_USETHREADS
37 isc_boolean_t threaded = ISC_TRUE;
38 #else
39 isc_boolean_t threaded = ISC_FALSE;
40 #endif
42 #define Tx_FUDGE_SECONDS 0 /* in absence of clock_getres() */
43 #define Tx_FUDGE_NANOSECONDS 500000000 /* in absence of clock_getres() */
45 static isc_time_t Tx_endtime;
46 static isc_time_t Tx_lasttime;
47 static int Tx_eventcnt;
48 static int Tx_nevents;
49 static isc_mutex_t Tx_mx;
50 static isc_condition_t Tx_cv;
51 static int Tx_nfails;
52 static int Tx_nprobs;
53 static isc_timer_t *Tx_timer;
54 static int Tx_seconds;
55 static int Tx_nanoseconds;
57 static void
58 require_threads(void) {
59 t_info("This test requires threads\n");
60 t_result(T_THREADONLY);
61 return;
64 static void
65 tx_sde(isc_task_t *task, isc_event_t *event) {
66 isc_result_t isc_result;
68 UNUSED(task);
69 UNUSED(event);
72 * Signal shutdown processing complete.
74 isc_result = isc_mutex_lock(&Tx_mx);
75 if (isc_result != ISC_R_SUCCESS) {
76 t_info("isc_mutex_lock failed %s\n",
77 isc_result_totext(isc_result));
78 ++Tx_nprobs;
81 isc_result = isc_condition_signal(&Tx_cv);
82 if (isc_result != ISC_R_SUCCESS) {
83 t_info("isc_condition_signal failed %s\n",
84 isc_result_totext(isc_result));
85 ++Tx_nprobs;
88 isc_result = isc_mutex_unlock(&Tx_mx);
89 if (isc_result != ISC_R_SUCCESS) {
90 t_info("isc_mutex_unlock failed %s\n",
91 isc_result_totext(isc_result));
92 ++Tx_nprobs;
95 isc_event_free(&event);
98 static void
99 tx_te(isc_task_t *task, isc_event_t *event) {
100 isc_result_t isc_result;
101 isc_time_t now;
102 isc_time_t base;
103 isc_time_t ulim;
104 isc_time_t llim;
105 isc_interval_t interval;
106 isc_eventtype_t expected_event_type;
108 ++Tx_eventcnt;
110 t_info("tick %d\n", Tx_eventcnt);
112 expected_event_type = ISC_TIMEREVENT_LIFE;
113 if ((isc_timertype_t) event->ev_arg == isc_timertype_ticker)
114 expected_event_type = ISC_TIMEREVENT_TICK;
116 if (event->ev_type != expected_event_type) {
117 t_info("expected event type %d, got %d\n",
118 expected_event_type, (int) event->ev_type);
119 ++Tx_nfails;
122 isc_result = isc_time_now(&now);
123 if (isc_result == ISC_R_SUCCESS) {
124 isc_interval_set(&interval, Tx_seconds, Tx_nanoseconds);
125 isc_result = isc_time_add(&Tx_lasttime, &interval, &base);
126 if (isc_result != ISC_R_SUCCESS) {
127 t_info("isc_time_add failed %s\n",
128 isc_result_totext(isc_result));
129 ++Tx_nprobs;
131 } else {
132 t_info("isc_time_now failed %s\n",
133 isc_result_totext(isc_result));
134 ++Tx_nprobs;
137 if (isc_result == ISC_R_SUCCESS) {
138 isc_interval_set(&interval,
139 Tx_FUDGE_SECONDS, Tx_FUDGE_NANOSECONDS);
140 isc_result = isc_time_add(&base, &interval, &ulim);
141 if (isc_result != ISC_R_SUCCESS) {
142 t_info("isc_time_add failed %s\n",
143 isc_result_totext(isc_result));
144 ++Tx_nprobs;
148 if (isc_result == ISC_R_SUCCESS) {
149 isc_result = isc_time_subtract(&base, &interval, &llim);
150 if (isc_result != ISC_R_SUCCESS) {
151 t_info("isc_time_subtract failed %s\n",
152 isc_result_totext(isc_result));
153 ++Tx_nprobs;
157 if (isc_result == ISC_R_SUCCESS) {
158 if (isc_time_compare(&llim, &now) > 0) {
159 t_info("timer range error: early by "
160 "%lu microseconds\n",
161 (unsigned long)isc_time_microdiff(&base, &now));
162 ++Tx_nfails;
163 } else if (isc_time_compare(&ulim, &now) < 0) {
164 t_info("timer range error: late by "
165 "%lu microseconds\n",
166 (unsigned long)isc_time_microdiff(&now, &base));
167 ++Tx_nfails;
169 Tx_lasttime = now;
172 if (Tx_eventcnt == Tx_nevents) {
173 isc_result = isc_time_now(&Tx_endtime);
174 if (isc_result != ISC_R_SUCCESS) {
175 t_info("isc_time_now failed %s\n",
176 isc_result_totext(isc_result));
177 ++Tx_nprobs;
179 isc_timer_detach(&Tx_timer);
180 isc_task_shutdown(task);
183 isc_event_free(&event);
186 static void
187 t_timers_x(isc_timertype_t timertype, isc_time_t *expires,
188 isc_interval_t *interval,
189 void (*action)(isc_task_t *, isc_event_t *))
191 char *p;
192 isc_mem_t *mctx;
193 isc_taskmgr_t *tmgr;
194 isc_task_t *task;
195 unsigned int workers;
196 isc_result_t isc_result;
197 isc_timermgr_t *timermgr;
199 Tx_eventcnt = 0;
200 isc_time_settoepoch(&Tx_endtime);
202 workers = 2;
203 p = t_getenv("ISC_TASK_WORKERS");
204 if (p != NULL)
205 workers = atoi(p);
207 mctx = NULL;
208 isc_result = isc_mem_create(0, 0, &mctx);
209 if (isc_result != ISC_R_SUCCESS) {
210 t_info("isc_mem_create failed %s\n",
211 isc_result_totext(isc_result));
212 ++Tx_nprobs;
213 return;
216 isc_result = isc_mutex_init(&Tx_mx);
217 if (isc_result != ISC_R_SUCCESS) {
218 t_info("isc_mutex_init failed %s\n",
219 isc_result_totext(isc_result));
220 isc_mem_destroy(&mctx);
221 ++Tx_nprobs;
222 return;
225 isc_result = isc_condition_init(&Tx_cv);
226 if (isc_result != ISC_R_SUCCESS) {
227 t_info("isc_condition_init failed %s\n",
228 isc_result_totext(isc_result));
229 DESTROYLOCK(&Tx_mx);
230 isc_mem_destroy(&mctx);
231 ++Tx_nprobs;
232 return;
235 tmgr = NULL;
236 isc_result = isc_taskmgr_create(mctx, workers, 0, &tmgr);
237 if (isc_result != ISC_R_SUCCESS) {
238 t_info("isc_taskmgr_create failed %s\n",
239 isc_result_totext(isc_result));
240 DESTROYLOCK(&Tx_mx);
241 (void) isc_condition_destroy(&Tx_cv);
242 isc_mem_destroy(&mctx);
243 ++Tx_nprobs;
244 return;
247 timermgr = NULL;
248 isc_result = isc_timermgr_create(mctx, &timermgr);
249 if (isc_result != ISC_R_SUCCESS) {
250 t_info("isc_timermgr_create failed %s\n",
251 isc_result_totext(isc_result));
252 isc_taskmgr_destroy(&tmgr);
253 DESTROYLOCK(&Tx_mx);
254 (void) isc_condition_destroy(&Tx_cv);
255 isc_mem_destroy(&mctx);
256 ++Tx_nprobs;
257 return;
260 isc_result = isc_mutex_lock(&Tx_mx);
261 if (isc_result != ISC_R_SUCCESS) {
262 t_info("isc_mutex_lock failed %s\n",
263 isc_result_totext(isc_result));
264 isc_timermgr_destroy(&timermgr);
265 isc_taskmgr_destroy(&tmgr);
266 DESTROYLOCK(&Tx_mx);
267 (void) isc_condition_destroy(&Tx_cv);
268 isc_mem_destroy(&mctx);
269 ++Tx_nprobs;
270 return;
273 task = NULL;
274 isc_result = isc_task_create(tmgr, 0, &task);
275 if (isc_result != ISC_R_SUCCESS) {
276 t_info("isc_task_create failed %s\n",
277 isc_result_totext(isc_result));
278 isc_timermgr_destroy(&timermgr);
279 isc_taskmgr_destroy(&tmgr);
280 DESTROYLOCK(&Tx_mx);
281 (void) isc_condition_destroy(&Tx_cv);
282 isc_mem_destroy(&mctx);
283 ++Tx_nprobs;
284 return;
287 isc_result = isc_task_onshutdown(task, tx_sde, NULL);
288 if (isc_result != ISC_R_SUCCESS) {
289 t_info("isc_task_onshutdown failed %s\n",
290 isc_result_totext(isc_result));
291 isc_timermgr_destroy(&timermgr);
292 isc_task_destroy(&task);
293 isc_taskmgr_destroy(&tmgr);
294 DESTROYLOCK(&Tx_mx);
295 (void) isc_condition_destroy(&Tx_cv);
296 isc_mem_destroy(&mctx);
297 ++Tx_nprobs;
298 return;
301 isc_result = isc_time_now(&Tx_lasttime);
302 if (isc_result != ISC_R_SUCCESS) {
303 isc_timermgr_destroy(&timermgr);
304 isc_task_destroy(&task);
305 isc_taskmgr_destroy(&tmgr);
306 DESTROYLOCK(&Tx_mx);
307 (void) isc_condition_destroy(&Tx_cv);
308 isc_mem_destroy(&mctx);
309 ++Tx_nprobs;
310 return;
313 Tx_timer = NULL;
314 isc_result = isc_timer_create(timermgr, timertype, expires, interval,
315 task, action, (void *)timertype,
316 &Tx_timer);
318 if (isc_result != ISC_R_SUCCESS) {
319 isc_timermgr_destroy(&timermgr);
320 isc_task_destroy(&task);
321 isc_taskmgr_destroy(&tmgr);
322 DESTROYLOCK(&Tx_mx);
323 (void) isc_condition_destroy(&Tx_cv);
324 isc_mem_destroy(&mctx);
325 ++Tx_nprobs;
326 return;
330 * Wait for shutdown processing to complete.
332 while (Tx_eventcnt != Tx_nevents) {
333 isc_result = isc_condition_wait(&Tx_cv, &Tx_mx);
334 if (isc_result != ISC_R_SUCCESS) {
335 t_info("isc_condition_waituntil failed %s\n",
336 isc_result_totext(isc_result));
337 ++Tx_nprobs;
341 isc_result = isc_mutex_unlock(&Tx_mx);
342 if (isc_result != ISC_R_SUCCESS) {
343 t_info("isc_mutex_unlock failed %s\n",
344 isc_result_totext(isc_result));
345 ++Tx_nprobs;
348 isc_task_detach(&task);
349 isc_taskmgr_destroy(&tmgr);
350 isc_timermgr_destroy(&timermgr);
351 DESTROYLOCK(&Tx_mx);
352 (void) isc_condition_destroy(&Tx_cv);
353 isc_mem_destroy(&mctx);
357 #define T1_SECONDS 2
358 #define T1_NANOSECONDS 500000000
360 static const char *a1 =
361 "When type is isc_timertype_ticker, a call to isc_timer_create() "
362 "creates a timer that posts an ISC_TIMEREVENT_TICK event to the "
363 "specified task every 'interval' seconds and returns ISC_R_SUCCESS.";
365 static void
366 t1(void) {
367 int result;
368 isc_time_t expires;
369 isc_interval_t interval;
371 t_assert("isc_timer_create", 1, T_REQUIRED, "%s", a1);
373 if (threaded) {
374 Tx_nfails = 0;
375 Tx_nprobs = 0;
376 Tx_nevents = 12;
377 Tx_seconds = T1_SECONDS;
378 Tx_nanoseconds = T1_NANOSECONDS;
379 isc_interval_set(&interval, Tx_seconds, Tx_nanoseconds);
380 isc_time_settoepoch(&expires);
382 t_timers_x(isc_timertype_ticker, &expires, &interval, tx_te);
384 result = T_UNRESOLVED;
386 if ((Tx_nfails == 0) && (Tx_nprobs == 0))
387 result = T_PASS;
388 else if (Tx_nfails)
389 result = T_FAIL;
391 t_result(result);
392 } else
393 require_threads();
396 #define T2_SECONDS 5
397 #define T2_NANOSECONDS 300000000;
399 static const char *a2 =
400 "When type is isc_timertype_once, a call to isc_timer_create() "
401 "creates a timer that posts an ISC_TIMEEVENT_LIFE event to the "
402 "specified task when the current time reaches or exceeds the time "
403 "specified by 'expires'.";
405 static void
406 t2(void) {
407 int result;
408 int isc_result;
409 isc_time_t expires;
410 isc_interval_t interval;
412 t_assert("isc_timer_create", 2, T_REQUIRED, "%s", a2);
414 if (threaded) {
415 Tx_nfails = 0;
416 Tx_nprobs = 0;
417 Tx_nevents = 1;
418 Tx_seconds = T2_SECONDS;
419 Tx_nanoseconds = T2_NANOSECONDS;
420 isc_interval_set(&interval, Tx_seconds, Tx_nanoseconds);
422 isc_result = isc_time_nowplusinterval(&expires, &interval);
423 if (isc_result == ISC_R_SUCCESS) {
425 isc_interval_set(&interval, 0, 0);
426 t_timers_x(isc_timertype_once, &expires, &interval,
427 tx_te);
429 } else {
430 t_info("isc_time_nowplusinterval failed %s\n",
431 isc_result_totext(isc_result));
434 result = T_UNRESOLVED;
436 if ((Tx_nfails == 0) && (Tx_nprobs == 0))
437 result = T_PASS;
438 else if (Tx_nfails)
439 result = T_FAIL;
441 t_result(result);
442 } else
443 require_threads();
446 static void
447 t3_te(isc_task_t *task, isc_event_t *event) {
448 isc_result_t isc_result;
449 isc_time_t now;
450 isc_time_t base;
451 isc_time_t ulim;
452 isc_time_t llim;
453 isc_interval_t interval;
455 ++Tx_eventcnt;
457 t_info("tick %d\n", Tx_eventcnt);
459 isc_result = isc_time_now(&now);
460 if (isc_result != ISC_R_SUCCESS) {
461 t_info("isc_time_now failed %s\n",
462 isc_result_totext(isc_result));
463 ++Tx_nprobs;
466 if (isc_result == ISC_R_SUCCESS) {
467 isc_interval_set(&interval, Tx_seconds, Tx_nanoseconds);
468 isc_result = isc_time_add(&Tx_lasttime, &interval, &base);
469 if (isc_result != ISC_R_SUCCESS) {
470 t_info("isc_time_add failed %s\n",
471 isc_result_totext(isc_result));
472 ++Tx_nprobs;
476 if (isc_result == ISC_R_SUCCESS) {
477 isc_interval_set(&interval,
478 Tx_FUDGE_SECONDS, Tx_FUDGE_NANOSECONDS);
479 isc_result = isc_time_add(&base, &interval, &ulim);
480 if (isc_result != ISC_R_SUCCESS) {
481 t_info("isc_time_add failed %s\n",
482 isc_result_totext(isc_result));
483 ++Tx_nprobs;
487 if (isc_result == ISC_R_SUCCESS) {
488 isc_result = isc_time_subtract(&base, &interval, &llim);
489 if (isc_result != ISC_R_SUCCESS) {
490 t_info("isc_time_subtract failed %s\n",
491 isc_result_totext(isc_result));
492 ++Tx_nprobs;
496 if (isc_result == ISC_R_SUCCESS) {
497 if (isc_time_compare(&llim, &now) > 0) {
498 t_info("timer range error: early by "
499 "%lu microseconds\n",
500 (unsigned long)isc_time_microdiff(&base, &now));
501 ++Tx_nfails;
502 } else if (isc_time_compare(&ulim, &now) < 0) {
503 t_info("timer range error: late by "
504 "%lu microseconds\n",
505 (unsigned long)isc_time_microdiff(&now, &base));
506 ++Tx_nfails;
508 Tx_lasttime = now;
511 if (event->ev_type != ISC_TIMEREVENT_IDLE) {
512 t_info("received event type %d, expected type %d\n",
513 event->ev_type, ISC_TIMEREVENT_IDLE);
514 ++Tx_nfails;
517 isc_timer_detach(&Tx_timer);
518 isc_task_shutdown(task);
519 isc_event_free(&event);
522 #define T3_SECONDS 4
523 #define T3_NANOSECONDS 400000000
525 static const char *a3 =
526 "When type is isc_timertype_once, a call to isc_timer_create() "
527 "creates a timer that posts an ISC_TIMEEVENT_IDLE event to the "
528 "specified task when the timer has been idle for 'interval' seconds.";
530 static void
531 t3(void) {
532 int result;
533 int isc_result;
534 isc_time_t expires;
535 isc_interval_t interval;
537 t_assert("isc_timer_create", 3, T_REQUIRED, "%s", a3);
539 if (threaded) {
540 Tx_nfails = 0;
541 Tx_nprobs = 0;
542 Tx_nevents = 1;
543 Tx_seconds = T3_SECONDS;
544 Tx_nanoseconds = T3_NANOSECONDS;
546 isc_interval_set(&interval, Tx_seconds + 1, Tx_nanoseconds);
548 isc_result = isc_time_nowplusinterval(&expires, &interval);
549 if (isc_result == ISC_R_SUCCESS) {
550 isc_interval_set(&interval, Tx_seconds,
551 Tx_nanoseconds);
552 t_timers_x(isc_timertype_once, &expires, &interval,
553 t3_te);
554 } else {
555 t_info("isc_time_nowplusinterval failed %s\n",
556 isc_result_totext(isc_result));
557 ++Tx_nprobs;
560 result = T_UNRESOLVED;
562 if ((Tx_nfails == 0) && (Tx_nprobs == 0))
563 result = T_PASS;
564 else if (Tx_nfails)
565 result = T_FAIL;
567 t_result(result);
568 } else
569 require_threads();
572 #define T4_SECONDS 2
573 #define T4_NANOSECONDS 500000000
575 static void
576 t4_te(isc_task_t *task, isc_event_t *event) {
578 isc_result_t isc_result;
579 isc_time_t now;
580 isc_time_t base;
581 isc_time_t ulim;
582 isc_time_t llim;
583 isc_time_t expires;
584 isc_interval_t interval;
586 ++Tx_eventcnt;
588 t_info("tick %d\n", Tx_eventcnt);
591 * Check expired time.
594 isc_result = isc_time_now(&now);
595 if (isc_result != ISC_R_SUCCESS) {
596 t_info("isc_time_now failed %s\n",
597 isc_result_totext(isc_result));
598 ++Tx_nprobs;
601 if (isc_result == ISC_R_SUCCESS) {
602 isc_interval_set(&interval, Tx_seconds, Tx_nanoseconds);
603 isc_result = isc_time_add(&Tx_lasttime, &interval, &base);
604 if (isc_result != ISC_R_SUCCESS) {
605 t_info("isc_time_add failed %s\n",
606 isc_result_totext(isc_result));
607 ++Tx_nprobs;
611 if (isc_result == ISC_R_SUCCESS) {
612 isc_interval_set(&interval,
613 Tx_FUDGE_SECONDS, Tx_FUDGE_NANOSECONDS);
614 isc_result = isc_time_add(&base, &interval, &ulim);
615 if (isc_result != ISC_R_SUCCESS) {
616 t_info("isc_time_add failed %s\n",
617 isc_result_totext(isc_result));
618 ++Tx_nprobs;
622 if (isc_result == ISC_R_SUCCESS) {
623 isc_result = isc_time_subtract(&base, &interval, &llim);
624 if (isc_result != ISC_R_SUCCESS) {
625 t_info("isc_time_subtract failed %s\n",
626 isc_result_totext(isc_result));
627 ++Tx_nprobs;
631 if (isc_result == ISC_R_SUCCESS) {
632 if (isc_time_compare(&llim, &now) > 0) {
633 t_info("timer range error: early by "
634 "%lu microseconds\n",
635 (unsigned long)isc_time_microdiff(&base, &now));
636 ++Tx_nfails;
637 } else if (isc_time_compare(&ulim, &now) < 0) {
638 t_info("timer range error: late by "
639 "%lu microseconds\n",
640 (unsigned long)isc_time_microdiff(&now, &base));
641 ++Tx_nfails;
643 Tx_lasttime = now;
646 if (Tx_eventcnt < 3) {
647 if (event->ev_type != ISC_TIMEREVENT_TICK) {
648 t_info("received event type %d, expected type %d\n",
649 event->ev_type, ISC_TIMEREVENT_IDLE);
650 ++Tx_nfails;
652 if (Tx_eventcnt == 2) {
653 isc_interval_set(&interval, T4_SECONDS,
654 T4_NANOSECONDS);
655 isc_result = isc_time_nowplusinterval(&expires,
656 &interval);
657 if (isc_result == ISC_R_SUCCESS) {
658 isc_interval_set(&interval, 0, 0);
659 isc_result =
660 isc_timer_reset(Tx_timer,
661 isc_timertype_once,
662 &expires, &interval,
663 ISC_FALSE);
664 if (isc_result != ISC_R_SUCCESS) {
665 t_info("isc_timer_reset failed %s\n",
666 isc_result_totext(isc_result));
667 ++Tx_nfails;
669 } else {
670 t_info("isc_time_nowplusinterval failed %s\n",
671 isc_result_totext(isc_result));
672 ++Tx_nprobs;
675 } else {
676 if (event->ev_type != ISC_TIMEREVENT_LIFE) {
677 t_info("received event type %d, expected type %d\n",
678 event->ev_type, ISC_TIMEREVENT_IDLE);
679 ++Tx_nfails;
682 isc_timer_detach(&Tx_timer);
683 isc_task_shutdown(task);
686 isc_event_free(&event);
689 static const char *a4 =
690 "A call to isc_timer_reset() changes the timer's type, expires and "
691 "interval values to the given values.";
693 static void
694 t4(void) {
695 int result;
696 isc_time_t expires;
697 isc_interval_t interval;
699 t_assert("isc_timer_reset", 4, T_REQUIRED, "%s", a4);
701 if (threaded) {
702 Tx_nfails = 0;
703 Tx_nprobs = 0;
704 Tx_nevents = 3;
705 Tx_seconds = T4_SECONDS;
706 Tx_nanoseconds = T4_NANOSECONDS;
708 isc_interval_set(&interval, T4_SECONDS, T4_NANOSECONDS);
709 isc_time_settoepoch(&expires);
710 t_timers_x(isc_timertype_ticker, &expires, &interval, t4_te);
712 result = T_UNRESOLVED;
714 if ((Tx_nfails == 0) && (Tx_nprobs == 0))
715 result = T_PASS;
716 else if (Tx_nfails)
717 result = T_FAIL;
719 t_result(result);
720 } else
721 require_threads();
724 #define T5_NTICKS 4
725 #define T5_SECONDS 3
727 static int T5_startflag;
728 static int T5_shutdownflag;
729 static int T5_eventcnt;
730 static isc_mutex_t T5_mx;
731 static isc_condition_t T5_cv;
732 static int T5_nfails;
733 static int T5_nprobs;
734 static isc_timer_t *T5_tickertimer;
735 static isc_timer_t *T5_oncetimer;
736 static isc_task_t *T5_task1;
737 static isc_task_t *T5_task2;
740 * T5_task1 blocks on T5_mx while events accumulate
741 * in it's queue, until signaled by T5_task2.
744 static void
745 t5_start_event(isc_task_t *task, isc_event_t *event) {
746 isc_result_t isc_result;
748 UNUSED(task);
750 t_info("t5_start_event\n");
752 isc_result = isc_mutex_lock(&T5_mx);
753 if (isc_result != ISC_R_SUCCESS) {
754 t_info("isc_mutex_lock failed %s\n",
755 isc_result_totext(isc_result));
756 ++T5_nprobs;
759 while (! T5_startflag) {
760 (void) isc_condition_wait(&T5_cv, &T5_mx);
763 isc_result = isc_mutex_unlock(&T5_mx);
764 if (isc_result != ISC_R_SUCCESS) {
765 t_info("isc_mutex_unlock failed %s\n",
766 isc_result_totext(isc_result));
767 ++T5_nprobs;
769 isc_event_free(&event);
772 static void
773 t5_tick_event(isc_task_t *task, isc_event_t *event) {
774 isc_result_t isc_result;
775 isc_time_t expires;
776 isc_interval_t interval;
778 UNUSED(task);
780 ++T5_eventcnt;
781 t_info("t5_tick_event %d\n", T5_eventcnt);
784 * On the first tick, purge all remaining tick events
785 * and then shut down the task.
787 if (T5_eventcnt == 1) {
788 isc_time_settoepoch(&expires);
789 isc_interval_set(&interval, T5_SECONDS, 0);
790 isc_result = isc_timer_reset(T5_tickertimer,
791 isc_timertype_ticker, &expires,
792 &interval, ISC_TRUE);
793 if (isc_result != ISC_R_SUCCESS) {
794 t_info("isc_timer_reset failed %s\n",
795 isc_result_totext(isc_result));
796 ++T5_nfails;
798 isc_task_shutdown(task);
800 isc_event_free(&event);
803 static void
804 t5_once_event(isc_task_t *task, isc_event_t *event) {
806 isc_result_t isc_result;
808 t_info("t5_once_event\n");
811 * Allow task1 to start processing events.
813 isc_result = isc_mutex_lock(&T5_mx);
814 if (isc_result != ISC_R_SUCCESS) {
815 t_info("isc_mutex_lock failed %s\n",
816 isc_result_totext(isc_result));
817 ++T5_nprobs;
820 T5_startflag = 1;
822 isc_result = isc_condition_broadcast(&T5_cv);
823 if (isc_result != ISC_R_SUCCESS) {
824 t_info("isc_condition_broadcast failed %s\n",
825 isc_result_totext(isc_result));
826 ++T5_nprobs;
829 isc_result = isc_mutex_unlock(&T5_mx);
830 if (isc_result != ISC_R_SUCCESS) {
831 t_info("isc_mutex_unlock failed %s\n",
832 isc_result_totext(isc_result));
833 ++T5_nprobs;
836 isc_event_free(&event);
837 isc_task_shutdown(task);
840 static void
841 t5_shutdown_event(isc_task_t *task, isc_event_t *event) {
843 isc_result_t isc_result;
845 UNUSED(task);
846 UNUSED(event);
848 t_info("t5_shutdown_event\n");
851 * Signal shutdown processing complete.
853 isc_result = isc_mutex_lock(&T5_mx);
854 if (isc_result != ISC_R_SUCCESS) {
855 t_info("isc_mutex_lock failed %s\n",
856 isc_result_totext(isc_result));
857 ++T5_nprobs;
860 T5_shutdownflag = 1;
862 isc_result = isc_condition_signal(&T5_cv);
863 if (isc_result != ISC_R_SUCCESS) {
864 t_info("isc_condition_signal failed %s\n",
865 isc_result_totext(isc_result));
866 ++T5_nprobs;
869 isc_result = isc_mutex_unlock(&T5_mx);
870 if (isc_result != ISC_R_SUCCESS) {
871 t_info("isc_mutex_unlock failed %s\n",
872 isc_result_totext(isc_result));
873 ++T5_nprobs;
875 isc_event_free(&event);
878 static int
879 t_timers5(void) {
880 char *p;
881 int result;
882 isc_mem_t *mctx;
883 isc_taskmgr_t *tmgr;
884 unsigned int workers;
885 isc_result_t isc_result;
886 isc_timermgr_t *timermgr;
887 isc_event_t *event;
888 isc_time_t expires;
889 isc_interval_t interval;
891 T5_startflag = 0;
892 T5_shutdownflag = 0;
893 T5_eventcnt = 0;
895 workers = 2;
896 p = t_getenv("ISC_TASK_WORKERS");
897 if (p != NULL)
898 workers = atoi(p);
900 mctx = NULL;
901 isc_result = isc_mem_create(0, 0, &mctx);
902 if (isc_result != ISC_R_SUCCESS) {
903 t_info("isc_mem_create failed %s\n",
904 isc_result_totext(isc_result));
905 return(T_UNRESOLVED);
908 isc_result = isc_mutex_init(&T5_mx);
909 if (isc_result != ISC_R_SUCCESS) {
910 t_info("isc_mutex_init failed %s\n",
911 isc_result_totext(isc_result));
912 isc_mem_destroy(&mctx);
913 return(T_UNRESOLVED);
916 isc_result = isc_condition_init(&T5_cv);
917 if (isc_result != ISC_R_SUCCESS) {
918 t_info("isc_condition_init failed %s\n",
919 isc_result_totext(isc_result));
920 DESTROYLOCK(&T5_mx);
921 isc_mem_destroy(&mctx);
922 return(T_UNRESOLVED);
925 tmgr = NULL;
926 isc_result = isc_taskmgr_create(mctx, workers, 0, &tmgr);
927 if (isc_result != ISC_R_SUCCESS) {
928 t_info("isc_taskmgr_create failed %s\n",
929 isc_result_totext(isc_result));
930 DESTROYLOCK(&T5_mx);
931 (void) isc_condition_destroy(&T5_cv);
932 isc_mem_destroy(&mctx);
933 return(T_UNRESOLVED);
936 timermgr = NULL;
937 isc_result = isc_timermgr_create(mctx, &timermgr);
938 if (isc_result != ISC_R_SUCCESS) {
939 t_info("isc_timermgr_create failed %s\n",
940 isc_result_totext(isc_result));
941 isc_taskmgr_destroy(&tmgr);
942 DESTROYLOCK(&T5_mx);
943 (void) isc_condition_destroy(&T5_cv);
944 isc_mem_destroy(&mctx);
945 return(T_UNRESOLVED);
948 T5_task1 = NULL;
949 isc_result = isc_task_create(tmgr, 0, &T5_task1);
950 if (isc_result != ISC_R_SUCCESS) {
951 t_info("isc_task_create failed %s\n",
952 isc_result_totext(isc_result));
953 isc_timermgr_destroy(&timermgr);
954 isc_taskmgr_destroy(&tmgr);
955 DESTROYLOCK(&T5_mx);
956 (void) isc_condition_destroy(&T5_cv);
957 isc_mem_destroy(&mctx);
958 return(T_UNRESOLVED);
961 isc_result = isc_task_onshutdown(T5_task1, t5_shutdown_event, NULL);
962 if (isc_result != ISC_R_SUCCESS) {
963 t_info("isc_task_onshutdown failed %s\n",
964 isc_result_totext(isc_result));
965 isc_timermgr_destroy(&timermgr);
966 isc_task_destroy(&T5_task1);
967 isc_taskmgr_destroy(&tmgr);
968 DESTROYLOCK(&T5_mx);
969 (void) isc_condition_destroy(&T5_cv);
970 isc_mem_destroy(&mctx);
971 return(T_UNRESOLVED);
974 T5_task2 = NULL;
975 isc_result = isc_task_create(tmgr, 0, &T5_task2);
976 if (isc_result != ISC_R_SUCCESS) {
977 t_info("isc_task_create failed %s\n",
978 isc_result_totext(isc_result));
979 isc_timermgr_destroy(&timermgr);
980 isc_task_destroy(&T5_task1);
981 isc_taskmgr_destroy(&tmgr);
982 DESTROYLOCK(&T5_mx);
983 (void) isc_condition_destroy(&T5_cv);
984 isc_mem_destroy(&mctx);
985 return(T_UNRESOLVED);
988 isc_result = isc_mutex_lock(&T5_mx);
989 if (isc_result != ISC_R_SUCCESS) {
990 t_info("isc_mutex_lock failed %s\n",
991 isc_result_totext(isc_result));
992 isc_timermgr_destroy(&timermgr);
993 isc_taskmgr_destroy(&tmgr);
994 DESTROYLOCK(&T5_mx);
995 (void) isc_condition_destroy(&T5_cv);
996 isc_mem_destroy(&mctx);
997 return(T_UNRESOLVED);
1000 event = isc_event_allocate(mctx, (void *)1 , (isc_eventtype_t)1,
1001 t5_start_event, NULL, sizeof(*event));
1002 isc_task_send(T5_task1, &event);
1004 isc_time_settoepoch(&expires);
1005 isc_interval_set(&interval, T5_SECONDS, 0);
1007 T5_tickertimer = NULL;
1008 isc_result = isc_timer_create(timermgr, isc_timertype_ticker,
1009 &expires, &interval, T5_task1,
1010 t5_tick_event, NULL, &T5_tickertimer);
1012 if (isc_result != ISC_R_SUCCESS) {
1013 isc_timermgr_destroy(&timermgr);
1014 (void) isc_condition_signal(&T5_cv);
1015 (void) isc_mutex_unlock(&T5_mx);
1016 isc_task_destroy(&T5_task1);
1017 isc_task_destroy(&T5_task2);
1018 isc_taskmgr_destroy(&tmgr);
1019 DESTROYLOCK(&T5_mx);
1020 (void) isc_condition_destroy(&T5_cv);
1021 isc_mem_destroy(&mctx);
1022 return(T_UNRESOLVED);
1025 T5_oncetimer = NULL;
1026 isc_interval_set(&interval, (T5_SECONDS * T5_NTICKS) + 2, 0);
1027 isc_result = isc_time_nowplusinterval(&expires, &interval);
1028 if (isc_result != ISC_R_SUCCESS) {
1029 isc_timer_detach(&T5_tickertimer);
1030 isc_timermgr_destroy(&timermgr);
1031 (void)isc_condition_signal(&T5_cv);
1032 (void)isc_mutex_unlock(&T5_mx);
1033 isc_task_destroy(&T5_task1);
1034 isc_task_destroy(&T5_task2);
1035 isc_taskmgr_destroy(&tmgr);
1036 DESTROYLOCK(&T5_mx);
1037 (void) isc_condition_destroy(&T5_cv);
1038 isc_mem_destroy(&mctx);
1039 return(T_UNRESOLVED);
1042 isc_interval_set(&interval, 0, 0);
1043 isc_result = isc_timer_create(timermgr, isc_timertype_once,
1044 &expires, &interval, T5_task2,
1045 t5_once_event, NULL, &T5_oncetimer);
1047 if (isc_result != ISC_R_SUCCESS) {
1048 isc_timer_detach(&T5_tickertimer);
1049 isc_timermgr_destroy(&timermgr);
1050 (void) isc_condition_signal(&T5_cv);
1051 (void) isc_mutex_unlock(&T5_mx);
1052 isc_task_destroy(&T5_task1);
1053 isc_task_destroy(&T5_task2);
1054 isc_taskmgr_destroy(&tmgr);
1055 DESTROYLOCK(&T5_mx);
1056 (void) isc_condition_destroy(&T5_cv);
1057 isc_mem_destroy(&mctx);
1058 ++T5_nprobs;
1059 return(T_UNRESOLVED);
1063 * Wait for shutdown processing to complete.
1065 while (! T5_shutdownflag) {
1066 isc_result = isc_condition_wait(&T5_cv, &T5_mx);
1067 if (isc_result != ISC_R_SUCCESS) {
1068 t_info("isc_condition_waituntil failed %s\n",
1069 isc_result_totext(isc_result));
1070 ++T5_nprobs;
1074 isc_result = isc_mutex_unlock(&T5_mx);
1075 if (isc_result != ISC_R_SUCCESS) {
1076 t_info("isc_mutex_unlock failed %s\n",
1077 isc_result_totext(isc_result));
1078 ++T5_nprobs;
1081 if (T5_eventcnt != 1) {
1082 t_info("processed %d events\n", T5_eventcnt);
1083 ++T5_nfails;
1086 isc_timer_detach(&T5_tickertimer);
1087 isc_timer_detach(&T5_oncetimer);
1088 isc_timermgr_destroy(&timermgr);
1089 isc_task_destroy(&T5_task1);
1090 isc_task_destroy(&T5_task2);
1091 isc_taskmgr_destroy(&tmgr);
1092 DESTROYLOCK(&T5_mx);
1093 (void) isc_condition_destroy(&T5_cv);
1094 isc_mem_destroy(&mctx);
1096 result = T_UNRESOLVED;
1098 if ((T5_nfails == 0) && (T5_nprobs == 0))
1099 result = T_PASS;
1100 else if (T5_nfails)
1101 result = T_FAIL;
1103 return (result);
1106 static const char *a5 =
1107 "When 'purge' is TRUE, a call to isc_timer_reset() purges any pending "
1108 "events from 'timer' from the task's event queue.";
1110 static void
1111 t5(void) {
1112 t_assert("isc_timer_reset", 5, T_REQUIRED, "%s", a5);
1114 if (threaded)
1115 t_result(t_timers5());
1116 else
1117 require_threads();
1120 testspec_t T_testlist[] = {
1121 { (PFV) t1, "timer_create" },
1122 { (PFV) t2, "timer_create" },
1123 { (PFV) t3, "timer_create" },
1124 { (PFV) t4, "timer_reset" },
1125 { (PFV) t5, "timer_reset" },
1126 { (PFV) NULL, NULL }
1129 #ifdef WIN32
1131 main(int argc, char **argv) {
1132 t_settests(T_testlist);
1133 return (t_main(argc, argv));
1135 #endif