1 /* $NetBSD: t_tasks.c,v 1.7 2014/12/10 04:37:54 christos Exp $ */
4 * Copyright (C) 2004, 2005, 2007, 2009, 2011, 2013, 2014 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.49 2011/07/27 07:45:55 marka 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
) {
76 t_info("shutdown %s\n", (char *)event
->ev_arg
);
77 isc_event_free(&event
);
81 my_tick(isc_task_t
*task
, isc_event_t
*event
) {
85 t_info("%s\n", (char *)event
->ev_arg
);
86 isc_event_free(&event
);
90 * Adapted from RTH's original task_test program
93 static char one
[] = "1";
94 static char two
[] = "2";
95 static char three
[] = "3";
96 static char four
[] = "4";
97 static char tick
[] = "tick";
98 static char tock
[] = "tock";
104 isc_taskmgr_t
*manager
;
110 unsigned int workers
;
111 isc_timermgr_t
*timgr
;
114 isc_result_t isc_result
;
116 isc_interval_t interval
;
126 p
= t_getenv("ISC_TASK_WORKERS");
130 t_info("Bad config value for ISC_TASK_WORKERS, %d\n", workers
);
131 return(T_UNRESOLVED
);
134 isc_result
= isc_mem_create(0, 0, &mctx
);
135 if (isc_result
!= ISC_R_SUCCESS
) {
136 t_info("isc_mem_create failed %d\n", isc_result
);
137 return(T_UNRESOLVED
);
140 isc_result
= isc_taskmgr_create(mctx
, workers
, 0, &manager
);
141 if (isc_result
!= ISC_R_SUCCESS
) {
142 t_info("isc_taskmgr_create failed %d\n", isc_result
);
146 isc_result
= isc_task_create(manager
, 0, &task1
);
147 if (isc_result
!= ISC_R_SUCCESS
) {
148 t_info("isc_task_create failed %d\n", isc_result
);
152 isc_result
= isc_task_create(manager
, 0, &task2
);
153 if (isc_result
!= ISC_R_SUCCESS
) {
154 t_info("isc_task_create failed %d\n", isc_result
);
158 isc_result
= isc_task_create(manager
, 0, &task3
);
159 if (isc_result
!= ISC_R_SUCCESS
) {
160 t_info("isc_task_create failed %d\n", isc_result
);
164 isc_result
= isc_task_create(manager
, 0, &task4
);
165 if (isc_result
!= ISC_R_SUCCESS
) {
166 t_info("isc_task_create failed %d\n", isc_result
);
170 isc_result
= isc_task_onshutdown(task1
, t1_shutdown
, one
);
171 if (isc_result
!= ISC_R_SUCCESS
) {
172 t_info("isc_task_onshutdown failed %d\n", isc_result
);
176 isc_result
= isc_task_onshutdown(task2
, t1_shutdown
, two
);
177 if (isc_result
!= ISC_R_SUCCESS
) {
178 t_info("isc_task_onshutdown failed %d\n", isc_result
);
182 isc_result
= isc_task_onshutdown(task3
, t1_shutdown
, three
);
183 if (isc_result
!= ISC_R_SUCCESS
) {
184 t_info("isc_task_onshutdown failed %d\n", isc_result
);
188 isc_result
= isc_task_onshutdown(task4
, t1_shutdown
, four
);
189 if (isc_result
!= ISC_R_SUCCESS
) {
190 t_info("isc_task_onshutdown failed %d\n", isc_result
);
195 isc_result
= isc_timermgr_create(mctx
, &timgr
);
196 if (isc_result
!= ISC_R_SUCCESS
) {
197 t_info("isc_timermgr_create %d\n", isc_result
);
198 return(T_UNRESOLVED
);
202 isc_time_settoepoch(&absolute
);
203 isc_interval_set(&interval
, 1, 0);
204 isc_result
= isc_timer_create(timgr
, isc_timertype_ticker
,
205 &absolute
, &interval
,
206 task1
, my_tick
, tick
, &ti1
);
207 if (isc_result
!= ISC_R_SUCCESS
) {
208 t_info("isc_timer_create %d\n", isc_result
);
209 return(T_UNRESOLVED
);
213 isc_time_settoepoch(&absolute
);
214 isc_interval_set(&interval
, 1, 0);
215 isc_result
= isc_timer_create(timgr
, isc_timertype_ticker
,
216 &absolute
, &interval
,
217 task2
, my_tick
, tock
, &ti2
);
218 if (isc_result
!= ISC_R_SUCCESS
) {
219 t_info("isc_timer_create %d\n", isc_result
);
220 return(T_UNRESOLVED
);
231 * Note: (void *)1 is used as a sender here, since some compilers
232 * don't like casting a function pointer to a (void *).
234 * In a real use, it is more likely the sender would be a
235 * structure (socket, timer, task, etc) but this is just a test
238 event
= isc_event_allocate(mctx
, (void *)1, 1, t1_callback
, one
,
241 t_info("isc_event_allocate failed\n");
242 return(T_UNRESOLVED
);
245 isc_task_send(task1
, &event
);
247 event
= isc_event_allocate(mctx
, (void *)1, 1, t1_callback
, one
,
250 t_info("isc_event_allocate failed\n");
251 return(T_UNRESOLVED
);
254 isc_task_send(task1
, &event
);
256 event
= isc_event_allocate(mctx
, (void *)1, 1, t1_callback
, one
,
259 t_info("isc_event_allocate failed\n");
260 return(T_UNRESOLVED
);
263 isc_task_send(task1
, &event
);
265 event
= isc_event_allocate(mctx
, (void *)1, 1, t1_callback
, one
,
268 t_info("isc_event_allocate failed\n");
269 return(T_UNRESOLVED
);
272 isc_task_send(task1
, &event
);
274 event
= isc_event_allocate(mctx
, (void *)1, 1, t1_callback
, one
,
277 t_info("isc_event_allocate failed\n");
278 return(T_UNRESOLVED
);
281 isc_task_send(task1
, &event
);
283 event
= isc_event_allocate(mctx
, (void *)1, 1, t1_callback
, one
,
286 t_info("isc_event_allocate failed\n");
287 return(T_UNRESOLVED
);
290 isc_task_send(task1
, &event
);
292 event
= isc_event_allocate(mctx
, (void *)1, 1, t1_callback
, one
,
295 t_info("isc_event_allocate failed\n");
296 return(T_UNRESOLVED
);
299 isc_task_send(task1
, &event
);
301 event
= isc_event_allocate(mctx
, (void *)1, 1, t1_callback
, one
,
304 t_info("isc_event_allocate failed\n");
305 return(T_UNRESOLVED
);
308 isc_task_send(task1
, &event
);
310 event
= isc_event_allocate(mctx
, (void *)1, 1, t1_callback
, one
,
313 t_info("isc_event_allocate failed\n");
314 return(T_UNRESOLVED
);
317 isc_task_send(task1
, &event
);
319 event
= isc_event_allocate(mctx
, (void *)1, 1, t1_callback
, two
,
322 t_info("isc_event_allocate failed\n");
323 return(T_UNRESOLVED
);
326 isc_task_send(task2
, &event
);
328 event
= isc_event_allocate(mctx
, (void *)1, 1, t1_callback
, three
,
331 t_info("isc_event_allocate failed\n");
332 return(T_UNRESOLVED
);
335 isc_task_send(task3
, &event
);
337 event
= isc_event_allocate(mctx
, (void *)1, 1, t1_callback
, four
,
340 t_info("isc_event_allocate failed\n");
341 return(T_UNRESOLVED
);
344 isc_task_send(task4
, &event
);
346 event
= isc_event_allocate(mctx
, (void *)1, 1, t1_callback
, two
,
349 t_info("isc_event_allocate failed\n");
350 return(T_UNRESOLVED
);
353 isc_task_send(task2
, &event
);
355 event
= isc_event_allocate(mctx
, (void *)1, 1, t1_callback
, three
,
358 t_info("isc_event_allocate failed\n");
359 return(T_UNRESOLVED
);
362 isc_task_send(task3
, &event
);
364 event
= isc_event_allocate(mctx
, (void *)1, 1, t1_callback
, four
,
367 t_info("isc_event_allocate failed\n");
368 return(T_UNRESOLVED
);
371 isc_task_send(task4
, &event
);
373 (void)isc_task_purge(task3
, NULL
, 0, 0);
375 isc_task_detach(&task1
);
376 isc_task_detach(&task2
);
377 isc_task_detach(&task3
);
378 isc_task_detach(&task4
);
385 isc_timer_detach(&ti1
);
386 isc_timer_detach(&ti2
);
387 isc_timermgr_destroy(&timgr
);
388 isc_taskmgr_destroy(&manager
);
390 isc_mem_destroy(&mctx
);
394 static const char *a1
= "The task subsystem can create and manage tasks";
400 t_assert("tasks", 1, T_REQUIRED
, "%s", a1
);
405 #define T2_NTASKS 10000
407 static isc_event_t
*T2_event
;
408 static isc_taskmgr_t
*T2_manager
;
409 static isc_mem_t
*T2_mctx
;
410 static isc_condition_t T2_cv
;
411 static isc_mutex_t T2_mx
;
413 static int T2_nprobs
;
414 static int T2_nfails
;
415 static int T2_ntasks
;
418 t2_shutdown(isc_task_t
*task
, isc_event_t
*event
) {
420 isc_result_t isc_result
;
424 if (event
->ev_arg
!= NULL
) {
425 isc_task_destroy((isc_task_t
**) &event
->ev_arg
);
428 isc_result
= isc_mutex_lock(&T2_mx
);
429 if (isc_result
!= ISC_R_SUCCESS
) {
430 t_info("isc_mutex_lock failed %d\n", isc_result
);
436 isc_result
= isc_condition_signal(&T2_cv
);
437 if (isc_result
!= ISC_R_SUCCESS
) {
438 t_info("isc_condition_signal failed %d\n", isc_result
);
442 isc_result
= isc_mutex_unlock(&T2_mx
);
443 if (isc_result
!= ISC_R_SUCCESS
) {
444 t_info("isc_mutex_unlock failed %d\n", isc_result
);
448 isc_event_free(&T2_event
);
449 isc_taskmgr_destroy(&T2_manager
);
450 isc_mem_destroy(&T2_mctx
);
455 t2_callback(isc_task_t
*task
, isc_event_t
*event
) {
456 isc_result_t isc_result
;
461 if (T_debug
&& ((T2_ntasks
% 100) == 0)) {
462 t_info("T2_ntasks %d\n", T2_ntasks
);
467 event
->ev_arg
= (void *)(((uintptr_t) event
->ev_arg
) - 1);
470 * Create a new task and forward the message.
473 isc_result
= isc_task_create(T2_manager
, 0, &newtask
);
474 if (isc_result
!= ISC_R_SUCCESS
) {
475 t_info("isc_task_create failed %d\n", isc_result
);
480 isc_result
= isc_task_onshutdown(newtask
, t2_shutdown
,
482 if (isc_result
!= ISC_R_SUCCESS
) {
483 t_info("isc_task_onshutdown failed %d\n",
489 isc_task_send(newtask
, &event
);
492 * Time to unwind, shutdown should perc back up.
494 isc_task_destroy(&task
);
504 unsigned int workers
;
505 isc_result_t isc_result
;
514 p
= t_getenv("ISC_TASK_WORKERS");
518 t_info("Bad config value for ISC_TASK_WORKERS, %d\n", workers
);
519 return(T_UNRESOLVED
);
522 p
= t_getenv("ISC_TASKS_MIN");
528 t_info("Bad config value for ISC_TASKS_MIN, %lu\n",
529 (unsigned long)ntasks
);
530 return(T_UNRESOLVED
);
533 t_info("Testing with %lu tasks\n", (unsigned long)ntasks
);
535 isc_result
= isc_mutex_init(&T2_mx
);
536 if (isc_result
!= ISC_R_SUCCESS
) {
537 t_info("isc_mutex_init failed %d\n", isc_result
);
538 return(T_UNRESOLVED
);
541 isc_result
= isc_condition_init(&T2_cv
);
542 if (isc_result
!= ISC_R_SUCCESS
) {
543 t_info("isc_condition_init failed %d\n", isc_result
);
544 return(T_UNRESOLVED
);
547 isc_result
= isc_mem_create(0, 0, &T2_mctx
);
548 if (isc_result
!= ISC_R_SUCCESS
) {
549 t_info("isc_mem_create failed %d\n", isc_result
);
550 return(T_UNRESOLVED
);
553 isc_result
= isc_taskmgr_create(T2_mctx
, workers
, 0, &T2_manager
);
554 if (isc_result
!= ISC_R_SUCCESS
) {
555 t_info("isc_taskmgr_create failed %d\n", isc_result
);
559 T2_event
= isc_event_allocate(T2_mctx
, (void *)1, 1, t2_callback
,
560 (void *)ntasks
, sizeof(*event
));
561 if (T2_event
== NULL
) {
562 t_info("isc_event_allocate failed\n");
563 return(T_UNRESOLVED
);
566 isc_result
= isc_mutex_lock(&T2_mx
);
567 if (isc_result
!= ISC_R_SUCCESS
) {
568 t_info("isc_mutex_lock failed %d\n", isc_result
);
569 return(T_UNRESOLVED
);
572 t2_callback(NULL
, T2_event
);
574 while (T2_done
== 0) {
575 isc_result
= isc_condition_wait(&T2_cv
, &T2_mx
);
576 if (isc_result
!= ISC_R_SUCCESS
) {
577 t_info("isc_condition_wait failed %d\n", isc_result
);
578 return(T_UNRESOLVED
);
582 result
= T_UNRESOLVED
;
584 if ((T2_nfails
== 0) && (T2_nprobs
== 0))
586 else if (T2_nfails
!= 0)
592 static const char *a2
= "The task subsystem can create ISC_TASKS_MIN tasks";
596 t_assert("tasks", 2, T_REQUIRED
, "%s", a2
);
599 t_result(t_tasks2());
604 #define T3_NEVENTS 256
607 static int T3_nevents
;
608 static int T3_nsdevents
;
609 static isc_mutex_t T3_mx
;
610 static isc_condition_t T3_cv
;
611 static int T3_nfails
;
612 static int T3_nprobs
;
615 t3_sde1(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
== 1) {
626 t_info("Shutdown events not processed in LIFO order\n");
629 isc_event_free(&event
);
633 t3_sde2(isc_task_t
*task
, isc_event_t
*event
) {
637 if (T3_nevents
!= T3_NEVENTS
) {
638 t_info("Some events were not processed\n");
641 if (T3_nsdevents
== 0) {
644 t_info("Shutdown events not processed in LIFO order\n");
647 isc_event_free(&event
);
651 t3_event1(isc_task_t
*task
, isc_event_t
*event
) {
652 isc_result_t isc_result
;
656 isc_result
= isc_mutex_lock(&T3_mx
);
657 if (isc_result
!= ISC_R_SUCCESS
) {
658 t_info("isc_mutex_lock failed %s\n",
659 isc_result_totext(isc_result
));
662 while (T3_flag
!= 1) {
663 (void) isc_condition_wait(&T3_cv
, &T3_mx
);
666 isc_result
= isc_mutex_unlock(&T3_mx
);
667 if (isc_result
!= ISC_R_SUCCESS
) {
668 t_info("isc_mutex_unlock failed %s\n",
669 isc_result_totext(isc_result
));
672 isc_event_free(&event
);
676 t3_event2(isc_task_t
*task
, isc_event_t
*event
) {
680 isc_event_free(&event
);
691 unsigned int workers
;
693 isc_result_t isc_result
;
694 isc_eventtype_t event_type
;
705 p
= t_getenv("ISC_TASK_WORKERS");
710 isc_result
= isc_mem_create(0, 0, &mctx
);
711 if (isc_result
!= ISC_R_SUCCESS
) {
712 t_info("isc_mem_create failed %s\n",
713 isc_result_totext(isc_result
));
714 return(T_UNRESOLVED
);
717 isc_result
= isc_mutex_init(&T3_mx
);
718 if (isc_result
!= ISC_R_SUCCESS
) {
719 t_info("isc_mutex_init failed %s\n",
720 isc_result_totext(isc_result
));
721 isc_mem_destroy(&mctx
);
722 return(T_UNRESOLVED
);
725 isc_result
= isc_condition_init(&T3_cv
);
726 if (isc_result
!= ISC_R_SUCCESS
) {
727 t_info("isc_condition_init failed %s\n",
728 isc_result_totext(isc_result
));
729 isc_mem_destroy(&mctx
);
730 return(T_UNRESOLVED
);
734 isc_result
= isc_taskmgr_create(mctx
, workers
, 0, &tmgr
);
735 if (isc_result
!= ISC_R_SUCCESS
) {
736 t_info("isc_taskmgr_create failed %s\n",
737 isc_result_totext(isc_result
));
738 isc_mem_destroy(&mctx
);
739 return(T_UNRESOLVED
);
742 isc_result
= isc_mutex_lock(&T3_mx
);
743 if (isc_result
!= ISC_R_SUCCESS
) {
744 t_info("isc_mutex_lock failed %s\n",
745 isc_result_totext(isc_result
));
746 isc_taskmgr_destroy(&tmgr
);
747 isc_mem_destroy(&mctx
);
748 return(T_UNRESOLVED
);
752 isc_result
= isc_task_create(tmgr
, 0, &task
);
753 if (isc_result
!= ISC_R_SUCCESS
) {
754 t_info("isc_task_create failed %s\n",
755 isc_result_totext(isc_result
));
756 (void) isc_mutex_unlock(&T3_mx
);
757 isc_taskmgr_destroy(&tmgr
);
758 isc_mem_destroy(&mctx
);
759 return(T_UNRESOLVED
);
763 * This event causes the task to wait on T3_cv.
765 event
= isc_event_allocate(mctx
, &senders
[1], event_type
, t3_event1
,
766 NULL
, sizeof(*event
));
768 t_info("isc_event_allocate failed\n");
769 (void) isc_mutex_unlock(&T3_mx
);
770 isc_task_destroy(&task
);
771 isc_taskmgr_destroy(&tmgr
);
772 isc_mem_destroy(&mctx
);
773 return(T_UNRESOLVED
);
775 isc_task_send(task
, &event
);
778 * Now we fill up the task's event queue with some events.
780 for (cnt
= 0; cnt
< T3_NEVENTS
; ++cnt
) {
781 event
= isc_event_allocate(mctx
, &senders
[1], event_type
,
782 t3_event2
, NULL
, sizeof(*event
));
784 t_info("isc_event_allocate failed\n");
785 (void) isc_mutex_unlock(&T3_mx
);
786 isc_task_destroy(&task
);
787 isc_taskmgr_destroy(&tmgr
);
788 isc_mem_destroy(&mctx
);
789 return(T_UNRESOLVED
);
791 isc_task_send(task
, &event
);
795 * Now we register two shutdown events.
797 isc_result
= isc_task_onshutdown(task
, t3_sde1
, NULL
);
798 if (isc_result
!= ISC_R_SUCCESS
) {
799 t_info("isc_task_send failed %s\n",
800 isc_result_totext(isc_result
));
801 (void) isc_mutex_unlock(&T3_mx
);
802 isc_task_destroy(&task
);
803 isc_taskmgr_destroy(&tmgr
);
804 isc_mem_destroy(&mctx
);
805 return(T_UNRESOLVED
);
808 isc_result
= isc_task_onshutdown(task
, t3_sde2
, NULL
);
809 if (isc_result
!= ISC_R_SUCCESS
) {
810 t_info("isc_task_send failed %s\n",
811 isc_result_totext(isc_result
));
812 (void) isc_mutex_unlock(&T3_mx
);
813 isc_task_destroy(&task
);
814 isc_taskmgr_destroy(&tmgr
);
815 isc_mem_destroy(&mctx
);
816 return(T_UNRESOLVED
);
819 isc_task_shutdown(task
);
822 * Now we free the task by signaling T3_cv.
825 isc_result
= isc_condition_signal(&T3_cv
);
826 if (isc_result
!= ISC_R_SUCCESS
) {
827 t_info("isc_condition_signal failed %s\n",
828 isc_result_totext(isc_result
));
832 isc_result
= isc_mutex_unlock(&T3_mx
);
833 if (isc_result
!= ISC_R_SUCCESS
) {
834 t_info("isc_mutex_unlock failed %s\n",
835 isc_result_totext(isc_result
));
840 isc_task_detach(&task
);
841 isc_taskmgr_destroy(&tmgr
);
842 isc_mem_destroy(&mctx
);
844 if (T3_nsdevents
!= 2) {
845 t_info("T3_nsdevents == %d, expected 2\n", T3_nsdevents
);
849 result
= T_UNRESOLVED
;
853 else if ((T3_nfails
== 0) && (T3_nprobs
== 0))
859 static const char *a3
= "When isc_task_shutdown() is called, any shutdown "
860 "events that have been requested via prior "
861 "isc_task_onshutdown() calls are posted in "
865 t_assert("tasks", 3, T_REQUIRED
, "%s", a3
);
868 t_result(t_tasks3());
873 static isc_mutex_t T4_mx
;
874 static isc_condition_t T4_cv
;
876 static int T4_nprobs
;
877 static int T4_nfails
;
880 t4_event1(isc_task_t
*task
, isc_event_t
*event
) {
881 isc_result_t isc_result
;
885 isc_result
= isc_mutex_lock(&T4_mx
);
886 if (isc_result
!= ISC_R_SUCCESS
) {
887 t_info("isc_mutex_lock failed %s\n",
888 isc_result_totext(isc_result
));
891 while (T4_flag
!= 1) {
892 (void) isc_condition_wait(&T4_cv
, &T4_mx
);
895 isc_result
= isc_mutex_unlock(&T4_mx
);
896 if (isc_result
!= ISC_R_SUCCESS
) {
897 t_info("isc_mutex_unlock failed %s\n",
898 isc_result_totext(isc_result
));
901 isc_event_free(&event
);
905 t4_sde(isc_task_t
*task
, isc_event_t
*event
) {
912 isc_event_free(&event
);
922 unsigned int workers
;
923 isc_result_t isc_result
;
924 isc_eventtype_t event_type
;
934 p
= t_getenv("ISC_TASK_WORKERS");
939 isc_result
= isc_mem_create(0, 0, &mctx
);
940 if (isc_result
!= ISC_R_SUCCESS
) {
941 t_info("isc_mem_create failed %s\n",
942 isc_result_totext(isc_result
));
943 return(T_UNRESOLVED
);
946 isc_result
= isc_mutex_init(&T4_mx
);
947 if (isc_result
!= ISC_R_SUCCESS
) {
948 t_info("isc_mutex_init failed %s\n",
949 isc_result_totext(isc_result
));
950 isc_mem_destroy(&mctx
);
951 return(T_UNRESOLVED
);
954 isc_result
= isc_condition_init(&T4_cv
);
955 if (isc_result
!= ISC_R_SUCCESS
) {
956 t_info("isc_condition_init failed %s\n",
957 isc_result_totext(isc_result
));
959 isc_mem_destroy(&mctx
);
960 return(T_UNRESOLVED
);
964 isc_result
= isc_taskmgr_create(mctx
, workers
, 0, &tmgr
);
965 if (isc_result
!= ISC_R_SUCCESS
) {
966 t_info("isc_taskmgr_create failed %s\n",
967 isc_result_totext(isc_result
));
969 (void) isc_condition_destroy(&T4_cv
);
970 isc_mem_destroy(&mctx
);
971 return(T_UNRESOLVED
);
974 isc_result
= isc_mutex_lock(&T4_mx
);
975 if (isc_result
!= ISC_R_SUCCESS
) {
976 t_info("isc_mutex_lock failed %s\n",
977 isc_result_totext(isc_result
));
979 (void) isc_condition_destroy(&T4_cv
);
980 isc_taskmgr_destroy(&tmgr
);
981 isc_mem_destroy(&mctx
);
982 return(T_UNRESOLVED
);
986 isc_result
= isc_task_create(tmgr
, 0, &task
);
987 if (isc_result
!= ISC_R_SUCCESS
) {
988 t_info("isc_task_create failed %s\n",
989 isc_result_totext(isc_result
));
991 (void) isc_condition_destroy(&T4_cv
);
992 isc_taskmgr_destroy(&tmgr
);
993 isc_mem_destroy(&mctx
);
994 return(T_UNRESOLVED
);
998 * This event causes the task to wait on T4_cv.
1000 event
= isc_event_allocate(mctx
, &senders
[1], event_type
, t4_event1
,
1001 NULL
, sizeof(*event
));
1002 if (event
== NULL
) {
1003 t_info("isc_event_allocate failed\n");
1004 DESTROYLOCK(&T4_mx
);
1005 isc_task_destroy(&task
);
1006 (void) isc_condition_destroy(&T4_cv
);
1007 isc_taskmgr_destroy(&tmgr
);
1008 isc_mem_destroy(&mctx
);
1009 return(T_UNRESOLVED
);
1011 isc_task_send(task
, &event
);
1013 isc_task_shutdown(task
);
1015 isc_result
= isc_task_onshutdown(task
, t4_sde
, NULL
);
1016 if (isc_result
!= ISC_R_SHUTTINGDOWN
) {
1017 t_info("isc_task_onshutdown returned %s\n",
1018 isc_result_totext(isc_result
));
1027 isc_result
= isc_condition_signal(&T4_cv
);
1028 if (isc_result
!= ISC_R_SUCCESS
) {
1029 t_info("isc_condition_signal failed %s\n",
1030 isc_result_totext(isc_result
));
1034 isc_result
= isc_mutex_unlock(&T4_mx
);
1035 if (isc_result
!= ISC_R_SUCCESS
) {
1036 t_info("isc_mutex_unlock failed %s\n",
1037 isc_result_totext(isc_result
));
1041 isc_task_detach(&task
);
1042 isc_taskmgr_destroy(&tmgr
);
1043 isc_mem_destroy(&mctx
);
1044 (void) isc_condition_destroy(&T4_cv
);
1045 DESTROYLOCK(&T4_mx
);
1047 result
= T_UNRESOLVED
;
1051 else if ((T4_nfails
== 0) && (T4_nprobs
== 0))
1057 static const char *a4
=
1058 "After isc_task_shutdown() has been called, any call to "
1059 "isc_task_onshutdown() will return ISC_R_SHUTTINGDOWN.";
1063 t_assert("tasks", 4, T_REQUIRED
, "%s", a4
);
1066 t_result(t_tasks4());
1071 static int T7_nprobs
;
1072 static int T7_eflag
;
1073 static int T7_sdflag
;
1074 static isc_mutex_t T7_mx
;
1075 static isc_condition_t T7_cv
;
1077 static int T7_nfails
;
1080 t7_event1(isc_task_t
*task
, isc_event_t
*event
) {
1085 isc_event_free(&event
);
1089 t7_sde(isc_task_t
*task
, isc_event_t
*event
) {
1090 isc_result_t isc_result
;
1094 isc_result
= isc_mutex_lock(&T7_mx
);
1095 if (isc_result
!= ISC_R_SUCCESS
) {
1096 t_info("isc_mutex_lock failed %s\n",
1097 isc_result_totext(isc_result
));
1103 isc_result
= isc_condition_signal(&T7_cv
);
1104 if (isc_result
!= ISC_R_SUCCESS
) {
1105 t_info("isc_condition_signal failed %s\n",
1106 isc_result_totext(isc_result
));
1110 isc_result
= isc_mutex_unlock(&T7_mx
);
1111 if (isc_result
!= ISC_R_SUCCESS
) {
1112 t_info("isc_mutex_unlock failed %s\n",
1113 isc_result_totext(isc_result
));
1117 isc_event_free(&event
);
1125 isc_taskmgr_t
*tmgr
;
1127 unsigned int workers
;
1128 isc_result_t isc_result
;
1129 isc_eventtype_t event_type
;
1132 isc_interval_t interval
;
1142 p
= t_getenv("ISC_TASK_WORKERS");
1147 isc_result
= isc_mem_create(0, 0, &mctx
);
1148 if (isc_result
!= ISC_R_SUCCESS
) {
1149 t_info("isc_mem_create failed %s\n",
1150 isc_result_totext(isc_result
));
1151 return(T_UNRESOLVED
);
1154 isc_result
= isc_mutex_init(&T7_mx
);
1155 if (isc_result
!= ISC_R_SUCCESS
) {
1156 t_info("isc_mutex_init failed %s\n",
1157 isc_result_totext(isc_result
));
1158 isc_mem_destroy(&mctx
);
1159 return(T_UNRESOLVED
);
1162 isc_result
= isc_condition_init(&T7_cv
);
1163 if (isc_result
!= ISC_R_SUCCESS
) {
1164 t_info("isc_condition_init failed %s\n",
1165 isc_result_totext(isc_result
));
1166 DESTROYLOCK(&T7_mx
);
1167 isc_mem_destroy(&mctx
);
1168 return(T_UNRESOLVED
);
1172 isc_result
= isc_taskmgr_create(mctx
, workers
, 0, &tmgr
);
1173 if (isc_result
!= ISC_R_SUCCESS
) {
1174 t_info("isc_taskmgr_create failed %s\n",
1175 isc_result_totext(isc_result
));
1176 DESTROYLOCK(&T7_mx
);
1177 (void) isc_condition_destroy(&T7_cv
);
1178 isc_mem_destroy(&mctx
);
1179 return(T_UNRESOLVED
);
1182 isc_result
= isc_mutex_lock(&T7_mx
);
1183 if (isc_result
!= ISC_R_SUCCESS
) {
1184 t_info("isc_mutex_lock failed %s\n",
1185 isc_result_totext(isc_result
));
1186 DESTROYLOCK(&T7_mx
);
1187 (void) isc_condition_destroy(&T7_cv
);
1188 isc_taskmgr_destroy(&tmgr
);
1189 isc_mem_destroy(&mctx
);
1194 isc_result
= isc_task_create(tmgr
, 0, &task
);
1195 if (isc_result
!= ISC_R_SUCCESS
) {
1196 t_info("isc_task_create failed %s\n",
1197 isc_result_totext(isc_result
));
1198 DESTROYLOCK(&T7_mx
);
1199 (void) isc_condition_destroy(&T7_cv
);
1200 isc_taskmgr_destroy(&tmgr
);
1201 isc_mem_destroy(&mctx
);
1205 isc_result
= isc_task_onshutdown(task
, t7_sde
, NULL
);
1206 if (isc_result
!= ISC_R_SUCCESS
) {
1207 t_info("isc_task_onshutdown returned %s\n",
1208 isc_result_totext(isc_result
));
1209 DESTROYLOCK(&T7_mx
);
1210 (void) isc_condition_destroy(&T7_cv
);
1211 isc_task_destroy(&task
);
1212 isc_taskmgr_destroy(&tmgr
);
1213 isc_mem_destroy(&mctx
);
1214 return(T_UNRESOLVED
);
1217 event
= isc_event_allocate(mctx
, &senders
[1], event_type
, t7_event1
,
1218 NULL
, sizeof(*event
));
1219 if (event
== NULL
) {
1220 t_info("isc_event_allocate failed\n");
1221 DESTROYLOCK(&T7_mx
);
1222 (void) isc_condition_destroy(&T7_cv
);
1223 isc_task_destroy(&task
);
1224 isc_taskmgr_destroy(&tmgr
);
1225 isc_mem_destroy(&mctx
);
1226 return(T_UNRESOLVED
);
1228 isc_task_send(task
, &event
);
1230 isc_task_shutdown(task
);
1232 isc_interval_set(&interval
, 5, 0);
1234 while (T7_sdflag
== 0) {
1235 isc_result
= isc_time_nowplusinterval(&now
, &interval
);
1236 if (isc_result
!= ISC_R_SUCCESS
) {
1237 t_info("isc_time_nowplusinterval failed %s\n",
1238 isc_result_totext(isc_result
));
1239 DESTROYLOCK(&T7_mx
);
1240 (void) isc_condition_destroy(&T7_cv
);
1241 isc_task_destroy(&task
);
1242 isc_taskmgr_destroy(&tmgr
);
1243 isc_mem_destroy(&mctx
);
1244 return(T_UNRESOLVED
);
1247 isc_result
= isc_condition_waituntil(&T7_cv
, &T7_mx
, &now
);
1248 if (isc_result
!= ISC_R_SUCCESS
) {
1249 t_info("isc_condition_waituntil returned %s\n",
1250 isc_result_totext(isc_result
));
1251 DESTROYLOCK(&T7_mx
);
1252 (void) isc_condition_destroy(&T7_cv
);
1253 isc_task_destroy(&task
);
1254 isc_taskmgr_destroy(&tmgr
);
1255 isc_mem_destroy(&mctx
);
1260 isc_result
= isc_mutex_unlock(&T7_mx
);
1261 if (isc_result
!= ISC_R_SUCCESS
) {
1262 t_info("isc_mutex_unlock failed %s\n",
1263 isc_result_totext(isc_result
));
1267 isc_task_detach(&task
);
1268 isc_taskmgr_destroy(&tmgr
);
1269 isc_mem_destroy(&mctx
);
1270 (void) isc_condition_destroy(&T7_cv
);
1271 DESTROYLOCK(&T7_mx
);
1273 result
= T_UNRESOLVED
;
1280 else if ((T7_nfails
== 0) && (T7_nprobs
== 0))
1286 static const char *a7
= "A call to isc_task_create() creates a task that can "
1291 t_assert("tasks", 7, T_REQUIRED
, "%s", a7
);
1294 t_result(t_tasks7());
1299 #define T10_SENDERCNT 3
1300 #define T10_TYPECNT 4
1301 #define T10_TAGCNT 5
1302 #define T10_NEVENTS (T10_SENDERCNT*T10_TYPECNT*T10_TAGCNT)
1303 #define T_CONTROL 99999
1305 static int T10_nprobs
;
1306 static int T10_nfails
;
1307 static int T10_startflag
;
1308 static int T10_shutdownflag
;
1309 static int T10_eventcnt
;
1310 static isc_mutex_t T10_mx
;
1311 static isc_condition_t T10_cv
;
1313 static void *T10_purge_sender
;
1314 static isc_eventtype_t T10_purge_type_first
;
1315 static isc_eventtype_t T10_purge_type_last
;
1316 static void *T10_purge_tag
;
1317 static int T10_testrange
;
1320 t10_event1(isc_task_t
*task
, isc_event_t
*event
) {
1321 isc_result_t isc_result
;
1325 isc_result
= isc_mutex_lock(&T10_mx
);
1326 if (isc_result
!= ISC_R_SUCCESS
) {
1327 t_info("isc_mutex_lock failed %s\n",
1328 isc_result_totext(isc_result
));
1332 while (T10_startflag
== 0) {
1333 isc_result
= isc_condition_wait(&T10_cv
, &T10_mx
);
1334 if (isc_result
!= ISC_R_SUCCESS
) {
1335 t_info("isc_mutex_lock failed %s\n",
1336 isc_result_totext(isc_result
));
1341 isc_result
= isc_mutex_unlock(&T10_mx
);
1342 if (isc_result
!= ISC_R_SUCCESS
) {
1343 t_info("isc_mutex_unlock failed %s\n",
1344 isc_result_totext(isc_result
));
1348 isc_event_free(&event
);
1352 t10_event2(isc_task_t
*task
, isc_event_t
*event
) {
1365 t_info("Event %p,%d,%p,%s\n",
1367 (int)event
->ev_type
,
1369 event
->ev_attributes
& ISC_EVENTATTR_NOPURGE
?
1373 if ((T10_purge_sender
== NULL
) ||
1374 (T10_purge_sender
== event
->ev_sender
)) {
1377 if (T10_testrange
== 0) {
1378 if (T10_purge_type_first
== event
->ev_type
) {
1382 if ((T10_purge_type_first
<= event
->ev_type
) &&
1383 (event
->ev_type
<= T10_purge_type_last
)) {
1387 if ((T10_purge_tag
== NULL
) ||
1388 (T10_purge_tag
== event
->ev_tag
)) {
1392 if (sender_match
&& type_match
&& tag_match
) {
1393 if (event
->ev_attributes
& ISC_EVENTATTR_NOPURGE
) {
1394 t_info("event %p,%d,%p matched but was not purgable\n",
1395 event
->ev_sender
, (int)event
->ev_type
,
1399 t_info("*** event %p,%d,%p not purged\n",
1400 event
->ev_sender
, (int)event
->ev_type
,
1406 isc_event_free(&event
);
1411 t10_sde(isc_task_t
*task
, isc_event_t
*event
) {
1412 isc_result_t isc_result
;
1416 isc_result
= isc_mutex_lock(&T10_mx
);
1417 if (isc_result
!= ISC_R_SUCCESS
) {
1418 t_info("isc_mutex_lock failed %s\n",
1419 isc_result_totext(isc_result
));
1425 isc_result
= isc_condition_signal(&T10_cv
);
1426 if (isc_result
!= ISC_R_SUCCESS
) {
1427 t_info("isc_condition_signal failed %s\n",
1428 isc_result_totext(isc_result
));
1432 isc_result
= isc_mutex_unlock(&T10_mx
);
1433 if (isc_result
!= ISC_R_SUCCESS
) {
1434 t_info("isc_mutex_unlock failed %s\n",
1435 isc_result_totext(isc_result
));
1439 isc_event_free(&event
);
1443 t_taskpurge_x(int sender
, int type
, int tag
, void *purge_sender
,
1444 int purge_type_first
, int purge_type_last
, void *purge_tag
,
1445 int exp_nevents
, int *nfails
, int *nprobs
, int testrange
)
1449 isc_taskmgr_t
*tmgr
;
1451 unsigned int workers
;
1452 isc_result_t isc_result
;
1455 isc_interval_t interval
;
1462 isc_event_t
*eventtab
[T10_NEVENTS
];
1466 T10_shutdownflag
= 0;
1468 T10_purge_sender
= purge_sender
;
1469 T10_purge_type_first
= (isc_eventtype_t
) purge_type_first
;
1470 T10_purge_type_last
= (isc_eventtype_t
) purge_type_last
;
1471 T10_purge_tag
= purge_tag
;
1472 T10_testrange
= testrange
;
1475 p
= t_getenv("ISC_TASK_WORKERS");
1480 isc_result
= isc_mem_create(0, 0, &mctx
);
1481 if (isc_result
!= ISC_R_SUCCESS
) {
1482 t_info("isc_mem_create failed %s\n",
1483 isc_result_totext(isc_result
));
1488 isc_result
= isc_mutex_init(&T10_mx
);
1489 if (isc_result
!= ISC_R_SUCCESS
) {
1490 t_info("isc_mutex_init failed %s\n",
1491 isc_result_totext(isc_result
));
1492 isc_mem_destroy(&mctx
);
1497 isc_result
= isc_condition_init(&T10_cv
);
1498 if (isc_result
!= ISC_R_SUCCESS
) {
1499 t_info("isc_condition_init failed %s\n",
1500 isc_result_totext(isc_result
));
1501 isc_mem_destroy(&mctx
);
1502 DESTROYLOCK(&T10_mx
);
1508 isc_result
= isc_taskmgr_create(mctx
, workers
, 0, &tmgr
);
1509 if (isc_result
!= ISC_R_SUCCESS
) {
1510 t_info("isc_taskmgr_create failed %s\n",
1511 isc_result_totext(isc_result
));
1512 isc_mem_destroy(&mctx
);
1513 DESTROYLOCK(&T10_mx
);
1514 (void) isc_condition_destroy(&T10_cv
);
1520 isc_result
= isc_task_create(tmgr
, 0, &task
);
1521 if (isc_result
!= ISC_R_SUCCESS
) {
1522 t_info("isc_task_create failed %s\n",
1523 isc_result_totext(isc_result
));
1524 isc_taskmgr_destroy(&tmgr
);
1525 isc_mem_destroy(&mctx
);
1526 DESTROYLOCK(&T10_mx
);
1527 (void) isc_condition_destroy(&T10_cv
);
1532 isc_result
= isc_task_onshutdown(task
, t10_sde
, NULL
);
1533 if (isc_result
!= ISC_R_SUCCESS
) {
1534 t_info("isc_task_onshutdown returned %s\n",
1535 isc_result_totext(isc_result
));
1536 isc_task_destroy(&task
);
1537 isc_taskmgr_destroy(&tmgr
);
1538 isc_mem_destroy(&mctx
);
1539 DESTROYLOCK(&T10_mx
);
1540 (void) isc_condition_destroy(&T10_cv
);
1546 * Block the task on T10_cv.
1548 event
= isc_event_allocate(mctx
, (void *)1, (isc_eventtype_t
)T_CONTROL
,
1549 t10_event1
, NULL
, sizeof(*event
));
1551 if (event
== NULL
) {
1552 t_info("isc_event_allocate failed\n");
1553 isc_task_destroy(&task
);
1554 isc_taskmgr_destroy(&tmgr
);
1555 isc_mem_destroy(&mctx
);
1556 DESTROYLOCK(&T10_mx
);
1557 (void) isc_condition_destroy(&T10_cv
);
1561 isc_task_send(task
, &event
);
1564 * Fill the task's queue with some messages with varying
1565 * sender, type, tag, and purgable attribute values.
1569 for (sender_cnt
= 0; sender_cnt
< T10_SENDERCNT
; ++sender_cnt
) {
1570 for (type_cnt
= 0; type_cnt
< T10_TYPECNT
; ++type_cnt
) {
1571 for (tag_cnt
= 0; tag_cnt
< T10_TAGCNT
; ++tag_cnt
) {
1572 eventtab
[event_cnt
] =
1573 isc_event_allocate(mctx
,
1574 &senders
[sender
+ sender_cnt
],
1575 (isc_eventtype_t
)(type
+ type_cnt
),
1576 t10_event2
, NULL
, sizeof(*event
));
1578 if (eventtab
[event_cnt
] == NULL
) {
1579 t_info("isc_event_allocate failed\n");
1580 isc_task_destroy(&task
);
1581 isc_taskmgr_destroy(&tmgr
);
1582 isc_mem_destroy(&mctx
);
1583 DESTROYLOCK(&T10_mx
);
1584 (void) isc_condition_destroy(&T10_cv
);
1589 eventtab
[event_cnt
]->ev_tag
=
1590 (void *)((uintptr_t)tag
+ tag_cnt
);
1593 * Make all odd message non-purgable.
1595 if ((sender_cnt
% 2) && (type_cnt
%2) &&
1597 eventtab
[event_cnt
]->ev_attributes
|=
1598 ISC_EVENTATTR_NOPURGE
;
1604 for (cnt
= 0; cnt
< event_cnt
; ++cnt
)
1605 isc_task_send(task
, &eventtab
[cnt
]);
1608 t_info("%d events queued\n", cnt
);
1610 if (testrange
== 0) {
1612 * We're testing isc_task_purge.
1614 nevents
= isc_task_purge(task
, purge_sender
,
1615 (isc_eventtype_t
)purge_type_first
,
1617 if (nevents
!= exp_nevents
) {
1618 t_info("*** isc_task_purge returned %d, expected %d\n",
1619 nevents
, exp_nevents
);
1622 t_info("isc_task_purge returned %d\n", nevents
);
1625 * We're testing isc_task_purgerange.
1627 nevents
= isc_task_purgerange(task
, purge_sender
,
1628 (isc_eventtype_t
)purge_type_first
,
1629 (isc_eventtype_t
)purge_type_last
,
1631 if (nevents
!= exp_nevents
) {
1632 t_info("*** isc_task_purgerange returned %d, "
1633 "expected %d\n", nevents
, exp_nevents
);
1636 t_info("isc_task_purgerange returned %d\n", nevents
);
1639 isc_result
= isc_mutex_lock(&T10_mx
);
1640 if (isc_result
!= ISC_R_SUCCESS
) {
1641 t_info("isc_mutex_lock failed %s\n",
1642 isc_result_totext(isc_result
));
1643 isc_task_destroy(&task
);
1644 isc_taskmgr_destroy(&tmgr
);
1645 isc_mem_destroy(&mctx
);
1646 DESTROYLOCK(&T10_mx
);
1647 (void) isc_condition_destroy(&T10_cv
);
1653 * Unblock the task, allowing event processing.
1656 isc_result
= isc_condition_signal(&T10_cv
);
1657 if (isc_result
!= ISC_R_SUCCESS
) {
1658 t_info("isc_condition_signal failed %s\n",
1659 isc_result_totext(isc_result
));
1663 isc_task_shutdown(task
);
1665 isc_interval_set(&interval
, 5, 0);
1668 * Wait for shutdown processing to complete.
1670 while (T10_shutdownflag
== 0) {
1671 isc_result
= isc_time_nowplusinterval(&now
, &interval
);
1672 if (isc_result
!= ISC_R_SUCCESS
) {
1673 t_info("isc_time_nowplusinterval failed %s\n",
1674 isc_result_totext(isc_result
));
1675 isc_task_detach(&task
);
1676 isc_taskmgr_destroy(&tmgr
);
1677 isc_mem_destroy(&mctx
);
1678 DESTROYLOCK(&T10_mx
);
1679 (void) isc_condition_destroy(&T10_cv
);
1684 isc_result
= isc_condition_waituntil(&T10_cv
, &T10_mx
, &now
);
1685 if (isc_result
!= ISC_R_SUCCESS
) {
1686 t_info("isc_condition_waituntil returned %s\n",
1687 isc_result_totext(isc_result
));
1688 isc_task_detach(&task
);
1689 isc_taskmgr_destroy(&tmgr
);
1690 isc_mem_destroy(&mctx
);
1691 DESTROYLOCK(&T10_mx
);
1692 (void) isc_condition_destroy(&T10_cv
);
1698 isc_result
= isc_mutex_unlock(&T10_mx
);
1699 if (isc_result
!= ISC_R_SUCCESS
) {
1700 t_info("isc_mutex_unlock failed %s\n",
1701 isc_result_totext(isc_result
));
1705 isc_task_detach(&task
);
1706 isc_taskmgr_destroy(&tmgr
);
1707 isc_mem_destroy(&mctx
);
1708 DESTROYLOCK(&T10_mx
);
1709 (void) isc_condition_destroy(&T10_cv
);
1712 t_info("task processed %d events\n", T10_eventcnt
);
1714 if ((T10_eventcnt
+ nevents
) != event_cnt
) {
1715 t_info("*** processed %d, purged %d, total %d\n",
1716 T10_eventcnt
, nevents
, event_cnt
);
1729 * Try purging on a specific sender.
1731 t_info("testing purge on 2,4,8 expecting 1\n");
1732 t_taskpurge_x(1, 4, 7, &senders
[2], 4, 4, (void *)8, 1, &T10_nfails
,
1736 * Try purging on all senders.
1738 t_info("testing purge on 0,4,8 expecting 3\n");
1739 t_taskpurge_x(1, 4, 7, NULL
, 4, 4, (void *)8, 3, &T10_nfails
,
1743 * Try purging on all senders, specified type, all tags.
1745 t_info("testing purge on 0,4,0 expecting 15\n");
1746 t_taskpurge_x(1, 4, 7, NULL
, 4, 4, NULL
, 15, &T10_nfails
,
1750 * Try purging on a specified tag, no such type.
1752 t_info("testing purge on 0,99,8 expecting 0\n");
1753 t_taskpurge_x(1, 4, 7, NULL
, 99, 99, (void *)8, 0, &T10_nfails
,
1757 * Try purging on specified sender, type, all tags.
1759 t_info("testing purge on 0,5,0 expecting 5\n");
1760 t_taskpurge_x(1, 4, 7, &senders
[3], 5, 5, NULL
, 5, &T10_nfails
,
1763 result
= T_UNRESOLVED
;
1765 if ((T10_nfails
== 0) && (T10_nprobs
== 0))
1767 else if (T10_nfails
!= 0)
1773 static const char *a10
=
1774 "A call to isc_task_purge(task, sender, type, tag) "
1775 "purges all events of type 'type' and with tag 'tag' "
1776 "not marked as unpurgable from sender from the task's "
1777 "queue and returns the number of events purged.";
1781 t_assert("tasks", 10, T_REQUIRED
, "%s", a10
);
1784 t_result(t_tasks10());
1789 static int T11_nprobs
;
1790 static int T11_nfails
;
1791 static int T11_startflag
;
1792 static int T11_shutdownflag
;
1793 static int T11_eventcnt
;
1794 static isc_mutex_t T11_mx
;
1795 static isc_condition_t T11_cv
;
1798 t11_event1(isc_task_t
*task
, isc_event_t
*event
) {
1799 isc_result_t isc_result
;
1803 isc_result
= isc_mutex_lock(&T11_mx
);
1804 if (isc_result
!= ISC_R_SUCCESS
) {
1805 t_info("isc_mutex_lock failed %s\n",
1806 isc_result_totext(isc_result
));
1810 while (T11_startflag
== 0) {
1811 isc_result
= isc_condition_wait(&T11_cv
, &T11_mx
);
1812 if (isc_result
!= ISC_R_SUCCESS
) {
1813 t_info("isc_mutex_lock failed %s\n",
1814 isc_result_totext(isc_result
));
1819 isc_result
= isc_mutex_unlock(&T11_mx
);
1820 if (isc_result
!= ISC_R_SUCCESS
) {
1821 t_info("isc_mutex_unlock failed %s\n",
1822 isc_result_totext(isc_result
));
1826 isc_event_free(&event
);
1830 t11_event2(isc_task_t
*task
, isc_event_t
*event
) {
1834 isc_event_free(&event
);
1839 t11_sde(isc_task_t
*task
, isc_event_t
*event
) {
1840 isc_result_t isc_result
;
1844 isc_result
= isc_mutex_lock(&T11_mx
);
1845 if (isc_result
!= ISC_R_SUCCESS
) {
1846 t_info("isc_mutex_lock failed %s\n",
1847 isc_result_totext(isc_result
));
1853 isc_result
= isc_condition_signal(&T11_cv
);
1854 if (isc_result
!= ISC_R_SUCCESS
) {
1855 t_info("isc_condition_signal failed %s\n",
1856 isc_result_totext(isc_result
));
1860 isc_result
= isc_mutex_unlock(&T11_mx
);
1861 if (isc_result
!= ISC_R_SUCCESS
) {
1862 t_info("isc_mutex_unlock failed %s\n",
1863 isc_result_totext(isc_result
));
1867 isc_event_free(&event
);
1871 t_tasks11(int purgable
) {
1874 isc_taskmgr_t
*tmgr
;
1877 unsigned int workers
;
1878 isc_result_t isc_result
;
1879 isc_event_t
*event1
;
1880 isc_event_t
*event2
, *event2_clone
;
1882 isc_interval_t interval
;
1886 T11_shutdownflag
= 0;
1890 p
= t_getenv("ISC_TASK_WORKERS");
1895 isc_result
= isc_mem_create(0, 0, &mctx
);
1896 if (isc_result
!= ISC_R_SUCCESS
) {
1897 t_info("isc_mem_create failed %s\n",
1898 isc_result_totext(isc_result
));
1899 return(T_UNRESOLVED
);
1902 isc_result
= isc_mutex_init(&T11_mx
);
1903 if (isc_result
!= ISC_R_SUCCESS
) {
1904 t_info("isc_mutex_init failed %s\n",
1905 isc_result_totext(isc_result
));
1906 isc_mem_destroy(&mctx
);
1907 return(T_UNRESOLVED
);
1910 isc_result
= isc_condition_init(&T11_cv
);
1911 if (isc_result
!= ISC_R_SUCCESS
) {
1912 t_info("isc_condition_init failed %s\n",
1913 isc_result_totext(isc_result
));
1914 isc_mem_destroy(&mctx
);
1915 DESTROYLOCK(&T11_mx
);
1916 return(T_UNRESOLVED
);
1920 isc_result
= isc_taskmgr_create(mctx
, workers
, 0, &tmgr
);
1921 if (isc_result
!= ISC_R_SUCCESS
) {
1922 t_info("isc_taskmgr_create failed %s\n",
1923 isc_result_totext(isc_result
));
1924 isc_mem_destroy(&mctx
);
1925 DESTROYLOCK(&T11_mx
);
1926 (void) isc_condition_destroy(&T11_cv
);
1927 return(T_UNRESOLVED
);
1931 isc_result
= isc_task_create(tmgr
, 0, &task
);
1932 if (isc_result
!= ISC_R_SUCCESS
) {
1933 t_info("isc_task_create failed %s\n",
1934 isc_result_totext(isc_result
));
1935 isc_taskmgr_destroy(&tmgr
);
1936 isc_mem_destroy(&mctx
);
1937 DESTROYLOCK(&T11_mx
);
1938 (void) isc_condition_destroy(&T11_cv
);
1939 return(T_UNRESOLVED
);
1942 isc_result
= isc_task_onshutdown(task
, t11_sde
, NULL
);
1943 if (isc_result
!= ISC_R_SUCCESS
) {
1944 t_info("isc_task_onshutdown returned %s\n",
1945 isc_result_totext(isc_result
));
1946 isc_task_destroy(&task
);
1947 isc_taskmgr_destroy(&tmgr
);
1948 isc_mem_destroy(&mctx
);
1949 DESTROYLOCK(&T11_mx
);
1950 (void) isc_condition_destroy(&T11_cv
);
1951 return(T_UNRESOLVED
);
1955 * Block the task on T11_cv.
1957 event1
= isc_event_allocate(mctx
, (void *)1, (isc_eventtype_t
)1,
1958 t11_event1
, NULL
, sizeof(*event1
));
1959 if (event1
== NULL
) {
1960 t_info("isc_event_allocate failed\n");
1961 isc_task_destroy(&task
);
1962 isc_taskmgr_destroy(&tmgr
);
1963 isc_mem_destroy(&mctx
);
1964 DESTROYLOCK(&T11_mx
);
1965 (void) isc_condition_destroy(&T11_cv
);
1966 return(T_UNRESOLVED
);
1968 isc_task_send(task
, &event1
);
1970 event2
= isc_event_allocate(mctx
, (void *)1, (isc_eventtype_t
)1,
1971 t11_event2
, NULL
, sizeof(*event2
));
1972 if (event2
== NULL
) {
1973 t_info("isc_event_allocate failed\n");
1974 isc_task_destroy(&task
);
1975 isc_taskmgr_destroy(&tmgr
);
1976 isc_mem_destroy(&mctx
);
1977 DESTROYLOCK(&T11_mx
);
1978 (void) isc_condition_destroy(&T11_cv
);
1979 return(T_UNRESOLVED
);
1981 event2_clone
= event2
;
1983 event2
->ev_attributes
&= ~ISC_EVENTATTR_NOPURGE
;
1985 event2
->ev_attributes
|= ISC_EVENTATTR_NOPURGE
;
1987 isc_task_send(task
, &event2
);
1989 rval
= isc_task_purgeevent(task
, event2_clone
);
1990 if (rval
!= (purgable
? ISC_TRUE
: ISC_FALSE
)) {
1991 t_info("isc_task_purgeevent returned %s, expected %s\n",
1992 (rval
? "ISC_TRUE" : "ISC_FALSE"),
1993 (purgable
? "ISC_TRUE" : "ISC_FALSE"));
1997 isc_result
= isc_mutex_lock(&T11_mx
);
1998 if (isc_result
!= ISC_R_SUCCESS
) {
1999 t_info("isc_mutex_lock failed %s\n",
2000 isc_result_totext(isc_result
));
2005 * Unblock the task, allowing event processing.
2008 isc_result
= isc_condition_signal(&T11_cv
);
2009 if (isc_result
!= ISC_R_SUCCESS
) {
2010 t_info("isc_condition_signal failed %s\n",
2011 isc_result_totext(isc_result
));
2015 isc_task_shutdown(task
);
2017 isc_interval_set(&interval
, 5, 0);
2020 * Wait for shutdown processing to complete.
2022 while (T11_shutdownflag
== 0) {
2023 isc_result
= isc_time_nowplusinterval(&now
, &interval
);
2024 if (isc_result
!= ISC_R_SUCCESS
) {
2025 t_info("isc_time_nowplusinterval failed %s\n",
2026 isc_result_totext(isc_result
));
2030 isc_result
= isc_condition_waituntil(&T11_cv
, &T11_mx
, &now
);
2031 if (isc_result
!= ISC_R_SUCCESS
) {
2032 t_info("isc_condition_waituntil returned %s\n",
2033 isc_result_totext(isc_result
));
2038 isc_result
= isc_mutex_unlock(&T11_mx
);
2039 if (isc_result
!= ISC_R_SUCCESS
) {
2040 t_info("isc_mutex_unlock failed %s\n",
2041 isc_result_totext(isc_result
));
2045 isc_task_detach(&task
);
2046 isc_taskmgr_destroy(&tmgr
);
2047 isc_mem_destroy(&mctx
);
2048 DESTROYLOCK(&T11_mx
);
2049 (void) isc_condition_destroy(&T11_cv
);
2051 if (T11_eventcnt
!= (purgable
? 0 : 1)) {
2052 t_info("Event was %s purged\n",
2053 (purgable
? "not" : "unexpectedly"));
2057 result
= T_UNRESOLVED
;
2059 if ((T11_nfails
== 0) && (T11_nprobs
== 0))
2061 else if (T11_nfails
)
2067 static const char *a11
=
2068 "When the event is marked as purgable, a call to "
2069 "isc_task_purgeevent(task, event) purges the event 'event' "
2070 "from the task's queue and returns ISC_TRUE.";
2074 t_assert("tasks", 11, T_REQUIRED
, "%s", a11
);
2077 t_result(t_tasks11(1));
2082 static const char *a12
=
2083 "When the event is not marked as purgable, a call to "
2084 "isc_task_purgeevent(task, event) does not purge the "
2085 "event 'event' from the task's queue and returns "
2090 return(t_tasks11(0));
2095 t_assert("tasks", 12, T_REQUIRED
, "%s", a12
);
2098 t_result(t_tasks12());
2103 static int T13_nfails
;
2104 static int T13_nprobs
;
2106 static const char *a13
=
2108 "isc_event_purgerange(task, sender, first, last, tag) "
2109 "purges all events not marked unpurgable from "
2110 "sender 'sender' and of type within the range 'first' "
2111 "to 'last' inclusive from the task's event queue and "
2112 "returns the number of tasks purged.";
2122 * First let's try the same cases we used in t10.
2126 * Try purging on a specific sender.
2128 t_info("testing purge on 2,4,8 expecting 1\n");
2129 t_taskpurge_x(1, 4, 7, &senders
[2], 4, 4, (void *)8, 1,
2130 &T13_nfails
, &T13_nprobs
, 1);
2133 * Try purging on all senders.
2135 t_info("testing purge on 0,4,8 expecting 3\n");
2136 t_taskpurge_x(1, 4, 7, NULL
, 4, 4, (void *)8, 3,
2137 &T13_nfails
, &T13_nprobs
, 1);
2140 * Try purging on all senders, specified type, all tags.
2142 t_info("testing purge on 0,4,0 expecting 15\n");
2143 t_taskpurge_x(1, 4, 7, NULL
, 4, 4, NULL
, 15, &T13_nfails
, &T13_nprobs
, 1);
2146 * Try purging on a specified tag, no such type.
2148 t_info("testing purge on 0,99,8 expecting 0\n");
2149 t_taskpurge_x(1, 4, 7, NULL
, 99, 99, (void *)8, 0,
2150 &T13_nfails
, &T13_nprobs
, 1);
2153 * Try purging on specified sender, type, all tags.
2155 t_info("testing purge on 3,5,0 expecting 5\n");
2156 t_taskpurge_x(1, 4, 7, &senders
[3], 5, 5, 0, 5, &T13_nfails
, &T13_nprobs
, 1);
2159 * Now let's try some ranges.
2162 t_info("testing purgerange on 2,4-5,8 expecting 2\n");
2163 t_taskpurge_x(1, 4, 7, &senders
[2], 4, 5, (void *)8, 1,
2164 &T13_nfails
, &T13_nprobs
, 1);
2167 * Try purging on all senders.
2169 t_info("testing purge on 0,4-5,8 expecting 5\n");
2170 t_taskpurge_x(1, 4, 7, NULL
, 4, 5, (void *)8, 5,
2171 &T13_nfails
, &T13_nprobs
, 1);
2174 * Try purging on all senders, specified type, all tags.
2176 t_info("testing purge on 0,5-6,0 expecting 28\n");
2177 t_taskpurge_x(1, 4, 7, NULL
, 5, 6, NULL
, 28, &T13_nfails
, &T13_nprobs
, 1);
2180 * Try purging on a specified tag, no such type.
2182 t_info("testing purge on 0,99-101,8 expecting 0\n");
2183 t_taskpurge_x(1, 4, 7, NULL
, 99, 101, (void *)8, 0,
2184 &T13_nfails
, &T13_nprobs
, 1);
2187 * Try purging on specified sender, type, all tags.
2189 t_info("testing purge on 3,5-6,0 expecting 10\n");
2190 t_taskpurge_x(1, 4, 7, &senders
[3], 5, 6, NULL
, 10, &T13_nfails
,
2193 result
= T_UNRESOLVED
;
2195 if ((T13_nfails
== 0) && (T13_nprobs
== 0))
2197 else if (T13_nfails
)
2205 t_assert("tasks", 13, T_REQUIRED
, "%s", a13
);
2208 t_result(t_tasks13());
2213 #define T14_NTASKS 10
2214 #define T14_EXCLTASK 6
2216 int t14_exclusiveerror
= ISC_R_SUCCESS
;
2222 int t14_active
[T14_NTASKS
];
2225 t14_callback(isc_task_t
*task
, isc_event_t
*event
) {
2226 int taskno
= *(int *)(event
->ev_arg
);
2229 t_info("task enter %d\n", taskno
);
2230 if (taskno
== T14_EXCLTASK
) {
2232 t14_exclusiveerror
= isc_task_beginexclusive(task
);
2233 if (t14_exclusiveerror
== ISC_R_SUCCESS
)
2234 t_info("task %d got exclusive access\n", taskno
);
2236 t_info("task %d failed to got exclusive access: %d\n",
2237 taskno
, t14_exclusiveerror
);
2238 for (i
= 0; i
< T14_NTASKS
; i
++) {
2239 t_info("task %d state %d\n", i
, t14_active
[i
]);
2243 isc_task_endexclusive(task
);
2246 t14_active
[taskno
]++;
2247 (void) spin(10000000);
2248 t14_active
[taskno
]--;
2250 t_info("task exit %d\n", taskno
);
2252 isc_mem_put(event
->ev_destroy_arg
, event
->ev_arg
, sizeof (int));
2253 isc_event_free(&event
);
2255 isc_task_send(task
, &event
);
2262 for (i
= 0; i
< n
; i
++) {
2274 isc_taskmgr_t
*manager
;
2275 isc_task_t
*tasks
[T14_NTASKS
];
2276 unsigned int workers
;
2277 isc_result_t isc_result
;
2283 for (i
= 0; i
< T14_NTASKS
; i
++)
2287 p
= t_getenv("ISC_TASK_WORKERS");
2291 t_info("Bad config value for ISC_TASK_WORKERS, %d\n", workers
);
2292 return(T_UNRESOLVED
);
2295 isc_result
= isc_mem_create(0, 0, &mctx
);
2296 if (isc_result
!= ISC_R_SUCCESS
) {
2297 t_info("isc_mem_create failed %d\n", isc_result
);
2298 return(T_UNRESOLVED
);
2301 isc_result
= isc_taskmgr_create(mctx
, workers
, 0, &manager
);
2302 if (isc_result
!= ISC_R_SUCCESS
) {
2303 t_info("isc_taskmgr_create failed %d\n", isc_result
);
2307 for (i
= 0; i
< T14_NTASKS
; i
++) {
2311 isc_result
= isc_task_create(manager
, 0, &tasks
[i
]);
2312 if (isc_result
!= ISC_R_SUCCESS
) {
2313 t_info("isc_task_create failed %d\n", isc_result
);
2317 v
= isc_mem_get(mctx
, sizeof *v
);
2319 isc_task_detach(&tasks
[i
]);
2320 t_info("isc_mem_get failed\n");
2325 event
= isc_event_allocate(mctx
, NULL
, 1, t14_callback
,
2327 if (event
== NULL
) {
2328 isc_mem_put(mctx
, v
, sizeof *v
);
2329 t_info("isc_event_allocate failed\n");
2330 return(T_UNRESOLVED
);
2332 isc_task_send(tasks
[i
], &event
);
2335 for (i
= 0; i
< T14_NTASKS
; i
++) {
2336 isc_task_detach(&tasks
[i
]);
2339 isc_taskmgr_destroy(&manager
);
2341 if (t14_exclusiveerror
!= ISC_R_SUCCESS
|| t14_error
) {
2342 if (t14_exclusiveerror
!= ISC_R_SUCCESS
)
2343 t_info("isc_task_beginexclusive() failed\n");
2345 t_info("mutual access occurred\n");
2349 isc_mem_destroy(&mctx
);
2357 t_assert("tasks", 14, T_REQUIRED
, "%s",
2358 "isc_task_beginexclusive() gets exclusive access");
2359 result
= t_tasks14();
2363 testspec_t T_testlist
[] = {
2364 { (PFV
) t1
, "basic task subsystem" },
2365 { (PFV
) t2
, "maxtasks" },
2366 { (PFV
) t3
, "isc_task_shutdown" },
2367 { (PFV
) t4
, "isc_task_shutdown" },
2368 { (PFV
) t7
, "isc_task_create" },
2369 { (PFV
) t10
, "isc_task_purge" },
2370 { (PFV
) t11
, "isc_task_purgeevent" },
2371 { (PFV
) t12
, "isc_task_purgeevent" },
2372 { (PFV
) t13
, "isc_task_purgerange" },
2373 { (PFV
) t14
, "isc_task_beginexclusive" },
2379 main(int argc
, char **argv
) {
2380 t_settests(T_testlist
);
2381 return (t_main(argc
, argv
));