1 /* $NetBSD: t_timers.c,v 1.6 2014/12/10 04:37:54 christos Exp $ */
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 */
26 #include <isc/condition.h>
28 #include <isc/platform.h>
31 #include <isc/timer.h>
34 #include <tests/t_api.h>
36 #ifdef ISC_PLATFORM_USETHREADS
37 isc_boolean_t threaded
= ISC_TRUE
;
39 isc_boolean_t threaded
= ISC_FALSE
;
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
;
53 static isc_timer_t
*Tx_timer
;
54 static int Tx_seconds
;
55 static int Tx_nanoseconds
;
58 require_threads(void) {
59 t_info("This test requires threads\n");
60 t_result(T_THREADONLY
);
65 tx_sde(isc_task_t
*task
, isc_event_t
*event
) {
66 isc_result_t isc_result
;
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
));
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
));
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
));
95 isc_event_free(&event
);
99 tx_te(isc_task_t
*task
, isc_event_t
*event
) {
100 isc_result_t isc_result
;
105 isc_interval_t interval
;
106 isc_eventtype_t expected_event_type
;
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
);
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
));
132 t_info("isc_time_now failed %s\n",
133 isc_result_totext(isc_result
));
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
));
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
));
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
));
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
));
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
));
179 isc_timer_detach(&Tx_timer
);
180 isc_task_shutdown(task
);
183 isc_event_free(&event
);
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
*))
195 unsigned int workers
;
196 isc_result_t isc_result
;
197 isc_timermgr_t
*timermgr
;
200 isc_time_settoepoch(&Tx_endtime
);
203 p
= t_getenv("ISC_TASK_WORKERS");
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
));
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
);
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
));
230 isc_mem_destroy(&mctx
);
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
));
241 (void) isc_condition_destroy(&Tx_cv
);
242 isc_mem_destroy(&mctx
);
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
);
254 (void) isc_condition_destroy(&Tx_cv
);
255 isc_mem_destroy(&mctx
);
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
);
267 (void) isc_condition_destroy(&Tx_cv
);
268 isc_mem_destroy(&mctx
);
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
);
281 (void) isc_condition_destroy(&Tx_cv
);
282 isc_mem_destroy(&mctx
);
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
);
295 (void) isc_condition_destroy(&Tx_cv
);
296 isc_mem_destroy(&mctx
);
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
);
307 (void) isc_condition_destroy(&Tx_cv
);
308 isc_mem_destroy(&mctx
);
314 isc_result
= isc_timer_create(timermgr
, timertype
, expires
, interval
,
315 task
, action
, (void *)timertype
,
318 if (isc_result
!= ISC_R_SUCCESS
) {
319 isc_timermgr_destroy(&timermgr
);
320 isc_task_destroy(&task
);
321 isc_taskmgr_destroy(&tmgr
);
323 (void) isc_condition_destroy(&Tx_cv
);
324 isc_mem_destroy(&mctx
);
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
));
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
));
348 isc_task_detach(&task
);
349 isc_taskmgr_destroy(&tmgr
);
350 isc_timermgr_destroy(&timermgr
);
352 (void) isc_condition_destroy(&Tx_cv
);
353 isc_mem_destroy(&mctx
);
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.";
369 isc_interval_t interval
;
371 t_assert("isc_timer_create", 1, T_REQUIRED
, "%s", a1
);
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))
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'.";
410 isc_interval_t interval
;
412 t_assert("isc_timer_create", 2, T_REQUIRED
, "%s", a2
);
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
,
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))
447 t3_te(isc_task_t
*task
, isc_event_t
*event
) {
448 isc_result_t isc_result
;
453 isc_interval_t interval
;
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
));
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
));
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
));
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
));
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
));
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
));
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
);
517 isc_timer_detach(&Tx_timer
);
518 isc_task_shutdown(task
);
519 isc_event_free(&event
);
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.";
535 isc_interval_t interval
;
537 t_assert("isc_timer_create", 3, T_REQUIRED
, "%s", a3
);
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
,
552 t_timers_x(isc_timertype_once
, &expires
, &interval
,
555 t_info("isc_time_nowplusinterval failed %s\n",
556 isc_result_totext(isc_result
));
560 result
= T_UNRESOLVED
;
562 if ((Tx_nfails
== 0) && (Tx_nprobs
== 0))
573 #define T4_NANOSECONDS 500000000
576 t4_te(isc_task_t
*task
, isc_event_t
*event
) {
578 isc_result_t isc_result
;
584 isc_interval_t interval
;
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
));
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
));
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
));
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
));
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
));
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
));
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
);
652 if (Tx_eventcnt
== 2) {
653 isc_interval_set(&interval
, T4_SECONDS
,
655 isc_result
= isc_time_nowplusinterval(&expires
,
657 if (isc_result
== ISC_R_SUCCESS
) {
658 isc_interval_set(&interval
, 0, 0);
660 isc_timer_reset(Tx_timer
,
664 if (isc_result
!= ISC_R_SUCCESS
) {
665 t_info("isc_timer_reset failed %s\n",
666 isc_result_totext(isc_result
));
670 t_info("isc_time_nowplusinterval failed %s\n",
671 isc_result_totext(isc_result
));
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
);
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.";
697 isc_interval_t interval
;
699 t_assert("isc_timer_reset", 4, T_REQUIRED
, "%s", a4
);
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))
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.
745 t5_start_event(isc_task_t
*task
, isc_event_t
*event
) {
746 isc_result_t isc_result
;
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
));
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
));
769 isc_event_free(&event
);
773 t5_tick_event(isc_task_t
*task
, isc_event_t
*event
) {
774 isc_result_t isc_result
;
776 isc_interval_t interval
;
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
));
798 isc_task_shutdown(task
);
800 isc_event_free(&event
);
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
));
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
));
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
));
836 isc_event_free(&event
);
837 isc_task_shutdown(task
);
841 t5_shutdown_event(isc_task_t
*task
, isc_event_t
*event
) {
843 isc_result_t isc_result
;
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
));
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
));
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
));
875 isc_event_free(&event
);
884 unsigned int workers
;
885 isc_result_t isc_result
;
886 isc_timermgr_t
*timermgr
;
889 isc_interval_t interval
;
896 p
= t_getenv("ISC_TASK_WORKERS");
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
));
921 isc_mem_destroy(&mctx
);
922 return(T_UNRESOLVED
);
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
));
931 (void) isc_condition_destroy(&T5_cv
);
932 isc_mem_destroy(&mctx
);
933 return(T_UNRESOLVED
);
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
);
943 (void) isc_condition_destroy(&T5_cv
);
944 isc_mem_destroy(&mctx
);
945 return(T_UNRESOLVED
);
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
);
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
);
969 (void) isc_condition_destroy(&T5_cv
);
970 isc_mem_destroy(&mctx
);
971 return(T_UNRESOLVED
);
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
);
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
);
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
);
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
));
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
));
1081 if (T5_eventcnt
!= 1) {
1082 t_info("processed %d events\n", T5_eventcnt
);
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))
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.";
1112 t_assert("isc_timer_reset", 5, T_REQUIRED
, "%s", a5
);
1115 t_result(t_timers5());
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
}
1131 main(int argc
, char **argv
) {
1132 t_settests(T_testlist
);
1133 return (t_main(argc
, argv
));