4 * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1998-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_tasks.c,v 1.42 2009/01/22 23:47:54 tbox Exp */
26 #ifdef HAVE_INTTYPES_H
27 #include <inttypes.h> /* uintptr_t */
29 #include <isc/condition.h>
31 #include <isc/platform.h>
34 #include <isc/timer.h>
37 #include <tests/t_api.h>
40 #ifdef ISC_PLATFORM_USETHREADS
41 isc_boolean_t threaded
= ISC_TRUE
;
43 isc_boolean_t threaded
= ISC_FALSE
;
46 static int senders
[4];
49 require_threads(void) {
50 t_info("This test requires threads\n");
51 t_result(T_THREADONLY
);
56 t1_callback(isc_task_t
*task
, isc_event_t
*event
) {
64 for (i
= 0; i
< 1000000; i
++)
67 t_info("task %s\n", (char *)event
->ev_arg
);
68 isc_event_free(&event
);
72 t1_shutdown(isc_task_t
*task
, isc_event_t
*event
) {
75 t_info("shutdown %s\n", (char *)event
->ev_arg
);
76 isc_event_free(&event
);
80 my_tick(isc_task_t
*task
, isc_event_t
*event
) {
83 t_info("%s\n", (char *)event
->ev_arg
);
84 isc_event_free(&event
);
88 * Adapted from RTH's original task_test program
95 isc_taskmgr_t
*manager
;
101 unsigned int workers
;
102 isc_timermgr_t
*timgr
;
105 isc_result_t isc_result
;
106 struct isc_time absolute
;
107 struct isc_interval interval
;
117 p
= t_getenv("ISC_TASK_WORKERS");
121 t_info("Bad config value for ISC_TASK_WORKERS, %d\n", workers
);
122 return(T_UNRESOLVED
);
125 isc_result
= isc_mem_create(0, 0, &mctx
);
126 if (isc_result
!= ISC_R_SUCCESS
) {
127 t_info("isc_mem_create failed %d\n", isc_result
);
128 return(T_UNRESOLVED
);
131 isc_result
= isc_taskmgr_create(mctx
, workers
, 0, &manager
);
132 if (isc_result
!= ISC_R_SUCCESS
) {
133 t_info("isc_taskmgr_create failed %d\n", isc_result
);
137 isc_result
= isc_task_create(manager
, 0, &task1
);
138 if (isc_result
!= ISC_R_SUCCESS
) {
139 t_info("isc_task_create failed %d\n", isc_result
);
143 isc_result
= isc_task_create(manager
, 0, &task2
);
144 if (isc_result
!= ISC_R_SUCCESS
) {
145 t_info("isc_task_create failed %d\n", isc_result
);
149 isc_result
= isc_task_create(manager
, 0, &task3
);
150 if (isc_result
!= ISC_R_SUCCESS
) {
151 t_info("isc_task_create failed %d\n", isc_result
);
155 isc_result
= isc_task_create(manager
, 0, &task4
);
156 if (isc_result
!= ISC_R_SUCCESS
) {
157 t_info("isc_task_create failed %d\n", isc_result
);
161 isc_result
= isc_task_onshutdown(task1
, t1_shutdown
, "1");
162 if (isc_result
!= ISC_R_SUCCESS
) {
163 t_info("isc_task_onshutdown failed %d\n", isc_result
);
167 isc_result
= isc_task_onshutdown(task2
, t1_shutdown
, "2");
168 if (isc_result
!= ISC_R_SUCCESS
) {
169 t_info("isc_task_onshutdown failed %d\n", isc_result
);
173 isc_result
= isc_task_onshutdown(task3
, t1_shutdown
, "3");
174 if (isc_result
!= ISC_R_SUCCESS
) {
175 t_info("isc_task_onshutdown failed %d\n", isc_result
);
179 isc_result
= isc_task_onshutdown(task4
, t1_shutdown
, "4");
180 if (isc_result
!= ISC_R_SUCCESS
) {
181 t_info("isc_task_onshutdown failed %d\n", isc_result
);
186 isc_result
= isc_timermgr_create(mctx
, &timgr
);
187 if (isc_result
!= ISC_R_SUCCESS
) {
188 t_info("isc_timermgr_create %d\n", isc_result
);
189 return(T_UNRESOLVED
);
193 isc_time_settoepoch(&absolute
);
194 isc_interval_set(&interval
, 1, 0);
195 isc_result
= isc_timer_create(timgr
, isc_timertype_ticker
,
196 &absolute
, &interval
,
197 task1
, my_tick
, "tick", &ti1
);
198 if (isc_result
!= ISC_R_SUCCESS
) {
199 t_info("isc_timer_create %d\n", isc_result
);
200 return(T_UNRESOLVED
);
204 isc_time_settoepoch(&absolute
);
205 isc_interval_set(&interval
, 1, 0);
206 isc_result
= isc_timer_create(timgr
, isc_timertype_ticker
,
207 &absolute
, &interval
,
208 task2
, my_tick
, "tock", &ti2
);
209 if (isc_result
!= ISC_R_SUCCESS
) {
210 t_info("isc_timer_create %d\n", isc_result
);
211 return(T_UNRESOLVED
);
218 * Note: (void *)1 is used as a sender here, since some compilers
219 * don't like casting a function pointer to a (void *).
221 * In a real use, it is more likely the sender would be a
222 * structure (socket, timer, task, etc) but this is just a test
225 event
= isc_event_allocate(mctx
, (void *)1, 1, t1_callback
, "1",
228 t_info("isc_event_allocate failed\n");
229 return(T_UNRESOLVED
);
232 isc_task_send(task1
, &event
);
234 event
= isc_event_allocate(mctx
, (void *)1, 1, t1_callback
, "1",
237 t_info("isc_event_allocate failed\n");
238 return(T_UNRESOLVED
);
241 isc_task_send(task1
, &event
);
243 event
= isc_event_allocate(mctx
, (void *)1, 1, t1_callback
, "1",
246 t_info("isc_event_allocate failed\n");
247 return(T_UNRESOLVED
);
250 isc_task_send(task1
, &event
);
252 event
= isc_event_allocate(mctx
, (void *)1, 1, t1_callback
, "1",
255 t_info("isc_event_allocate failed\n");
256 return(T_UNRESOLVED
);
259 isc_task_send(task1
, &event
);
261 event
= isc_event_allocate(mctx
, (void *)1, 1, t1_callback
, "1",
264 t_info("isc_event_allocate failed\n");
265 return(T_UNRESOLVED
);
268 isc_task_send(task1
, &event
);
270 event
= isc_event_allocate(mctx
, (void *)1, 1, t1_callback
, "1",
273 t_info("isc_event_allocate failed\n");
274 return(T_UNRESOLVED
);
277 isc_task_send(task1
, &event
);
279 event
= isc_event_allocate(mctx
, (void *)1, 1, t1_callback
, "1",
282 t_info("isc_event_allocate failed\n");
283 return(T_UNRESOLVED
);
286 isc_task_send(task1
, &event
);
288 event
= isc_event_allocate(mctx
, (void *)1, 1, t1_callback
, "1",
291 t_info("isc_event_allocate failed\n");
292 return(T_UNRESOLVED
);
295 isc_task_send(task1
, &event
);
297 event
= isc_event_allocate(mctx
, (void *)1, 1, t1_callback
, "1",
300 t_info("isc_event_allocate failed\n");
301 return(T_UNRESOLVED
);
304 isc_task_send(task1
, &event
);
306 event
= isc_event_allocate(mctx
, (void *)1, 1, t1_callback
, "2",
309 t_info("isc_event_allocate failed\n");
310 return(T_UNRESOLVED
);
313 isc_task_send(task2
, &event
);
315 event
= isc_event_allocate(mctx
, (void *)1, 1, t1_callback
, "3",
318 t_info("isc_event_allocate failed\n");
319 return(T_UNRESOLVED
);
322 isc_task_send(task3
, &event
);
324 event
= isc_event_allocate(mctx
, (void *)1, 1, t1_callback
, "4",
327 t_info("isc_event_allocate failed\n");
328 return(T_UNRESOLVED
);
331 isc_task_send(task4
, &event
);
333 event
= isc_event_allocate(mctx
, (void *)1, 1, t1_callback
, "2",
336 t_info("isc_event_allocate failed\n");
337 return(T_UNRESOLVED
);
340 isc_task_send(task2
, &event
);
342 event
= isc_event_allocate(mctx
, (void *)1, 1, t1_callback
, "3",
345 t_info("isc_event_allocate failed\n");
346 return(T_UNRESOLVED
);
349 isc_task_send(task3
, &event
);
351 event
= isc_event_allocate(mctx
, (void *)1, 1, t1_callback
, "4",
354 t_info("isc_event_allocate failed\n");
355 return(T_UNRESOLVED
);
358 isc_task_send(task4
, &event
);
360 (void)isc_task_purge(task3
, NULL
, 0, 0);
362 isc_task_detach(&task1
);
363 isc_task_detach(&task2
);
364 isc_task_detach(&task3
);
365 isc_task_detach(&task4
);
368 isc_timer_detach(&ti1
);
369 isc_timer_detach(&ti2
);
370 isc_timermgr_destroy(&timgr
);
371 isc_taskmgr_destroy(&manager
);
373 isc_mem_destroy(&mctx
);
377 static const char *a1
= "The task subsystem can create and manage tasks";
383 t_assert("tasks", 1, T_REQUIRED
, "%s", a1
);
388 #define T2_NTASKS 10000
390 static isc_event_t
*T2_event
;
391 static isc_taskmgr_t
*T2_manager
;
392 static isc_mem_t
*T2_mctx
;
393 static isc_condition_t T2_cv
;
394 static isc_mutex_t T2_mx
;
396 static int T2_nprobs
;
397 static int T2_nfails
;
398 static int T2_ntasks
;
401 t2_shutdown(isc_task_t
*task
, isc_event_t
*event
) {
403 isc_result_t isc_result
;
405 task
= task
; /* notused */
407 if (event
->ev_arg
!= NULL
) {
408 isc_task_destroy((isc_task_t
**) &event
->ev_arg
);
411 isc_result
= isc_mutex_lock(&T2_mx
);
412 if (isc_result
!= ISC_R_SUCCESS
) {
413 t_info("isc_mutex_lock failed %d\n", isc_result
);
419 isc_result
= isc_condition_signal(&T2_cv
);
420 if (isc_result
!= ISC_R_SUCCESS
) {
421 t_info("isc_condition_signal failed %d\n", isc_result
);
425 isc_result
= isc_mutex_unlock(&T2_mx
);
426 if (isc_result
!= ISC_R_SUCCESS
) {
427 t_info("isc_mutex_unlock failed %d\n", isc_result
);
431 isc_event_free(&T2_event
);
432 isc_taskmgr_destroy(&T2_manager
);
433 isc_mem_destroy(&T2_mctx
);
438 t2_callback(isc_task_t
*task
, isc_event_t
*event
) {
439 isc_result_t isc_result
;
444 if (T_debug
&& ((T2_ntasks
% 100) == 0)) {
445 t_info("T2_ntasks %d\n", T2_ntasks
);
450 event
->ev_arg
= (void *)(((uintptr_t) event
->ev_arg
) - 1);
453 * Create a new task and forward the message.
456 isc_result
= isc_task_create(T2_manager
, 0, &newtask
);
457 if (isc_result
!= ISC_R_SUCCESS
) {
458 t_info("isc_task_create failed %d\n", isc_result
);
463 isc_result
= isc_task_onshutdown(newtask
, t2_shutdown
,
465 if (isc_result
!= ISC_R_SUCCESS
) {
466 t_info("isc_task_onshutdown failed %d\n",
472 isc_task_send(newtask
, &event
);
475 * Time to unwind, shutdown should perc back up.
477 isc_task_destroy(&task
);
487 unsigned int workers
;
488 isc_result_t isc_result
;
497 p
= t_getenv("ISC_TASK_WORKERS");
501 t_info("Bad config value for ISC_TASK_WORKERS, %d\n", workers
);
502 return(T_UNRESOLVED
);
505 p
= t_getenv("ISC_TASKS_MIN");
511 t_info("Bad config value for ISC_TASKS_MIN, %lu\n",
512 (unsigned long)ntasks
);
513 return(T_UNRESOLVED
);
516 t_info("Testing with %lu tasks\n", (unsigned long)ntasks
);
518 isc_result
= isc_mutex_init(&T2_mx
);
519 if (isc_result
!= ISC_R_SUCCESS
) {
520 t_info("isc_mutex_init failed %d\n", isc_result
);
521 return(T_UNRESOLVED
);
524 isc_result
= isc_condition_init(&T2_cv
);
525 if (isc_result
!= ISC_R_SUCCESS
) {
526 t_info("isc_condition_init failed %d\n", isc_result
);
527 return(T_UNRESOLVED
);
530 isc_result
= isc_mem_create(0, 0, &T2_mctx
);
531 if (isc_result
!= ISC_R_SUCCESS
) {
532 t_info("isc_mem_create failed %d\n", isc_result
);
533 return(T_UNRESOLVED
);
536 isc_result
= isc_taskmgr_create(T2_mctx
, workers
, 0, &T2_manager
);
537 if (isc_result
!= ISC_R_SUCCESS
) {
538 t_info("isc_taskmgr_create failed %d\n", isc_result
);
542 T2_event
= isc_event_allocate(T2_mctx
, (void *)1, 1, t2_callback
,
543 (void *)ntasks
, sizeof(*event
));
544 if (T2_event
== NULL
) {
545 t_info("isc_event_allocate failed\n");
546 return(T_UNRESOLVED
);
549 isc_result
= isc_mutex_lock(&T2_mx
);
550 if (isc_result
!= ISC_R_SUCCESS
) {
551 t_info("isc_mutex_lock failed %d\n", isc_result
);
552 return(T_UNRESOLVED
);
555 t2_callback(NULL
, T2_event
);
557 while (T2_done
== 0) {
558 isc_result
= isc_condition_wait(&T2_cv
, &T2_mx
);
559 if (isc_result
!= ISC_R_SUCCESS
) {
560 t_info("isc_condition_wait failed %d\n", isc_result
);
561 return(T_UNRESOLVED
);
565 result
= T_UNRESOLVED
;
567 if ((T2_nfails
== 0) && (T2_nprobs
== 0))
569 else if (T2_nfails
!= 0)
575 static const char *a2
= "The task subsystem can create ISC_TASKS_MIN tasks";
579 t_assert("tasks", 2, T_REQUIRED
, "%s", a2
);
582 t_result(t_tasks2());
587 #define T3_NEVENTS 256
590 static int T3_nevents
;
591 static int T3_nsdevents
;
592 static isc_mutex_t T3_mx
;
593 static isc_condition_t T3_cv
;
594 static int T3_nfails
;
595 static int T3_nprobs
;
598 t3_sde1(isc_task_t
*task
, isc_event_t
*event
) {
601 if (T3_nevents
!= T3_NEVENTS
) {
602 t_info("Some events were not processed\n");
605 if (T3_nsdevents
== 1) {
608 t_info("Shutdown events not processed in LIFO order\n");
611 isc_event_free(&event
);
615 t3_sde2(isc_task_t
*task
, isc_event_t
*event
) {
619 if (T3_nevents
!= T3_NEVENTS
) {
620 t_info("Some events were not processed\n");
623 if (T3_nsdevents
== 0) {
626 t_info("Shutdown events not processed in LIFO order\n");
629 isc_event_free(&event
);
633 t3_event1(isc_task_t
*task
, isc_event_t
*event
) {
634 isc_result_t isc_result
;
638 isc_result
= isc_mutex_lock(&T3_mx
);
639 if (isc_result
!= ISC_R_SUCCESS
) {
640 t_info("isc_mutex_lock failed %s\n",
641 isc_result_totext(isc_result
));
644 while (T3_flag
!= 1) {
645 (void) isc_condition_wait(&T3_cv
, &T3_mx
);
648 isc_result
= isc_mutex_unlock(&T3_mx
);
649 if (isc_result
!= ISC_R_SUCCESS
) {
650 t_info("isc_mutex_unlock failed %s\n",
651 isc_result_totext(isc_result
));
654 isc_event_free(&event
);
658 t3_event2(isc_task_t
*task
, isc_event_t
*event
) {
662 isc_event_free(&event
);
673 unsigned int workers
;
675 isc_result_t isc_result
;
676 isc_eventtype_t event_type
;
687 p
= t_getenv("ISC_TASK_WORKERS");
692 isc_result
= isc_mem_create(0, 0, &mctx
);
693 if (isc_result
!= ISC_R_SUCCESS
) {
694 t_info("isc_mem_create failed %s\n",
695 isc_result_totext(isc_result
));
696 return(T_UNRESOLVED
);
699 isc_result
= isc_mutex_init(&T3_mx
);
700 if (isc_result
!= ISC_R_SUCCESS
) {
701 t_info("isc_mutex_init failed %s\n",
702 isc_result_totext(isc_result
));
703 isc_mem_destroy(&mctx
);
704 return(T_UNRESOLVED
);
707 isc_result
= isc_condition_init(&T3_cv
);
708 if (isc_result
!= ISC_R_SUCCESS
) {
709 t_info("isc_condition_init failed %s\n",
710 isc_result_totext(isc_result
));
711 isc_mem_destroy(&mctx
);
712 return(T_UNRESOLVED
);
716 isc_result
= isc_taskmgr_create(mctx
, workers
, 0, &tmgr
);
717 if (isc_result
!= ISC_R_SUCCESS
) {
718 t_info("isc_taskmgr_create failed %s\n",
719 isc_result_totext(isc_result
));
720 isc_mem_destroy(&mctx
);
721 return(T_UNRESOLVED
);
724 isc_result
= isc_mutex_lock(&T3_mx
);
725 if (isc_result
!= ISC_R_SUCCESS
) {
726 t_info("isc_mutex_lock failed %s\n",
727 isc_result_totext(isc_result
));
728 isc_taskmgr_destroy(&tmgr
);
729 isc_mem_destroy(&mctx
);
730 return(T_UNRESOLVED
);
734 isc_result
= isc_task_create(tmgr
, 0, &task
);
735 if (isc_result
!= ISC_R_SUCCESS
) {
736 t_info("isc_task_create failed %s\n",
737 isc_result_totext(isc_result
));
738 isc_mutex_unlock(&T3_mx
);
739 isc_taskmgr_destroy(&tmgr
);
740 isc_mem_destroy(&mctx
);
741 return(T_UNRESOLVED
);
745 * This event causes the task to wait on T3_cv.
747 event
= isc_event_allocate(mctx
, &senders
[1], event_type
, t3_event1
,
748 NULL
, sizeof(*event
));
749 isc_task_send(task
, &event
);
752 * Now we fill up the task's event queue with some events.
754 for (cnt
= 0; cnt
< T3_NEVENTS
; ++cnt
) {
755 event
= isc_event_allocate(mctx
, &senders
[1], event_type
,
756 t3_event2
, NULL
, sizeof(*event
));
757 isc_task_send(task
, &event
);
761 * Now we register two shutdown events.
763 isc_result
= isc_task_onshutdown(task
, t3_sde1
, NULL
);
764 if (isc_result
!= ISC_R_SUCCESS
) {
765 t_info("isc_task_send failed %s\n",
766 isc_result_totext(isc_result
));
767 isc_mutex_unlock(&T3_mx
);
768 isc_task_destroy(&task
);
769 isc_taskmgr_destroy(&tmgr
);
770 isc_mem_destroy(&mctx
);
771 return(T_UNRESOLVED
);
774 isc_result
= isc_task_onshutdown(task
, t3_sde2
, NULL
);
775 if (isc_result
!= ISC_R_SUCCESS
) {
776 t_info("isc_task_send failed %s\n",
777 isc_result_totext(isc_result
));
778 isc_mutex_unlock(&T3_mx
);
779 isc_task_destroy(&task
);
780 isc_taskmgr_destroy(&tmgr
);
781 isc_mem_destroy(&mctx
);
782 return(T_UNRESOLVED
);
785 isc_task_shutdown(task
);
788 * Now we free the task by signaling T3_cv.
791 isc_result
= isc_condition_signal(&T3_cv
);
792 if (isc_result
!= ISC_R_SUCCESS
) {
793 t_info("isc_task_send failed %s\n",
794 isc_result_totext(isc_result
));
798 isc_result
= isc_mutex_unlock(&T3_mx
);
799 if (isc_result
!= ISC_R_SUCCESS
) {
800 t_info("isc_task_send failed %s\n",
801 isc_result_totext(isc_result
));
806 isc_task_detach(&task
);
807 isc_taskmgr_destroy(&tmgr
);
808 isc_mem_destroy(&mctx
);
810 if (T3_nsdevents
!= 2) {
811 t_info("T3_nsdevents == %d, expected 2\n", T3_nsdevents
);
815 if (T3_nevents
!= T3_nevents
) {
816 t_info("T3_nevents == %d, expected 2\n", T3_nevents
);
820 result
= T_UNRESOLVED
;
824 else if ((T3_nfails
== 0) && (T3_nprobs
== 0))
830 static const char *a3
= "When isc_task_shutdown() is called, any shutdown "
831 "events that have been requested via prior "
832 "isc_task_onshutdown() calls are posted in "
836 t_assert("tasks", 3, T_REQUIRED
, "%s", a3
);
839 t_result(t_tasks3());
844 static isc_mutex_t T4_mx
;
845 static isc_condition_t T4_cv
;
847 static int T4_nprobs
;
848 static int T4_nfails
;
851 t4_event1(isc_task_t
*task
, isc_event_t
*event
) {
852 isc_result_t isc_result
;
856 isc_result
= isc_mutex_lock(&T4_mx
);
857 if (isc_result
!= ISC_R_SUCCESS
) {
858 t_info("isc_mutex_lock failed %s\n",
859 isc_result_totext(isc_result
));
862 while (T4_flag
!= 1) {
863 (void) isc_condition_wait(&T4_cv
, &T4_mx
);
866 isc_result
= isc_mutex_unlock(&T4_mx
);
867 if (isc_result
!= ISC_R_SUCCESS
) {
868 t_info("isc_mutex_unlock failed %s\n",
869 isc_result_totext(isc_result
));
872 isc_event_free(&event
);
876 t4_sde(isc_task_t
*task
, isc_event_t
*event
) {
883 isc_event_free(&event
);
893 unsigned int workers
;
894 isc_result_t isc_result
;
895 isc_eventtype_t event_type
;
902 result
= T_UNRESOLVED
;
906 p
= t_getenv("ISC_TASK_WORKERS");
911 isc_result
= isc_mem_create(0, 0, &mctx
);
912 if (isc_result
!= ISC_R_SUCCESS
) {
913 t_info("isc_mem_create failed %s\n",
914 isc_result_totext(isc_result
));
915 return(T_UNRESOLVED
);
918 isc_result
= isc_mutex_init(&T4_mx
);
919 if (isc_result
!= ISC_R_SUCCESS
) {
920 t_info("isc_mutex_init failed %s\n",
921 isc_result_totext(isc_result
));
922 isc_mem_destroy(&mctx
);
923 return(T_UNRESOLVED
);
926 isc_result
= isc_condition_init(&T4_cv
);
927 if (isc_result
!= ISC_R_SUCCESS
) {
928 t_info("isc_condition_init failed %s\n",
929 isc_result_totext(isc_result
));
931 isc_mem_destroy(&mctx
);
932 return(T_UNRESOLVED
);
936 isc_result
= isc_taskmgr_create(mctx
, workers
, 0, &tmgr
);
937 if (isc_result
!= ISC_R_SUCCESS
) {
938 t_info("isc_taskmgr_create failed %s\n",
939 isc_result_totext(isc_result
));
941 isc_condition_destroy(&T4_cv
);
942 isc_mem_destroy(&mctx
);
943 return(T_UNRESOLVED
);
946 isc_result
= isc_mutex_lock(&T4_mx
);
947 if (isc_result
!= ISC_R_SUCCESS
) {
948 t_info("isc_mutex_lock failed %s\n",
949 isc_result_totext(isc_result
));
951 isc_condition_destroy(&T4_cv
);
952 isc_taskmgr_destroy(&tmgr
);
953 isc_mem_destroy(&mctx
);
954 return(T_UNRESOLVED
);
958 isc_result
= isc_task_create(tmgr
, 0, &task
);
959 if (isc_result
!= ISC_R_SUCCESS
) {
960 t_info("isc_task_create failed %s\n",
961 isc_result_totext(isc_result
));
963 isc_condition_destroy(&T4_cv
);
964 isc_taskmgr_destroy(&tmgr
);
965 isc_mem_destroy(&mctx
);
966 return(T_UNRESOLVED
);
970 * This event causes the task to wait on T4_cv.
972 event
= isc_event_allocate(mctx
, &senders
[1], event_type
, t4_event1
,
973 NULL
, sizeof(*event
));
974 isc_task_send(task
, &event
);
976 isc_task_shutdown(task
);
978 isc_result
= isc_task_onshutdown(task
, t4_sde
, NULL
);
979 if (isc_result
!= ISC_R_SHUTTINGDOWN
) {
980 t_info("isc_task_onshutdown returned %s\n",
981 isc_result_totext(isc_result
));
990 isc_result
= isc_condition_signal(&T4_cv
);
991 if (isc_result
!= ISC_R_SUCCESS
) {
992 t_info("isc_condition_signal failed %s\n",
993 isc_result_totext(isc_result
));
997 isc_result
= isc_mutex_unlock(&T4_mx
);
998 if (isc_result
!= ISC_R_SUCCESS
) {
999 t_info("isc_mutex_unlock failed %s\n",
1000 isc_result_totext(isc_result
));
1004 isc_task_detach(&task
);
1005 isc_taskmgr_destroy(&tmgr
);
1006 isc_mem_destroy(&mctx
);
1007 isc_condition_destroy(&T4_cv
);
1008 DESTROYLOCK(&T4_mx
);
1010 result
= T_UNRESOLVED
;
1014 else if ((T4_nfails
== 0) && (T4_nprobs
== 0))
1020 static const char *a4
=
1021 "After isc_task_shutdown() has been called, any call to "
1022 "isc_task_onshutdown() will return ISC_R_SHUTTINGDOWN.";
1026 t_assert("tasks", 4, T_REQUIRED
, "%s", a4
);
1029 t_result(t_tasks4());
1034 static int T7_nprobs
;
1035 static int T7_eflag
;
1036 static int T7_sdflag
;
1037 static isc_mutex_t T7_mx
;
1038 static isc_condition_t T7_cv
;
1040 static int T7_nfails
;
1043 t7_event1(isc_task_t
*task
, isc_event_t
*event
) {
1048 isc_event_free(&event
);
1052 t7_sde(isc_task_t
*task
, isc_event_t
*event
) {
1053 isc_result_t isc_result
;
1057 isc_result
= isc_mutex_lock(&T7_mx
);
1058 if (isc_result
!= ISC_R_SUCCESS
) {
1059 t_info("isc_mutex_lock failed %s\n",
1060 isc_result_totext(isc_result
));
1066 isc_result
= isc_condition_signal(&T7_cv
);
1067 if (isc_result
!= ISC_R_SUCCESS
) {
1068 t_info("isc_condition_signal failed %s\n",
1069 isc_result_totext(isc_result
));
1073 isc_result
= isc_mutex_unlock(&T7_mx
);
1074 if (isc_result
!= ISC_R_SUCCESS
) {
1075 t_info("isc_mutex_unlock failed %s\n",
1076 isc_result_totext(isc_result
));
1080 isc_event_free(&event
);
1088 isc_taskmgr_t
*tmgr
;
1090 unsigned int workers
;
1091 isc_result_t isc_result
;
1092 isc_eventtype_t event_type
;
1095 isc_interval_t interval
;
1102 result
= T_UNRESOLVED
;
1106 p
= t_getenv("ISC_TASK_WORKERS");
1111 isc_result
= isc_mem_create(0, 0, &mctx
);
1112 if (isc_result
!= ISC_R_SUCCESS
) {
1113 t_info("isc_mem_create failed %s\n",
1114 isc_result_totext(isc_result
));
1115 return(T_UNRESOLVED
);
1118 isc_result
= isc_mutex_init(&T7_mx
);
1119 if (isc_result
!= ISC_R_SUCCESS
) {
1120 t_info("isc_mutex_init failed %s\n",
1121 isc_result_totext(isc_result
));
1122 isc_mem_destroy(&mctx
);
1123 return(T_UNRESOLVED
);
1126 isc_result
= isc_condition_init(&T7_cv
);
1127 if (isc_result
!= ISC_R_SUCCESS
) {
1128 t_info("isc_condition_init failed %s\n",
1129 isc_result_totext(isc_result
));
1130 DESTROYLOCK(&T7_mx
);
1131 isc_mem_destroy(&mctx
);
1132 return(T_UNRESOLVED
);
1136 isc_result
= isc_taskmgr_create(mctx
, workers
, 0, &tmgr
);
1137 if (isc_result
!= ISC_R_SUCCESS
) {
1138 t_info("isc_taskmgr_create failed %s\n",
1139 isc_result_totext(isc_result
));
1140 DESTROYLOCK(&T7_mx
);
1141 isc_condition_destroy(&T7_cv
);
1142 isc_mem_destroy(&mctx
);
1143 return(T_UNRESOLVED
);
1146 isc_result
= isc_mutex_lock(&T7_mx
);
1147 if (isc_result
!= ISC_R_SUCCESS
) {
1148 t_info("isc_mutex_lock failed %s\n",
1149 isc_result_totext(isc_result
));
1150 DESTROYLOCK(&T7_mx
);
1151 isc_condition_destroy(&T7_cv
);
1152 isc_taskmgr_destroy(&tmgr
);
1153 isc_mem_destroy(&mctx
);
1158 isc_result
= isc_task_create(tmgr
, 0, &task
);
1159 if (isc_result
!= ISC_R_SUCCESS
) {
1160 t_info("isc_task_create failed %s\n",
1161 isc_result_totext(isc_result
));
1162 DESTROYLOCK(&T7_mx
);
1163 isc_condition_destroy(&T7_cv
);
1164 isc_taskmgr_destroy(&tmgr
);
1165 isc_mem_destroy(&mctx
);
1169 isc_result
= isc_task_onshutdown(task
, t7_sde
, NULL
);
1170 if (isc_result
!= ISC_R_SUCCESS
) {
1171 t_info("isc_task_onshutdown returned %s\n",
1172 isc_result_totext(isc_result
));
1173 DESTROYLOCK(&T7_mx
);
1174 isc_condition_destroy(&T7_cv
);
1175 isc_task_destroy(&task
);
1176 isc_taskmgr_destroy(&tmgr
);
1177 isc_mem_destroy(&mctx
);
1178 return(T_UNRESOLVED
);
1181 event
= isc_event_allocate(mctx
, &senders
[1], event_type
, t7_event1
,
1182 NULL
, sizeof(*event
));
1183 isc_task_send(task
, &event
);
1185 isc_task_shutdown(task
);
1187 interval
.seconds
= 5;
1188 interval
.nanoseconds
= 0;
1190 while (T7_sdflag
== 0) {
1191 isc_result
= isc_time_nowplusinterval(&now
, &interval
);
1192 if (isc_result
!= ISC_R_SUCCESS
) {
1193 t_info("isc_time_nowplusinterval failed %s\n",
1194 isc_result_totext(isc_result
));
1195 DESTROYLOCK(&T7_mx
);
1196 isc_condition_destroy(&T7_cv
);
1197 isc_task_destroy(&task
);
1198 isc_taskmgr_destroy(&tmgr
);
1199 isc_mem_destroy(&mctx
);
1200 return(T_UNRESOLVED
);
1203 isc_result
= isc_condition_waituntil(&T7_cv
, &T7_mx
, &now
);
1204 if (isc_result
!= ISC_R_SUCCESS
) {
1205 t_info("isc_condition_waituntil returned %s\n",
1206 isc_result_totext(isc_result
));
1207 DESTROYLOCK(&T7_mx
);
1208 isc_condition_destroy(&T7_cv
);
1209 isc_task_destroy(&task
);
1210 isc_taskmgr_destroy(&tmgr
);
1211 isc_mem_destroy(&mctx
);
1216 isc_result
= isc_mutex_unlock(&T7_mx
);
1217 if (isc_result
!= ISC_R_SUCCESS
) {
1218 t_info("isc_mutex_unlock failed %s\n",
1219 isc_result_totext(isc_result
));
1223 isc_task_detach(&task
);
1224 isc_taskmgr_destroy(&tmgr
);
1225 isc_mem_destroy(&mctx
);
1226 isc_condition_destroy(&T7_cv
);
1227 DESTROYLOCK(&T7_mx
);
1229 result
= T_UNRESOLVED
;
1236 else if ((T7_nfails
== 0) && (T7_nprobs
== 0))
1242 static const char *a7
= "A call to isc_task_create() creates a task that can "
1247 t_assert("tasks", 7, T_REQUIRED
, "%s", a7
);
1250 t_result(t_tasks7());
1255 #define T10_SENDERCNT 3
1256 #define T10_TYPECNT 4
1257 #define T10_TAGCNT 5
1258 #define T10_NEVENTS (T10_SENDERCNT*T10_TYPECNT*T10_TAGCNT)
1259 #define T_CONTROL 99999
1261 static int T10_nprobs
;
1262 static int T10_nfails
;
1263 static int T10_startflag
;
1264 static int T10_shutdownflag
;
1265 static int T10_eventcnt
;
1266 static isc_mutex_t T10_mx
;
1267 static isc_condition_t T10_cv
;
1269 static void *T10_purge_sender
;
1270 static isc_eventtype_t T10_purge_type_first
;
1271 static isc_eventtype_t T10_purge_type_last
;
1272 static void *T10_purge_tag
;
1273 static int T10_testrange
;
1276 t10_event1(isc_task_t
*task
, isc_event_t
*event
) {
1277 isc_result_t isc_result
;
1281 isc_result
= isc_mutex_lock(&T10_mx
);
1282 if (isc_result
!= ISC_R_SUCCESS
) {
1283 t_info("isc_mutex_lock failed %s\n",
1284 isc_result_totext(isc_result
));
1288 while (T10_startflag
== 0) {
1289 isc_result
= isc_condition_wait(&T10_cv
, &T10_mx
);
1290 if (isc_result
!= ISC_R_SUCCESS
) {
1291 t_info("isc_mutex_lock failed %s\n",
1292 isc_result_totext(isc_result
));
1297 isc_result
= isc_mutex_unlock(&T10_mx
);
1298 if (isc_result
!= ISC_R_SUCCESS
) {
1299 t_info("isc_mutex_unlock failed %s\n",
1300 isc_result_totext(isc_result
));
1304 isc_event_free(&event
);
1308 t10_event2(isc_task_t
*task
, isc_event_t
*event
) {
1321 t_info("Event %p,%d,%p,%s\n",
1323 (int)event
->ev_type
,
1325 event
->ev_attributes
& ISC_EVENTATTR_NOPURGE
?
1329 if ((T10_purge_sender
== NULL
) ||
1330 (T10_purge_sender
== event
->ev_sender
)) {
1333 if (T10_testrange
== 0) {
1334 if (T10_purge_type_first
== event
->ev_type
) {
1338 if ((T10_purge_type_first
<= event
->ev_type
) &&
1339 (event
->ev_type
<= T10_purge_type_last
)) {
1343 if ((T10_purge_tag
== NULL
) ||
1344 (T10_purge_tag
== event
->ev_tag
)) {
1348 if (sender_match
&& type_match
&& tag_match
) {
1349 if (event
->ev_attributes
& ISC_EVENTATTR_NOPURGE
) {
1350 t_info("event %p,%d,%p matched but was not purgable\n",
1351 event
->ev_sender
, (int)event
->ev_type
,
1355 t_info("*** event %p,%d,%p not purged\n",
1356 event
->ev_sender
, (int)event
->ev_type
,
1362 isc_event_free(&event
);
1367 t10_sde(isc_task_t
*task
, isc_event_t
*event
) {
1368 isc_result_t isc_result
;
1372 isc_result
= isc_mutex_lock(&T10_mx
);
1373 if (isc_result
!= ISC_R_SUCCESS
) {
1374 t_info("isc_mutex_lock failed %s\n",
1375 isc_result_totext(isc_result
));
1381 isc_result
= isc_condition_signal(&T10_cv
);
1382 if (isc_result
!= ISC_R_SUCCESS
) {
1383 t_info("isc_condition_signal failed %s\n",
1384 isc_result_totext(isc_result
));
1388 isc_result
= isc_mutex_unlock(&T10_mx
);
1389 if (isc_result
!= ISC_R_SUCCESS
) {
1390 t_info("isc_mutex_unlock failed %s\n",
1391 isc_result_totext(isc_result
));
1395 isc_event_free(&event
);
1399 t_taskpurge_x(int sender
, int type
, int tag
, void *purge_sender
,
1400 int purge_type_first
, int purge_type_last
, void *purge_tag
,
1401 int exp_nevents
, int *nfails
, int *nprobs
, int testrange
)
1405 isc_taskmgr_t
*tmgr
;
1407 unsigned int workers
;
1408 isc_result_t isc_result
;
1411 isc_interval_t interval
;
1418 isc_event_t
*eventtab
[T10_NEVENTS
];
1422 T10_shutdownflag
= 0;
1424 T10_purge_sender
= purge_sender
;
1425 T10_purge_type_first
= (isc_eventtype_t
) purge_type_first
;
1426 T10_purge_type_last
= (isc_eventtype_t
) purge_type_last
;
1427 T10_purge_tag
= purge_tag
;
1428 T10_testrange
= testrange
;
1431 p
= t_getenv("ISC_TASK_WORKERS");
1436 isc_result
= isc_mem_create(0, 0, &mctx
);
1437 if (isc_result
!= ISC_R_SUCCESS
) {
1438 t_info("isc_mem_create failed %s\n",
1439 isc_result_totext(isc_result
));
1444 isc_result
= isc_mutex_init(&T10_mx
);
1445 if (isc_result
!= ISC_R_SUCCESS
) {
1446 t_info("isc_mutex_init failed %s\n",
1447 isc_result_totext(isc_result
));
1448 isc_mem_destroy(&mctx
);
1453 isc_result
= isc_condition_init(&T10_cv
);
1454 if (isc_result
!= ISC_R_SUCCESS
) {
1455 t_info("isc_condition_init failed %s\n",
1456 isc_result_totext(isc_result
));
1457 isc_mem_destroy(&mctx
);
1458 DESTROYLOCK(&T10_mx
);
1464 isc_result
= isc_taskmgr_create(mctx
, workers
, 0, &tmgr
);
1465 if (isc_result
!= ISC_R_SUCCESS
) {
1466 t_info("isc_taskmgr_create failed %s\n",
1467 isc_result_totext(isc_result
));
1468 isc_mem_destroy(&mctx
);
1469 DESTROYLOCK(&T10_mx
);
1470 isc_condition_destroy(&T10_cv
);
1476 isc_result
= isc_task_create(tmgr
, 0, &task
);
1477 if (isc_result
!= ISC_R_SUCCESS
) {
1478 t_info("isc_task_create failed %s\n",
1479 isc_result_totext(isc_result
));
1480 isc_taskmgr_destroy(&tmgr
);
1481 isc_mem_destroy(&mctx
);
1482 DESTROYLOCK(&T10_mx
);
1483 isc_condition_destroy(&T10_cv
);
1488 isc_result
= isc_task_onshutdown(task
, t10_sde
, NULL
);
1489 if (isc_result
!= ISC_R_SUCCESS
) {
1490 t_info("isc_task_onshutdown returned %s\n",
1491 isc_result_totext(isc_result
));
1492 isc_task_destroy(&task
);
1493 isc_taskmgr_destroy(&tmgr
);
1494 isc_mem_destroy(&mctx
);
1495 DESTROYLOCK(&T10_mx
);
1496 isc_condition_destroy(&T10_cv
);
1502 * Block the task on T10_cv.
1504 event
= isc_event_allocate(mctx
, (void *)1, (isc_eventtype_t
)T_CONTROL
,
1505 t10_event1
, NULL
, sizeof(*event
));
1507 isc_task_send(task
, &event
);
1510 * Fill the task's queue with some messages with varying
1511 * sender, type, tag, and purgable attribute values.
1515 for (sender_cnt
= 0; sender_cnt
< T10_SENDERCNT
; ++sender_cnt
) {
1516 for (type_cnt
= 0; type_cnt
< T10_TYPECNT
; ++type_cnt
) {
1517 for (tag_cnt
= 0; tag_cnt
< T10_TAGCNT
; ++tag_cnt
) {
1518 eventtab
[event_cnt
] =
1519 isc_event_allocate(mctx
,
1520 &senders
[sender
+ sender_cnt
],
1521 (isc_eventtype_t
)(type
+ type_cnt
),
1522 t10_event2
, NULL
, sizeof(*event
));
1524 eventtab
[event_cnt
]->ev_tag
=
1525 (void *)((uintptr_t)tag
+ tag_cnt
);
1528 * Make all odd message non-purgable.
1530 if ((sender_cnt
% 2) && (type_cnt
%2) &&
1532 eventtab
[event_cnt
]->ev_attributes
|=
1533 ISC_EVENTATTR_NOPURGE
;
1539 for (cnt
= 0; cnt
< event_cnt
; ++cnt
)
1540 isc_task_send(task
, &eventtab
[cnt
]);
1543 t_info("%d events queued\n", cnt
);
1545 if (testrange
== 0) {
1547 * We're testing isc_task_purge.
1549 nevents
= isc_task_purge(task
, purge_sender
,
1550 (isc_eventtype_t
)purge_type_first
,
1552 if (nevents
!= exp_nevents
) {
1553 t_info("*** isc_task_purge returned %d, expected %d\n",
1554 nevents
, exp_nevents
);
1557 t_info("isc_task_purge returned %d\n", nevents
);
1560 * We're testing isc_task_purgerange.
1562 nevents
= isc_task_purgerange(task
, purge_sender
,
1563 (isc_eventtype_t
)purge_type_first
,
1564 (isc_eventtype_t
)purge_type_last
,
1566 if (nevents
!= exp_nevents
) {
1567 t_info("*** isc_task_purgerange returned %d, "
1568 "expected %d\n", nevents
, exp_nevents
);
1571 t_info("isc_task_purgerange returned %d\n", nevents
);
1574 isc_result
= isc_mutex_lock(&T10_mx
);
1575 if (isc_result
!= ISC_R_SUCCESS
) {
1576 t_info("isc_mutex_lock failed %s\n",
1577 isc_result_totext(isc_result
));
1578 isc_task_destroy(&task
);
1579 isc_taskmgr_destroy(&tmgr
);
1580 isc_mem_destroy(&mctx
);
1581 DESTROYLOCK(&T10_mx
);
1582 isc_condition_destroy(&T10_cv
);
1588 * Unblock the task, allowing event processing.
1591 isc_result
= isc_condition_signal(&T10_cv
);
1592 if (isc_result
!= ISC_R_SUCCESS
) {
1593 t_info("isc_condition_signal failed %s\n",
1594 isc_result_totext(isc_result
));
1598 isc_task_shutdown(task
);
1600 interval
.seconds
= 5;
1601 interval
.nanoseconds
= 0;
1604 * Wait for shutdown processing to complete.
1606 while (T10_shutdownflag
== 0) {
1607 isc_result
= isc_time_nowplusinterval(&now
, &interval
);
1608 if (isc_result
!= ISC_R_SUCCESS
) {
1609 t_info("isc_time_nowplusinterval failed %s\n",
1610 isc_result_totext(isc_result
));
1611 isc_task_detach(&task
);
1612 isc_taskmgr_destroy(&tmgr
);
1613 isc_mem_destroy(&mctx
);
1614 DESTROYLOCK(&T10_mx
);
1615 isc_condition_destroy(&T10_cv
);
1620 isc_result
= isc_condition_waituntil(&T10_cv
, &T10_mx
, &now
);
1621 if (isc_result
!= ISC_R_SUCCESS
) {
1622 t_info("isc_condition_waituntil returned %s\n",
1623 isc_result_totext(isc_result
));
1624 isc_task_detach(&task
);
1625 isc_taskmgr_destroy(&tmgr
);
1626 isc_mem_destroy(&mctx
);
1627 DESTROYLOCK(&T10_mx
);
1628 isc_condition_destroy(&T10_cv
);
1634 isc_result
= isc_mutex_unlock(&T10_mx
);
1635 if (isc_result
!= ISC_R_SUCCESS
) {
1636 t_info("isc_mutex_unlock failed %s\n",
1637 isc_result_totext(isc_result
));
1641 isc_task_detach(&task
);
1642 isc_taskmgr_destroy(&tmgr
);
1643 isc_mem_destroy(&mctx
);
1644 DESTROYLOCK(&T10_mx
);
1645 isc_condition_destroy(&T10_cv
);
1648 t_info("task processed %d events\n", T10_eventcnt
);
1650 if ((T10_eventcnt
+ nevents
) != event_cnt
) {
1651 t_info("*** processed %d, purged %d, total %d\n",
1652 T10_eventcnt
, nevents
, event_cnt
);
1665 * Try purging on a specific sender.
1667 t_info("testing purge on 2,4,8 expecting 1\n");
1668 t_taskpurge_x(1, 4, 7, &senders
[2], 4, 4, (void *)8, 1, &T10_nfails
,
1672 * Try purging on all senders.
1674 t_info("testing purge on 0,4,8 expecting 3\n");
1675 t_taskpurge_x(1, 4, 7, NULL
, 4, 4, (void *)8, 3, &T10_nfails
,
1679 * Try purging on all senders, specified type, all tags.
1681 t_info("testing purge on 0,4,0 expecting 15\n");
1682 t_taskpurge_x(1, 4, 7, NULL
, 4, 4, NULL
, 15, &T10_nfails
,
1686 * Try purging on a specified tag, no such type.
1688 t_info("testing purge on 0,99,8 expecting 0\n");
1689 t_taskpurge_x(1, 4, 7, NULL
, 99, 99, (void *)8, 0, &T10_nfails
,
1693 * Try purging on specified sender, type, all tags.
1695 t_info("testing purge on 0,5,0 expecting 5\n");
1696 t_taskpurge_x(1, 4, 7, &senders
[3], 5, 5, NULL
, 5, &T10_nfails
,
1699 result
= T_UNRESOLVED
;
1701 if ((T10_nfails
== 0) && (T10_nprobs
== 0))
1703 else if (T10_nfails
!= 0)
1709 static const char *a10
=
1710 "A call to isc_task_purge(task, sender, type, tag) "
1711 "purges all events of type 'type' and with tag 'tag' "
1712 "not marked as unpurgable from sender from the task's "
1713 "queue and returns the number of events purged.";
1717 t_assert("tasks", 10, T_REQUIRED
, "%s", a10
);
1720 t_result(t_tasks10());
1725 static int T11_nprobs
;
1726 static int T11_nfails
;
1727 static int T11_startflag
;
1728 static int T11_shutdownflag
;
1729 static int T11_eventcnt
;
1730 static isc_mutex_t T11_mx
;
1731 static isc_condition_t T11_cv
;
1734 t11_event1(isc_task_t
*task
, isc_event_t
*event
) {
1735 isc_result_t isc_result
;
1739 isc_result
= isc_mutex_lock(&T11_mx
);
1740 if (isc_result
!= ISC_R_SUCCESS
) {
1741 t_info("isc_mutex_lock failed %s\n",
1742 isc_result_totext(isc_result
));
1746 while (T11_startflag
== 0) {
1747 isc_result
= isc_condition_wait(&T11_cv
, &T11_mx
);
1748 if (isc_result
!= ISC_R_SUCCESS
) {
1749 t_info("isc_mutex_lock failed %s\n",
1750 isc_result_totext(isc_result
));
1755 isc_result
= isc_mutex_unlock(&T11_mx
);
1756 if (isc_result
!= ISC_R_SUCCESS
) {
1757 t_info("isc_mutex_unlock failed %s\n",
1758 isc_result_totext(isc_result
));
1762 isc_event_free(&event
);
1766 t11_event2(isc_task_t
*task
, isc_event_t
*event
) {
1770 isc_event_free(&event
);
1775 t11_sde(isc_task_t
*task
, isc_event_t
*event
) {
1776 isc_result_t isc_result
;
1780 isc_result
= isc_mutex_lock(&T11_mx
);
1781 if (isc_result
!= ISC_R_SUCCESS
) {
1782 t_info("isc_mutex_lock failed %s\n",
1783 isc_result_totext(isc_result
));
1789 isc_result
= isc_condition_signal(&T11_cv
);
1790 if (isc_result
!= ISC_R_SUCCESS
) {
1791 t_info("isc_condition_signal failed %s\n",
1792 isc_result_totext(isc_result
));
1796 isc_result
= isc_mutex_unlock(&T11_mx
);
1797 if (isc_result
!= ISC_R_SUCCESS
) {
1798 t_info("isc_mutex_unlock failed %s\n",
1799 isc_result_totext(isc_result
));
1803 isc_event_free(&event
);
1807 t_tasks11(int purgable
) {
1810 isc_taskmgr_t
*tmgr
;
1813 unsigned int workers
;
1814 isc_result_t isc_result
;
1815 isc_event_t
*event1
;
1816 isc_event_t
*event2
, *event2_clone
;
1818 isc_interval_t interval
;
1822 T11_shutdownflag
= 0;
1826 p
= t_getenv("ISC_TASK_WORKERS");
1831 isc_result
= isc_mem_create(0, 0, &mctx
);
1832 if (isc_result
!= ISC_R_SUCCESS
) {
1833 t_info("isc_mem_create failed %s\n",
1834 isc_result_totext(isc_result
));
1835 return(T_UNRESOLVED
);
1838 isc_result
= isc_mutex_init(&T11_mx
);
1839 if (isc_result
!= ISC_R_SUCCESS
) {
1840 t_info("isc_mutex_init failed %s\n",
1841 isc_result_totext(isc_result
));
1842 isc_mem_destroy(&mctx
);
1843 return(T_UNRESOLVED
);
1846 isc_result
= isc_condition_init(&T11_cv
);
1847 if (isc_result
!= ISC_R_SUCCESS
) {
1848 t_info("isc_condition_init failed %s\n",
1849 isc_result_totext(isc_result
));
1850 isc_mem_destroy(&mctx
);
1851 DESTROYLOCK(&T11_mx
);
1852 return(T_UNRESOLVED
);
1856 isc_result
= isc_taskmgr_create(mctx
, workers
, 0, &tmgr
);
1857 if (isc_result
!= ISC_R_SUCCESS
) {
1858 t_info("isc_taskmgr_create failed %s\n",
1859 isc_result_totext(isc_result
));
1860 isc_mem_destroy(&mctx
);
1861 DESTROYLOCK(&T11_mx
);
1862 isc_condition_destroy(&T11_cv
);
1863 return(T_UNRESOLVED
);
1867 isc_result
= isc_task_create(tmgr
, 0, &task
);
1868 if (isc_result
!= ISC_R_SUCCESS
) {
1869 t_info("isc_task_create failed %s\n",
1870 isc_result_totext(isc_result
));
1871 isc_taskmgr_destroy(&tmgr
);
1872 isc_mem_destroy(&mctx
);
1873 DESTROYLOCK(&T11_mx
);
1874 isc_condition_destroy(&T11_cv
);
1875 return(T_UNRESOLVED
);
1878 isc_result
= isc_task_onshutdown(task
, t11_sde
, NULL
);
1879 if (isc_result
!= ISC_R_SUCCESS
) {
1880 t_info("isc_task_onshutdown returned %s\n",
1881 isc_result_totext(isc_result
));
1882 isc_task_destroy(&task
);
1883 isc_taskmgr_destroy(&tmgr
);
1884 isc_mem_destroy(&mctx
);
1885 DESTROYLOCK(&T11_mx
);
1886 isc_condition_destroy(&T11_cv
);
1887 return(T_UNRESOLVED
);
1891 * Block the task on T11_cv.
1893 event1
= isc_event_allocate(mctx
, (void *)1, (isc_eventtype_t
)1,
1894 t11_event1
, NULL
, sizeof(*event1
));
1896 isc_task_send(task
, &event1
);
1898 event2
= isc_event_allocate(mctx
, (void *)1, (isc_eventtype_t
)1,
1899 t11_event2
, NULL
, sizeof(*event2
));
1900 event2_clone
= event2
;
1902 event2
->ev_attributes
&= ~ISC_EVENTATTR_NOPURGE
;
1904 event2
->ev_attributes
|= ISC_EVENTATTR_NOPURGE
;
1906 isc_task_send(task
, &event2
);
1908 rval
= isc_task_purgeevent(task
, event2_clone
);
1909 if (rval
!= (purgable
? ISC_TRUE
: ISC_FALSE
)) {
1910 t_info("isc_task_purgeevent returned %s, expected %s\n",
1911 (rval
? "ISC_TRUE" : "ISC_FALSE"),
1912 (purgable
? "ISC_TRUE" : "ISC_FALSE"));
1916 isc_result
= isc_mutex_lock(&T11_mx
);
1917 if (isc_result
!= ISC_R_SUCCESS
) {
1918 t_info("isc_mutex_lock failed %s\n",
1919 isc_result_totext(isc_result
));
1924 * Unblock the task, allowing event processing.
1927 isc_result
= isc_condition_signal(&T11_cv
);
1928 if (isc_result
!= ISC_R_SUCCESS
) {
1929 t_info("isc_condition_signal failed %s\n",
1930 isc_result_totext(isc_result
));
1934 isc_task_shutdown(task
);
1936 interval
.seconds
= 5;
1937 interval
.nanoseconds
= 0;
1940 * Wait for shutdown processing to complete.
1942 while (T11_shutdownflag
== 0) {
1943 isc_result
= isc_time_nowplusinterval(&now
, &interval
);
1944 if (isc_result
!= ISC_R_SUCCESS
) {
1945 t_info("isc_time_nowplusinterval failed %s\n",
1946 isc_result_totext(isc_result
));
1950 isc_result
= isc_condition_waituntil(&T11_cv
, &T11_mx
, &now
);
1951 if (isc_result
!= ISC_R_SUCCESS
) {
1952 t_info("isc_condition_waituntil returned %s\n",
1953 isc_result_totext(isc_result
));
1958 isc_result
= isc_mutex_unlock(&T11_mx
);
1959 if (isc_result
!= ISC_R_SUCCESS
) {
1960 t_info("isc_mutex_unlock failed %s\n",
1961 isc_result_totext(isc_result
));
1965 isc_task_detach(&task
);
1966 isc_taskmgr_destroy(&tmgr
);
1967 isc_mem_destroy(&mctx
);
1968 DESTROYLOCK(&T11_mx
);
1969 isc_condition_destroy(&T11_cv
);
1971 if (T11_eventcnt
!= (purgable
? 0 : 1)) {
1972 t_info("Event was %s purged\n",
1973 (purgable
? "not" : "unexpectedly"));
1977 result
= T_UNRESOLVED
;
1979 if ((T11_nfails
== 0) && (T11_nprobs
== 0))
1981 else if (T11_nfails
)
1987 static const char *a11
=
1988 "When the event is marked as purgable, a call to "
1989 "isc_task_purgeevent(task, event) purges the event 'event' "
1990 "from the task's queue and returns ISC_TRUE.";
1994 t_assert("tasks", 11, T_REQUIRED
, "%s", a11
);
1997 t_result(t_tasks11(1));
2002 static const char *a12
=
2003 "When the event is not marked as purgable, a call to "
2004 "isc_task_purgeevent(task, event) does not purge the "
2005 "event 'event' from the task's queue and returns "
2010 return(t_tasks11(0));
2015 t_assert("tasks", 12, T_REQUIRED
, "%s", a12
);
2018 t_result(t_tasks12());
2023 static int T13_nfails
;
2024 static int T13_nprobs
;
2026 static const char *a13
=
2028 "isc_event_purgerange(task, sender, first, last, tag) "
2029 "purges all events not marked unpurgable from "
2030 "sender 'sender' and of type within the range 'first' "
2031 "to 'last' inclusive from the task's event queue and "
2032 "returns the number of tasks purged.";
2042 * First let's try the same cases we used in t10.
2046 * Try purging on a specific sender.
2048 t_info("testing purge on 2,4,8 expecting 1\n");
2049 t_taskpurge_x(1, 4, 7, &senders
[2], 4, 4, (void *)8, 1,
2050 &T13_nfails
, &T13_nprobs
, 1);
2053 * Try purging on all senders.
2055 t_info("testing purge on 0,4,8 expecting 3\n");
2056 t_taskpurge_x(1, 4, 7, NULL
, 4, 4, (void *)8, 3,
2057 &T13_nfails
, &T13_nprobs
, 1);
2060 * Try purging on all senders, specified type, all tags.
2062 t_info("testing purge on 0,4,0 expecting 15\n");
2063 t_taskpurge_x(1, 4, 7, NULL
, 4, 4, NULL
, 15, &T13_nfails
, &T13_nprobs
, 1);
2066 * Try purging on a specified tag, no such type.
2068 t_info("testing purge on 0,99,8 expecting 0\n");
2069 t_taskpurge_x(1, 4, 7, NULL
, 99, 99, (void *)8, 0,
2070 &T13_nfails
, &T13_nprobs
, 1);
2073 * Try purging on specified sender, type, all tags.
2075 t_info("testing purge on 3,5,0 expecting 5\n");
2076 t_taskpurge_x(1, 4, 7, &senders
[3], 5, 5, 0, 5, &T13_nfails
, &T13_nprobs
, 1);
2079 * Now let's try some ranges.
2082 t_info("testing purgerange on 2,4-5,8 expecting 2\n");
2083 t_taskpurge_x(1, 4, 7, &senders
[2], 4, 5, (void *)8, 1,
2084 &T13_nfails
, &T13_nprobs
, 1);
2087 * Try purging on all senders.
2089 t_info("testing purge on 0,4-5,8 expecting 5\n");
2090 t_taskpurge_x(1, 4, 7, NULL
, 4, 5, (void *)8, 5,
2091 &T13_nfails
, &T13_nprobs
, 1);
2094 * Try purging on all senders, specified type, all tags.
2096 t_info("testing purge on 0,5-6,0 expecting 28\n");
2097 t_taskpurge_x(1, 4, 7, NULL
, 5, 6, NULL
, 28, &T13_nfails
, &T13_nprobs
, 1);
2100 * Try purging on a specified tag, no such type.
2102 t_info("testing purge on 0,99-101,8 expecting 0\n");
2103 t_taskpurge_x(1, 4, 7, NULL
, 99, 101, (void *)8, 0,
2104 &T13_nfails
, &T13_nprobs
, 1);
2107 * Try purging on specified sender, type, all tags.
2109 t_info("testing purge on 3,5-6,0 expecting 10\n");
2110 t_taskpurge_x(1, 4, 7, &senders
[3], 5, 6, NULL
, 10, &T13_nfails
,
2113 result
= T_UNRESOLVED
;
2115 if ((T13_nfails
== 0) && (T13_nprobs
== 0))
2117 else if (T13_nfails
)
2125 t_assert("tasks", 13, T_REQUIRED
, "%s", a13
);
2128 t_result(t_tasks13());
2133 #define T14_NTASKS 10
2134 #define T14_EXCLTASK 6
2136 int t14_exclusiveerror
= ISC_R_SUCCESS
;
2142 int t14_active
[T14_NTASKS
];
2145 t14_callback(isc_task_t
*task
, isc_event_t
*event
) {
2146 int taskno
= *(int *)(event
->ev_arg
);
2149 t_info("task enter %d\n", taskno
);
2150 if (taskno
== T14_EXCLTASK
) {
2152 t14_exclusiveerror
= isc_task_beginexclusive(task
);
2153 if (t14_exclusiveerror
== ISC_R_SUCCESS
)
2154 t_info("task %d got exclusive access\n", taskno
);
2156 t_info("task %d failed to got exclusive access: %d\n",
2157 taskno
, t14_exclusiveerror
);
2158 for (i
= 0; i
< T14_NTASKS
; i
++) {
2159 t_info("task %d state %d\n", i
, t14_active
[i
]);
2163 isc_task_endexclusive(task
);
2166 t14_active
[taskno
]++;
2167 (void) spin(10000000);
2168 t14_active
[taskno
]--;
2170 t_info("task exit %d\n", taskno
);
2172 isc_mem_put(event
->ev_destroy_arg
, event
->ev_arg
, sizeof (int));
2173 isc_event_free(&event
);
2175 isc_task_send(task
, &event
);
2182 for (i
= 0; i
< n
; i
++) {
2194 isc_taskmgr_t
*manager
;
2195 isc_task_t
*tasks
[T14_NTASKS
];
2196 unsigned int workers
;
2197 isc_result_t isc_result
;
2203 for (i
= 0; i
< T14_NTASKS
; i
++)
2207 p
= t_getenv("ISC_TASK_WORKERS");
2211 t_info("Bad config value for ISC_TASK_WORKERS, %d\n", workers
);
2212 return(T_UNRESOLVED
);
2215 isc_result
= isc_mem_create(0, 0, &mctx
);
2216 if (isc_result
!= ISC_R_SUCCESS
) {
2217 t_info("isc_mem_create failed %d\n", isc_result
);
2218 return(T_UNRESOLVED
);
2221 isc_result
= isc_taskmgr_create(mctx
, workers
, 0, &manager
);
2222 if (isc_result
!= ISC_R_SUCCESS
) {
2223 t_info("isc_taskmgr_create failed %d\n", isc_result
);
2227 for (i
= 0; i
< T14_NTASKS
; i
++) {
2231 isc_result
= isc_task_create(manager
, 0, &tasks
[i
]);
2232 if (isc_result
!= ISC_R_SUCCESS
) {
2233 t_info("isc_task_create failed %d\n", isc_result
);
2237 v
= isc_mem_get(mctx
, sizeof *v
);
2239 isc_task_detach(&tasks
[i
]);
2240 t_info("isc_mem_get failed\n");
2245 event
= isc_event_allocate(mctx
, NULL
, 1, t14_callback
,
2247 if (event
== NULL
) {
2248 isc_mem_put(mctx
, v
, sizeof *v
);
2249 t_info("isc_event_allocate failed\n");
2250 return(T_UNRESOLVED
);
2252 isc_task_send(tasks
[i
], &event
);
2255 for (i
= 0; i
< T14_NTASKS
; i
++) {
2256 isc_task_detach(&tasks
[i
]);
2259 isc_taskmgr_destroy(&manager
);
2261 if (t14_exclusiveerror
!= ISC_R_SUCCESS
|| t14_error
) {
2262 if (t14_exclusiveerror
!= ISC_R_SUCCESS
)
2263 t_info("isc_task_beginexclusive() failed\n");
2265 t_info("mutual access occurred\n");
2269 isc_mem_destroy(&mctx
);
2277 t_assert("tasks", 14, T_REQUIRED
, "%s",
2278 "isc_task_beginexclusive() gets exclusive access");
2279 result
= t_tasks14();
2283 testspec_t T_testlist
[] = {
2284 { t1
, "basic task subsystem" },
2286 { t3
, "isc_task_shutdown" },
2287 { t4
, "isc_task_shutdown" },
2288 { t7
, "isc_task_create" },
2289 { t10
, "isc_task_purge" },
2290 { t11
, "isc_task_purgeevent" },
2291 { t12
, "isc_task_purgeevent" },
2292 { t13
, "isc_task_purgerange" },
2293 { t14
, "isc_task_beginexclusive" },