etc/services - sync with NetBSD-8
[minix.git] / external / bsd / bind / dist / bin / tests / tasks / t_tasks.c
blob08cac35b7dc512fedbb6119b36ae74715d7bcd75
1 /* $NetBSD: t_tasks.c,v 1.7 2014/12/10 04:37:54 christos Exp $ */
3 /*
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 */
22 #include <config.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26 #ifdef HAVE_INTTYPES_H
27 #include <inttypes.h> /* uintptr_t */
28 #endif
29 #include <isc/condition.h>
30 #include <isc/mem.h>
31 #include <isc/platform.h>
32 #include <isc/task.h>
33 #include <isc/time.h>
34 #include <isc/timer.h>
35 #include <isc/util.h>
37 #include <tests/t_api.h>
40 #ifdef ISC_PLATFORM_USETHREADS
41 isc_boolean_t threaded = ISC_TRUE;
42 #else
43 isc_boolean_t threaded = ISC_FALSE;
44 #endif
46 static int senders[4];
48 static void
49 require_threads(void) {
50 t_info("This test requires threads\n");
51 t_result(T_THREADONLY);
52 return;
55 static void
56 t1_callback(isc_task_t *task, isc_event_t *event) {
57 int i;
58 int j;
60 UNUSED(task);
62 j = 0;
64 for (i = 0; i < 1000000; i++)
65 j += 100;
67 t_info("task %s\n", (char *)event->ev_arg);
68 isc_event_free(&event);
71 static void
72 t1_shutdown(isc_task_t *task, isc_event_t *event) {
74 UNUSED(task);
76 t_info("shutdown %s\n", (char *)event->ev_arg);
77 isc_event_free(&event);
80 static void
81 my_tick(isc_task_t *task, isc_event_t *event) {
83 UNUSED(task);
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";
100 static int
101 t_tasks1(void) {
102 char *p;
103 isc_mem_t *mctx;
104 isc_taskmgr_t *manager;
105 isc_task_t *task1;
106 isc_task_t *task2;
107 isc_task_t *task3;
108 isc_task_t *task4;
109 isc_event_t *event;
110 unsigned int workers;
111 isc_timermgr_t *timgr;
112 isc_timer_t *ti1;
113 isc_timer_t *ti2;
114 isc_result_t isc_result;
115 isc_time_t absolute;
116 isc_interval_t interval;
118 manager = NULL;
119 task1 = NULL;
120 task2 = NULL;
121 task3 = NULL;
122 task4 = NULL;
123 mctx = NULL;
125 workers = 2;
126 p = t_getenv("ISC_TASK_WORKERS");
127 if (p != NULL)
128 workers = atoi(p);
129 if (workers < 1) {
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);
143 return(T_FAIL);
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);
149 return(T_FAIL);
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);
155 return(T_FAIL);
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);
161 return(T_FAIL);
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);
167 return(T_FAIL);
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);
173 return(T_FAIL);
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);
179 return(T_FAIL);
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);
185 return(T_FAIL);
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);
191 return(T_FAIL);
194 timgr = NULL;
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);
201 ti1 = NULL;
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);
212 ti2 = NULL;
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);
224 #ifndef WIN32
225 sleep(2);
226 #else
227 Sleep(2000);
228 #endif
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
236 * program.
238 event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, one,
239 sizeof(*event));
240 if (event == NULL) {
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,
248 sizeof(*event));
249 if (event == NULL) {
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,
257 sizeof(*event));
258 if (event == NULL) {
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,
266 sizeof(*event));
267 if (event == NULL) {
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,
275 sizeof(*event));
276 if (event == NULL) {
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,
284 sizeof(*event));
285 if (event == NULL) {
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,
293 sizeof(*event));
294 if (event == NULL) {
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,
302 sizeof(*event));
303 if (event == NULL) {
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,
311 sizeof(*event));
312 if (event == NULL) {
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,
320 sizeof(*event));
321 if (event == NULL) {
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,
329 sizeof(*event));
330 if (event == NULL) {
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,
338 sizeof(*event));
339 if (event == NULL) {
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,
347 sizeof(*event));
348 if (event == NULL) {
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,
356 sizeof(*event));
357 if (event == NULL) {
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,
365 sizeof(*event));
366 if (event == NULL) {
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);
380 #ifndef WIN32
381 sleep(10);
382 #else
383 Sleep(10000);
384 #endif
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);
391 return(T_PASS);
394 static const char *a1 = "The task subsystem can create and manage tasks";
396 static void
397 t1(void) {
398 int result;
400 t_assert("tasks", 1, T_REQUIRED, "%s", a1);
401 result = t_tasks1();
402 t_result(result);
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;
412 static int T2_done;
413 static int T2_nprobs;
414 static int T2_nfails;
415 static int T2_ntasks;
417 static void
418 t2_shutdown(isc_task_t *task, isc_event_t *event) {
420 isc_result_t isc_result;
422 UNUSED(task);
424 if (event->ev_arg != NULL) {
425 isc_task_destroy((isc_task_t**) &event->ev_arg);
427 else {
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);
431 ++T2_nprobs;
434 T2_done = 1;
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);
439 ++T2_nprobs;
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);
445 ++T2_nprobs;
448 isc_event_free(&T2_event);
449 isc_taskmgr_destroy(&T2_manager);
450 isc_mem_destroy(&T2_mctx);
454 static void
455 t2_callback(isc_task_t *task, isc_event_t *event) {
456 isc_result_t isc_result;
457 isc_task_t *newtask;
459 ++T2_ntasks;
461 if (T_debug && ((T2_ntasks % 100) == 0)) {
462 t_info("T2_ntasks %d\n", T2_ntasks);
465 if (event->ev_arg) {
467 event->ev_arg = (void *)(((uintptr_t) event->ev_arg) - 1);
470 * Create a new task and forward the message.
472 newtask = NULL;
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);
476 ++T2_nfails;
477 return;
480 isc_result = isc_task_onshutdown(newtask, t2_shutdown,
481 (void *)task);
482 if (isc_result != ISC_R_SUCCESS) {
483 t_info("isc_task_onshutdown failed %d\n",
484 isc_result);
485 ++T2_nfails;
486 return;
489 isc_task_send(newtask, &event);
490 } else {
492 * Time to unwind, shutdown should perc back up.
494 isc_task_destroy(&task);
498 static int
499 t_tasks2(void) {
500 uintptr_t ntasks;
501 int result;
502 char *p;
503 isc_event_t *event;
504 unsigned int workers;
505 isc_result_t isc_result;
507 T2_manager = NULL;
508 T2_done = 0;
509 T2_nprobs = 0;
510 T2_nfails = 0;
511 T2_ntasks = 0;
513 workers = 2;
514 p = t_getenv("ISC_TASK_WORKERS");
515 if (p != NULL)
516 workers = atoi(p);
517 if (workers < 1) {
518 t_info("Bad config value for ISC_TASK_WORKERS, %d\n", workers);
519 return(T_UNRESOLVED);
522 p = t_getenv("ISC_TASKS_MIN");
523 if (p != NULL)
524 ntasks = atoi(p);
525 else
526 ntasks = T2_NTASKS;
527 if (ntasks == 0U) {
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);
556 return(T_FAIL);
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))
585 result = T_PASS;
586 else if (T2_nfails != 0)
587 result = T_FAIL;
589 return(result);
592 static const char *a2 = "The task subsystem can create ISC_TASKS_MIN tasks";
594 static void
595 t2(void) {
596 t_assert("tasks", 2, T_REQUIRED, "%s", a2);
598 if (threaded)
599 t_result(t_tasks2());
600 else
601 require_threads();
604 #define T3_NEVENTS 256
606 static int T3_flag;
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;
614 static void
615 t3_sde1(isc_task_t *task, isc_event_t *event) {
617 UNUSED(task);
619 if (T3_nevents != T3_NEVENTS) {
620 t_info("Some events were not processed\n");
621 ++T3_nprobs;
623 if (T3_nsdevents == 1) {
624 ++T3_nsdevents;
625 } else {
626 t_info("Shutdown events not processed in LIFO order\n");
627 ++T3_nfails;
629 isc_event_free(&event);
632 static void
633 t3_sde2(isc_task_t *task, isc_event_t *event) {
635 UNUSED(task);
637 if (T3_nevents != T3_NEVENTS) {
638 t_info("Some events were not processed\n");
639 ++T3_nprobs;
641 if (T3_nsdevents == 0) {
642 ++T3_nsdevents;
643 } else {
644 t_info("Shutdown events not processed in LIFO order\n");
645 ++T3_nfails;
647 isc_event_free(&event);
650 static void
651 t3_event1(isc_task_t *task, isc_event_t *event) {
652 isc_result_t isc_result;
654 UNUSED(task);
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));
660 ++T3_nprobs;
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));
670 ++T3_nprobs;
672 isc_event_free(&event);
675 static void
676 t3_event2(isc_task_t *task, isc_event_t *event) {
677 UNUSED(task);
679 ++T3_nevents;
680 isc_event_free(&event);
683 static int
684 t_tasks3(void) {
685 int cnt;
686 int result;
687 char *p;
688 isc_mem_t *mctx;
689 isc_taskmgr_t *tmgr;
690 isc_task_t *task;
691 unsigned int workers;
692 isc_event_t *event;
693 isc_result_t isc_result;
694 isc_eventtype_t event_type;
696 T3_flag = 0;
697 T3_nevents = 0;
698 T3_nsdevents = 0;
699 T3_nfails = 0;
700 T3_nprobs = 0;
702 event_type = 3;
704 workers = 2;
705 p = t_getenv("ISC_TASK_WORKERS");
706 if (p != NULL)
707 workers = atoi(p);
709 mctx = NULL;
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);
733 tmgr = NULL;
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);
751 task = NULL;
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));
767 if (event == NULL) {
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));
783 if (event == NULL) {
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.
824 T3_flag = 1;
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));
829 ++T3_nprobs;
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));
836 ++T3_nprobs;
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);
846 ++T3_nfails;
849 result = T_UNRESOLVED;
851 if (T3_nfails != 0)
852 result = T_FAIL;
853 else if ((T3_nfails == 0) && (T3_nprobs == 0))
854 result = T_PASS;
856 return(result);
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 "
862 "LIFO order.";
863 static void
864 t3(void) {
865 t_assert("tasks", 3, T_REQUIRED, "%s", a3);
867 if (threaded)
868 t_result(t_tasks3());
869 else
870 require_threads();
873 static isc_mutex_t T4_mx;
874 static isc_condition_t T4_cv;
875 static int T4_flag;
876 static int T4_nprobs;
877 static int T4_nfails;
879 static void
880 t4_event1(isc_task_t *task, isc_event_t *event) {
881 isc_result_t isc_result;
883 UNUSED(task);
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));
889 ++T4_nprobs;
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));
899 ++T4_nprobs;
901 isc_event_free(&event);
904 static void
905 t4_sde(isc_task_t *task, isc_event_t *event) {
906 UNUSED(task);
909 * No-op.
912 isc_event_free(&event);
915 static int
916 t_tasks4(void) {
917 int result;
918 char *p;
919 isc_mem_t *mctx;
920 isc_taskmgr_t *tmgr;
921 isc_task_t *task;
922 unsigned int workers;
923 isc_result_t isc_result;
924 isc_eventtype_t event_type;
925 isc_event_t *event;
927 T4_nprobs = 0;
928 T4_nfails = 0;
929 T4_flag = 0;
931 event_type = 4;
933 workers = 2;
934 p = t_getenv("ISC_TASK_WORKERS");
935 if (p != NULL)
936 workers = atoi(p);
938 mctx = NULL;
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));
958 DESTROYLOCK(&T4_mx);
959 isc_mem_destroy(&mctx);
960 return(T_UNRESOLVED);
963 tmgr = NULL;
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));
968 DESTROYLOCK(&T4_mx);
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));
978 DESTROYLOCK(&T4_mx);
979 (void) isc_condition_destroy(&T4_cv);
980 isc_taskmgr_destroy(&tmgr);
981 isc_mem_destroy(&mctx);
982 return(T_UNRESOLVED);
985 task = NULL;
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));
990 DESTROYLOCK(&T4_mx);
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));
1019 ++T4_nfails;
1023 * Release the task.
1025 T4_flag = 1;
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));
1031 ++T4_nprobs;
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));
1038 ++T4_nprobs;
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;
1049 if (T4_nfails != 0)
1050 result = T_FAIL;
1051 else if ((T4_nfails == 0) && (T4_nprobs == 0))
1052 result = T_PASS;
1054 return(result);
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.";
1061 static void
1062 t4(void) {
1063 t_assert("tasks", 4, T_REQUIRED, "%s", a4);
1065 if (threaded)
1066 t_result(t_tasks4());
1067 else
1068 require_threads();
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;
1079 static void
1080 t7_event1(isc_task_t *task, isc_event_t *event) {
1081 UNUSED(task);
1083 ++T7_eflag;
1085 isc_event_free(&event);
1088 static void
1089 t7_sde(isc_task_t *task, isc_event_t *event) {
1090 isc_result_t isc_result;
1092 UNUSED(task);
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));
1098 ++T7_nprobs;
1101 ++T7_sdflag;
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));
1107 ++T7_nprobs;
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));
1114 ++T7_nprobs;
1117 isc_event_free(&event);
1120 static int
1121 t_tasks7(void) {
1122 int result;
1123 char *p;
1124 isc_mem_t *mctx;
1125 isc_taskmgr_t *tmgr;
1126 isc_task_t *task;
1127 unsigned int workers;
1128 isc_result_t isc_result;
1129 isc_eventtype_t event_type;
1130 isc_event_t *event;
1131 isc_time_t now;
1132 isc_interval_t interval;
1134 T7_nprobs = 0;
1135 T7_nfails = 0;
1136 T7_sdflag = 0;
1137 T7_eflag = 0;
1139 event_type = 7;
1141 workers = 2;
1142 p = t_getenv("ISC_TASK_WORKERS");
1143 if (p != NULL)
1144 workers = atoi(p);
1146 mctx = NULL;
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);
1171 tmgr = NULL;
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);
1190 return(T_FAIL);
1193 task = NULL;
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);
1202 return(T_FAIL);
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);
1256 return(T_FAIL);
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));
1264 ++T7_nprobs;
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;
1275 if (T7_eflag == 0)
1276 ++T7_nfails;
1278 if (T7_nfails != 0)
1279 result = T_FAIL;
1280 else if ((T7_nfails == 0) && (T7_nprobs == 0))
1281 result = T_PASS;
1283 return(result);
1286 static const char *a7 = "A call to isc_task_create() creates a task that can "
1287 "receive events.";
1289 static void
1290 t7(void) {
1291 t_assert("tasks", 7, T_REQUIRED, "%s", a7);
1293 if (threaded)
1294 t_result(t_tasks7());
1295 else
1296 require_threads();
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;
1319 static void
1320 t10_event1(isc_task_t *task, isc_event_t *event) {
1321 isc_result_t isc_result;
1323 UNUSED(task);
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));
1329 ++T10_nprobs;
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));
1337 ++T10_nprobs;
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));
1345 ++T10_nprobs;
1348 isc_event_free(&event);
1351 static void
1352 t10_event2(isc_task_t *task, isc_event_t *event) {
1354 int sender_match;
1355 int type_match;
1356 int tag_match;
1358 UNUSED(task);
1360 sender_match = 0;
1361 type_match = 0;
1362 tag_match = 0;
1364 if (T_debug) {
1365 t_info("Event %p,%d,%p,%s\n",
1366 event->ev_sender,
1367 (int)event->ev_type,
1368 event->ev_tag,
1369 event->ev_attributes & ISC_EVENTATTR_NOPURGE ?
1370 "NP" : "P");
1373 if ((T10_purge_sender == NULL) ||
1374 (T10_purge_sender == event->ev_sender)) {
1375 sender_match = 1;
1377 if (T10_testrange == 0) {
1378 if (T10_purge_type_first == event->ev_type) {
1379 type_match = 1;
1381 } else {
1382 if ((T10_purge_type_first <= event->ev_type) &&
1383 (event->ev_type <= T10_purge_type_last)) {
1384 type_match = 1;
1387 if ((T10_purge_tag == NULL) ||
1388 (T10_purge_tag == event->ev_tag)) {
1389 tag_match = 1;
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,
1396 event->ev_tag);
1397 ++T10_eventcnt;
1398 } else {
1399 t_info("*** event %p,%d,%p not purged\n",
1400 event->ev_sender, (int)event->ev_type,
1401 event->ev_tag);
1403 } else {
1404 ++T10_eventcnt;
1406 isc_event_free(&event);
1410 static void
1411 t10_sde(isc_task_t *task, isc_event_t *event) {
1412 isc_result_t isc_result;
1414 UNUSED(task);
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));
1420 ++T10_nprobs;
1423 ++T10_shutdownflag;
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));
1429 ++T10_nprobs;
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));
1436 ++T10_nprobs;
1439 isc_event_free(&event);
1442 static void
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)
1447 char *p;
1448 isc_mem_t *mctx;
1449 isc_taskmgr_t *tmgr;
1450 isc_task_t *task;
1451 unsigned int workers;
1452 isc_result_t isc_result;
1453 isc_event_t *event;
1454 isc_time_t now;
1455 isc_interval_t interval;
1456 int sender_cnt;
1457 int type_cnt;
1458 int tag_cnt;
1459 int event_cnt;
1460 int cnt;
1461 int nevents;
1462 isc_event_t *eventtab[T10_NEVENTS];
1465 T10_startflag = 0;
1466 T10_shutdownflag = 0;
1467 T10_eventcnt = 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;
1474 workers = 2;
1475 p = t_getenv("ISC_TASK_WORKERS");
1476 if (p != NULL)
1477 workers = atoi(p);
1479 mctx = NULL;
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));
1484 ++*nprobs;
1485 return;
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);
1493 ++*nprobs;
1494 return;
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);
1503 ++*nprobs;
1504 return;
1507 tmgr = NULL;
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);
1515 ++*nprobs;
1516 return;
1519 task = NULL;
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);
1528 ++*nprobs;
1529 return;
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);
1541 ++*nprobs;
1542 return;
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);
1558 ++*nprobs;
1559 return;
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.
1568 event_cnt = 0;
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);
1585 ++*nprobs;
1586 return;
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) &&
1596 (tag_cnt %2))
1597 eventtab[event_cnt]->ev_attributes |=
1598 ISC_EVENTATTR_NOPURGE;
1599 ++event_cnt;
1604 for (cnt = 0; cnt < event_cnt; ++cnt)
1605 isc_task_send(task, &eventtab[cnt]);
1607 if (T_debug)
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,
1616 purge_tag);
1617 if (nevents != exp_nevents) {
1618 t_info("*** isc_task_purge returned %d, expected %d\n",
1619 nevents, exp_nevents);
1620 ++*nfails;
1621 } else if (T_debug)
1622 t_info("isc_task_purge returned %d\n", nevents);
1623 } else {
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,
1630 purge_tag);
1631 if (nevents != exp_nevents) {
1632 t_info("*** isc_task_purgerange returned %d, "
1633 "expected %d\n", nevents, exp_nevents);
1634 ++*nfails;
1635 } else if (T_debug)
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);
1648 ++*nprobs;
1649 return;
1653 * Unblock the task, allowing event processing.
1655 T10_startflag = 1;
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));
1660 ++*nprobs;
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);
1680 ++*nprobs;
1681 return;
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);
1693 ++*nfails;
1694 return;
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));
1702 ++*nprobs;
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);
1711 if (T_debug)
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);
1717 ++*nfails;
1721 static int
1722 t_tasks10(void) {
1723 int result;
1725 T10_nprobs = 0;
1726 T10_nfails = 0;
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,
1733 &T10_nprobs, 0);
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,
1740 &T10_nprobs, 0);
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,
1747 &T10_nprobs, 0);
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,
1754 &T10_nprobs, 0);
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,
1761 &T10_nprobs, 0);
1763 result = T_UNRESOLVED;
1765 if ((T10_nfails == 0) && (T10_nprobs == 0))
1766 result = T_PASS;
1767 else if (T10_nfails != 0)
1768 result = T_FAIL;
1770 return(result);
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.";
1779 static void
1780 t10(void) {
1781 t_assert("tasks", 10, T_REQUIRED, "%s", a10);
1783 if (threaded)
1784 t_result(t_tasks10());
1785 else
1786 require_threads();
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;
1797 static void
1798 t11_event1(isc_task_t *task, isc_event_t *event) {
1799 isc_result_t isc_result;
1801 UNUSED(task);
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));
1807 ++T11_nprobs;
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));
1815 ++T11_nprobs;
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));
1823 ++T11_nprobs;
1826 isc_event_free(&event);
1829 static void
1830 t11_event2(isc_task_t *task, isc_event_t *event) {
1831 UNUSED(task);
1833 ++T11_eventcnt;
1834 isc_event_free(&event);
1838 static void
1839 t11_sde(isc_task_t *task, isc_event_t *event) {
1840 isc_result_t isc_result;
1842 UNUSED(task);
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));
1848 ++T11_nprobs;
1851 ++T11_shutdownflag;
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));
1857 ++T11_nprobs;
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));
1864 ++T11_nprobs;
1867 isc_event_free(&event);
1870 static int
1871 t_tasks11(int purgable) {
1872 char *p;
1873 isc_mem_t *mctx;
1874 isc_taskmgr_t *tmgr;
1875 isc_task_t *task;
1876 isc_boolean_t rval;
1877 unsigned int workers;
1878 isc_result_t isc_result;
1879 isc_event_t *event1;
1880 isc_event_t *event2, *event2_clone;
1881 isc_time_t now;
1882 isc_interval_t interval;
1883 int result;
1885 T11_startflag = 0;
1886 T11_shutdownflag = 0;
1887 T11_eventcnt = 0;
1889 workers = 2;
1890 p = t_getenv("ISC_TASK_WORKERS");
1891 if (p != NULL)
1892 workers = atoi(p);
1894 mctx = NULL;
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);
1919 tmgr = NULL;
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);
1930 task = NULL;
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;
1982 if (purgable)
1983 event2->ev_attributes &= ~ISC_EVENTATTR_NOPURGE;
1984 else
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"));
1994 ++T11_nfails;
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));
2001 ++T11_nprobs;
2005 * Unblock the task, allowing event processing.
2007 T11_startflag = 1;
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));
2012 ++T11_nprobs;
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));
2027 ++T11_nprobs;
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));
2034 ++T11_nprobs;
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));
2042 ++T11_nprobs;
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"));
2054 ++T11_nfails;
2057 result = T_UNRESOLVED;
2059 if ((T11_nfails == 0) && (T11_nprobs == 0))
2060 result = T_PASS;
2061 else if (T11_nfails)
2062 result = T_FAIL;
2064 return(result);
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.";
2072 static void
2073 t11(void) {
2074 t_assert("tasks", 11, T_REQUIRED, "%s", a11);
2076 if (threaded)
2077 t_result(t_tasks11(1));
2078 else
2079 require_threads();
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 "
2086 "ISC_FALSE.";
2088 static int
2089 t_tasks12(void) {
2090 return(t_tasks11(0));
2093 static void
2094 t12(void) {
2095 t_assert("tasks", 12, T_REQUIRED, "%s", a12);
2097 if (threaded)
2098 t_result(t_tasks12());
2099 else
2100 require_threads();
2103 static int T13_nfails;
2104 static int T13_nprobs;
2106 static const char *a13 =
2107 "A call to "
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.";
2114 static int
2115 t_tasks13(void) {
2116 int result;
2118 T13_nfails = 0;
2119 T13_nprobs = 0;
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,
2191 &T13_nprobs, 1);
2193 result = T_UNRESOLVED;
2195 if ((T13_nfails == 0) && (T13_nprobs == 0))
2196 result = T_PASS;
2197 else if (T13_nfails)
2198 result = T_FAIL;
2200 return (result);
2203 static void
2204 t13(void) {
2205 t_assert("tasks", 13, T_REQUIRED, "%s", a13);
2207 if (threaded)
2208 t_result(t_tasks13());
2209 else
2210 require_threads();
2213 #define T14_NTASKS 10
2214 #define T14_EXCLTASK 6
2216 int t14_exclusiveerror = ISC_R_SUCCESS;
2217 int t14_error = 0;
2218 int t14_done = 0;
2220 int spin(int n);
2222 int t14_active[T14_NTASKS];
2224 static void
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) {
2231 int i;
2232 t14_exclusiveerror = isc_task_beginexclusive(task);
2233 if (t14_exclusiveerror == ISC_R_SUCCESS)
2234 t_info("task %d got exclusive access\n", taskno);
2235 else
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]);
2240 if (t14_active[i])
2241 t14_error++;
2243 isc_task_endexclusive(task);
2244 t14_done = 1;
2245 } else {
2246 t14_active[taskno]++;
2247 (void) spin(10000000);
2248 t14_active[taskno]--;
2250 t_info("task exit %d\n", taskno);
2251 if (t14_done) {
2252 isc_mem_put(event->ev_destroy_arg, event->ev_arg, sizeof (int));
2253 isc_event_free(&event);
2254 } else {
2255 isc_task_send(task, &event);
2259 int spin(int n) {
2260 int i;
2261 int r = 0;
2262 for (i = 0; i < n; i++) {
2263 r += i;
2264 if (r > 1000000)
2265 r = 0;
2267 return (r);
2270 static int
2271 t_tasks14(void) {
2272 char *p;
2273 isc_mem_t *mctx;
2274 isc_taskmgr_t *manager;
2275 isc_task_t *tasks[T14_NTASKS];
2276 unsigned int workers;
2277 isc_result_t isc_result;
2278 int i;
2280 manager = NULL;
2281 mctx = NULL;
2283 for (i = 0; i < T14_NTASKS; i++)
2284 tasks[i] = NULL;
2286 workers = 4;
2287 p = t_getenv("ISC_TASK_WORKERS");
2288 if (p != NULL)
2289 workers = atoi(p);
2290 if (workers < 1) {
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);
2304 return(T_FAIL);
2307 for (i = 0; i < T14_NTASKS; i++) {
2308 isc_event_t *event;
2309 int *v;
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);
2314 return(T_FAIL);
2317 v = isc_mem_get(mctx, sizeof *v);
2318 if (v == NULL) {
2319 isc_task_detach(&tasks[i]);
2320 t_info("isc_mem_get failed\n");
2321 return(T_FAIL);
2323 *v = i;
2325 event = isc_event_allocate(mctx, NULL, 1, t14_callback,
2326 v, sizeof(*event));
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");
2344 if (t14_error)
2345 t_info("mutual access occurred\n");
2346 return(T_FAIL);
2349 isc_mem_destroy(&mctx);
2350 return(T_PASS);
2353 static void
2354 t14(void) {
2355 int result;
2357 t_assert("tasks", 14, T_REQUIRED, "%s",
2358 "isc_task_beginexclusive() gets exclusive access");
2359 result = t_tasks14();
2360 t_result(result);
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" },
2374 { (PFV) 0, NULL }
2377 #ifdef WIN32
2379 main(int argc, char **argv) {
2380 t_settests(T_testlist);
2381 return (t_main(argc, argv));
2383 #endif