No empty .Rs/.Re
[netbsd-mini2440.git] / external / bsd / bind / dist / bin / tests / tasks / t_tasks.c
blobc617558803a91a58be542cae588e4788076ea4de
1 /* $NetBSD$ */
3 /*
4 * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1998-2001 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: t_tasks.c,v 1.42 2009/01/22 23:47:54 tbox Exp */
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) {
73 UNUSED(task);
75 t_info("shutdown %s\n", (char *)event->ev_arg);
76 isc_event_free(&event);
79 static void
80 my_tick(isc_task_t *task, isc_event_t *event) {
81 UNUSED(task);
83 t_info("%s\n", (char *)event->ev_arg);
84 isc_event_free(&event);
88 * Adapted from RTH's original task_test program
91 static int
92 t_tasks1(void) {
93 char *p;
94 isc_mem_t *mctx;
95 isc_taskmgr_t *manager;
96 isc_task_t *task1;
97 isc_task_t *task2;
98 isc_task_t *task3;
99 isc_task_t *task4;
100 isc_event_t *event;
101 unsigned int workers;
102 isc_timermgr_t *timgr;
103 isc_timer_t *ti1;
104 isc_timer_t *ti2;
105 isc_result_t isc_result;
106 struct isc_time absolute;
107 struct isc_interval interval;
109 manager = NULL;
110 task1 = NULL;
111 task2 = NULL;
112 task3 = NULL;
113 task4 = NULL;
114 mctx = NULL;
116 workers = 2;
117 p = t_getenv("ISC_TASK_WORKERS");
118 if (p != NULL)
119 workers = atoi(p);
120 if (workers < 1) {
121 t_info("Bad config value for ISC_TASK_WORKERS, %d\n", workers);
122 return(T_UNRESOLVED);
125 isc_result = isc_mem_create(0, 0, &mctx);
126 if (isc_result != ISC_R_SUCCESS) {
127 t_info("isc_mem_create failed %d\n", isc_result);
128 return(T_UNRESOLVED);
131 isc_result = isc_taskmgr_create(mctx, workers, 0, &manager);
132 if (isc_result != ISC_R_SUCCESS) {
133 t_info("isc_taskmgr_create failed %d\n", isc_result);
134 return(T_FAIL);
137 isc_result = isc_task_create(manager, 0, &task1);
138 if (isc_result != ISC_R_SUCCESS) {
139 t_info("isc_task_create failed %d\n", isc_result);
140 return(T_FAIL);
143 isc_result = isc_task_create(manager, 0, &task2);
144 if (isc_result != ISC_R_SUCCESS) {
145 t_info("isc_task_create failed %d\n", isc_result);
146 return(T_FAIL);
149 isc_result = isc_task_create(manager, 0, &task3);
150 if (isc_result != ISC_R_SUCCESS) {
151 t_info("isc_task_create failed %d\n", isc_result);
152 return(T_FAIL);
155 isc_result = isc_task_create(manager, 0, &task4);
156 if (isc_result != ISC_R_SUCCESS) {
157 t_info("isc_task_create failed %d\n", isc_result);
158 return(T_FAIL);
161 isc_result = isc_task_onshutdown(task1, t1_shutdown, "1");
162 if (isc_result != ISC_R_SUCCESS) {
163 t_info("isc_task_onshutdown failed %d\n", isc_result);
164 return(T_FAIL);
167 isc_result = isc_task_onshutdown(task2, t1_shutdown, "2");
168 if (isc_result != ISC_R_SUCCESS) {
169 t_info("isc_task_onshutdown failed %d\n", isc_result);
170 return(T_FAIL);
173 isc_result = isc_task_onshutdown(task3, t1_shutdown, "3");
174 if (isc_result != ISC_R_SUCCESS) {
175 t_info("isc_task_onshutdown failed %d\n", isc_result);
176 return(T_FAIL);
179 isc_result = isc_task_onshutdown(task4, t1_shutdown, "4");
180 if (isc_result != ISC_R_SUCCESS) {
181 t_info("isc_task_onshutdown failed %d\n", isc_result);
182 return(T_FAIL);
185 timgr = NULL;
186 isc_result = isc_timermgr_create(mctx, &timgr);
187 if (isc_result != ISC_R_SUCCESS) {
188 t_info("isc_timermgr_create %d\n", isc_result);
189 return(T_UNRESOLVED);
192 ti1 = NULL;
193 isc_time_settoepoch(&absolute);
194 isc_interval_set(&interval, 1, 0);
195 isc_result = isc_timer_create(timgr, isc_timertype_ticker,
196 &absolute, &interval,
197 task1, my_tick, "tick", &ti1);
198 if (isc_result != ISC_R_SUCCESS) {
199 t_info("isc_timer_create %d\n", isc_result);
200 return(T_UNRESOLVED);
203 ti2 = NULL;
204 isc_time_settoepoch(&absolute);
205 isc_interval_set(&interval, 1, 0);
206 isc_result = isc_timer_create(timgr, isc_timertype_ticker,
207 &absolute, &interval,
208 task2, my_tick, "tock", &ti2);
209 if (isc_result != ISC_R_SUCCESS) {
210 t_info("isc_timer_create %d\n", isc_result);
211 return(T_UNRESOLVED);
215 sleep(2);
218 * Note: (void *)1 is used as a sender here, since some compilers
219 * don't like casting a function pointer to a (void *).
221 * In a real use, it is more likely the sender would be a
222 * structure (socket, timer, task, etc) but this is just a test
223 * program.
225 event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "1",
226 sizeof(*event));
227 if (event == NULL) {
228 t_info("isc_event_allocate failed\n");
229 return(T_UNRESOLVED);
232 isc_task_send(task1, &event);
234 event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "1",
235 sizeof(*event));
236 if (event == NULL) {
237 t_info("isc_event_allocate failed\n");
238 return(T_UNRESOLVED);
241 isc_task_send(task1, &event);
243 event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "1",
244 sizeof(*event));
245 if (event == NULL) {
246 t_info("isc_event_allocate failed\n");
247 return(T_UNRESOLVED);
250 isc_task_send(task1, &event);
252 event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "1",
253 sizeof(*event));
254 if (event == NULL) {
255 t_info("isc_event_allocate failed\n");
256 return(T_UNRESOLVED);
259 isc_task_send(task1, &event);
261 event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "1",
262 sizeof(*event));
263 if (event == NULL) {
264 t_info("isc_event_allocate failed\n");
265 return(T_UNRESOLVED);
268 isc_task_send(task1, &event);
270 event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "1",
271 sizeof(*event));
272 if (event == NULL) {
273 t_info("isc_event_allocate failed\n");
274 return(T_UNRESOLVED);
277 isc_task_send(task1, &event);
279 event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "1",
280 sizeof(*event));
281 if (event == NULL) {
282 t_info("isc_event_allocate failed\n");
283 return(T_UNRESOLVED);
286 isc_task_send(task1, &event);
288 event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "1",
289 sizeof(*event));
290 if (event == NULL) {
291 t_info("isc_event_allocate failed\n");
292 return(T_UNRESOLVED);
295 isc_task_send(task1, &event);
297 event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "1",
298 sizeof(*event));
299 if (event == NULL) {
300 t_info("isc_event_allocate failed\n");
301 return(T_UNRESOLVED);
304 isc_task_send(task1, &event);
306 event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "2",
307 sizeof(*event));
308 if (event == NULL) {
309 t_info("isc_event_allocate failed\n");
310 return(T_UNRESOLVED);
313 isc_task_send(task2, &event);
315 event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "3",
316 sizeof(*event));
317 if (event == NULL) {
318 t_info("isc_event_allocate failed\n");
319 return(T_UNRESOLVED);
322 isc_task_send(task3, &event);
324 event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "4",
325 sizeof(*event));
326 if (event == NULL) {
327 t_info("isc_event_allocate failed\n");
328 return(T_UNRESOLVED);
331 isc_task_send(task4, &event);
333 event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "2",
334 sizeof(*event));
335 if (event == NULL) {
336 t_info("isc_event_allocate failed\n");
337 return(T_UNRESOLVED);
340 isc_task_send(task2, &event);
342 event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "3",
343 sizeof(*event));
344 if (event == NULL) {
345 t_info("isc_event_allocate failed\n");
346 return(T_UNRESOLVED);
349 isc_task_send(task3, &event);
351 event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "4",
352 sizeof(*event));
353 if (event == NULL) {
354 t_info("isc_event_allocate failed\n");
355 return(T_UNRESOLVED);
358 isc_task_send(task4, &event);
360 (void)isc_task_purge(task3, NULL, 0, 0);
362 isc_task_detach(&task1);
363 isc_task_detach(&task2);
364 isc_task_detach(&task3);
365 isc_task_detach(&task4);
367 sleep(10);
368 isc_timer_detach(&ti1);
369 isc_timer_detach(&ti2);
370 isc_timermgr_destroy(&timgr);
371 isc_taskmgr_destroy(&manager);
373 isc_mem_destroy(&mctx);
374 return(T_PASS);
377 static const char *a1 = "The task subsystem can create and manage tasks";
379 static void
380 t1(void) {
381 int result;
383 t_assert("tasks", 1, T_REQUIRED, "%s", a1);
384 result = t_tasks1();
385 t_result(result);
388 #define T2_NTASKS 10000
390 static isc_event_t *T2_event;
391 static isc_taskmgr_t *T2_manager;
392 static isc_mem_t *T2_mctx;
393 static isc_condition_t T2_cv;
394 static isc_mutex_t T2_mx;
395 static int T2_done;
396 static int T2_nprobs;
397 static int T2_nfails;
398 static int T2_ntasks;
400 static void
401 t2_shutdown(isc_task_t *task, isc_event_t *event) {
403 isc_result_t isc_result;
405 task = task; /* notused */
407 if (event->ev_arg != NULL) {
408 isc_task_destroy((isc_task_t**) &event->ev_arg);
410 else {
411 isc_result = isc_mutex_lock(&T2_mx);
412 if (isc_result != ISC_R_SUCCESS) {
413 t_info("isc_mutex_lock failed %d\n", isc_result);
414 ++T2_nprobs;
417 T2_done = 1;
419 isc_result = isc_condition_signal(&T2_cv);
420 if (isc_result != ISC_R_SUCCESS) {
421 t_info("isc_condition_signal failed %d\n", isc_result);
422 ++T2_nprobs;
425 isc_result = isc_mutex_unlock(&T2_mx);
426 if (isc_result != ISC_R_SUCCESS) {
427 t_info("isc_mutex_unlock failed %d\n", isc_result);
428 ++T2_nprobs;
431 isc_event_free(&T2_event);
432 isc_taskmgr_destroy(&T2_manager);
433 isc_mem_destroy(&T2_mctx);
437 static void
438 t2_callback(isc_task_t *task, isc_event_t *event) {
439 isc_result_t isc_result;
440 isc_task_t *newtask;
442 ++T2_ntasks;
444 if (T_debug && ((T2_ntasks % 100) == 0)) {
445 t_info("T2_ntasks %d\n", T2_ntasks);
448 if (event->ev_arg) {
450 event->ev_arg = (void *)(((uintptr_t) event->ev_arg) - 1);
453 * Create a new task and forward the message.
455 newtask = NULL;
456 isc_result = isc_task_create(T2_manager, 0, &newtask);
457 if (isc_result != ISC_R_SUCCESS) {
458 t_info("isc_task_create failed %d\n", isc_result);
459 ++T2_nfails;
460 return;
463 isc_result = isc_task_onshutdown(newtask, t2_shutdown,
464 (void *)task);
465 if (isc_result != ISC_R_SUCCESS) {
466 t_info("isc_task_onshutdown failed %d\n",
467 isc_result);
468 ++T2_nfails;
469 return;
472 isc_task_send(newtask, &event);
473 } else {
475 * Time to unwind, shutdown should perc back up.
477 isc_task_destroy(&task);
481 static int
482 t_tasks2(void) {
483 uintptr_t ntasks;
484 int result;
485 char *p;
486 isc_event_t *event;
487 unsigned int workers;
488 isc_result_t isc_result;
490 T2_manager = NULL;
491 T2_done = 0;
492 T2_nprobs = 0;
493 T2_nfails = 0;
494 T2_ntasks = 0;
496 workers = 2;
497 p = t_getenv("ISC_TASK_WORKERS");
498 if (p != NULL)
499 workers = atoi(p);
500 if (workers < 1) {
501 t_info("Bad config value for ISC_TASK_WORKERS, %d\n", workers);
502 return(T_UNRESOLVED);
505 p = t_getenv("ISC_TASKS_MIN");
506 if (p != NULL)
507 ntasks = atoi(p);
508 else
509 ntasks = T2_NTASKS;
510 if (ntasks == 0U) {
511 t_info("Bad config value for ISC_TASKS_MIN, %lu\n",
512 (unsigned long)ntasks);
513 return(T_UNRESOLVED);
516 t_info("Testing with %lu tasks\n", (unsigned long)ntasks);
518 isc_result = isc_mutex_init(&T2_mx);
519 if (isc_result != ISC_R_SUCCESS) {
520 t_info("isc_mutex_init failed %d\n", isc_result);
521 return(T_UNRESOLVED);
524 isc_result = isc_condition_init(&T2_cv);
525 if (isc_result != ISC_R_SUCCESS) {
526 t_info("isc_condition_init failed %d\n", isc_result);
527 return(T_UNRESOLVED);
530 isc_result = isc_mem_create(0, 0, &T2_mctx);
531 if (isc_result != ISC_R_SUCCESS) {
532 t_info("isc_mem_create failed %d\n", isc_result);
533 return(T_UNRESOLVED);
536 isc_result = isc_taskmgr_create(T2_mctx, workers, 0, &T2_manager);
537 if (isc_result != ISC_R_SUCCESS) {
538 t_info("isc_taskmgr_create failed %d\n", isc_result);
539 return(T_FAIL);
542 T2_event = isc_event_allocate(T2_mctx, (void *)1, 1, t2_callback,
543 (void *)ntasks, sizeof(*event));
544 if (T2_event == NULL) {
545 t_info("isc_event_allocate failed\n");
546 return(T_UNRESOLVED);
549 isc_result = isc_mutex_lock(&T2_mx);
550 if (isc_result != ISC_R_SUCCESS) {
551 t_info("isc_mutex_lock failed %d\n", isc_result);
552 return(T_UNRESOLVED);
555 t2_callback(NULL, T2_event);
557 while (T2_done == 0) {
558 isc_result = isc_condition_wait(&T2_cv, &T2_mx);
559 if (isc_result != ISC_R_SUCCESS) {
560 t_info("isc_condition_wait failed %d\n", isc_result);
561 return(T_UNRESOLVED);
565 result = T_UNRESOLVED;
567 if ((T2_nfails == 0) && (T2_nprobs == 0))
568 result = T_PASS;
569 else if (T2_nfails != 0)
570 result = T_FAIL;
572 return(result);
575 static const char *a2 = "The task subsystem can create ISC_TASKS_MIN tasks";
577 static void
578 t2(void) {
579 t_assert("tasks", 2, T_REQUIRED, "%s", a2);
581 if (threaded)
582 t_result(t_tasks2());
583 else
584 require_threads();
587 #define T3_NEVENTS 256
589 static int T3_flag;
590 static int T3_nevents;
591 static int T3_nsdevents;
592 static isc_mutex_t T3_mx;
593 static isc_condition_t T3_cv;
594 static int T3_nfails;
595 static int T3_nprobs;
597 static void
598 t3_sde1(isc_task_t *task, isc_event_t *event) {
599 task = task;
601 if (T3_nevents != T3_NEVENTS) {
602 t_info("Some events were not processed\n");
603 ++T3_nprobs;
605 if (T3_nsdevents == 1) {
606 ++T3_nsdevents;
607 } else {
608 t_info("Shutdown events not processed in LIFO order\n");
609 ++T3_nfails;
611 isc_event_free(&event);
614 static void
615 t3_sde2(isc_task_t *task, isc_event_t *event) {
617 task = task;
619 if (T3_nevents != T3_NEVENTS) {
620 t_info("Some events were not processed\n");
621 ++T3_nprobs;
623 if (T3_nsdevents == 0) {
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_event1(isc_task_t *task, isc_event_t *event) {
634 isc_result_t isc_result;
636 task = task;
638 isc_result = isc_mutex_lock(&T3_mx);
639 if (isc_result != ISC_R_SUCCESS) {
640 t_info("isc_mutex_lock failed %s\n",
641 isc_result_totext(isc_result));
642 ++T3_nprobs;
644 while (T3_flag != 1) {
645 (void) isc_condition_wait(&T3_cv, &T3_mx);
648 isc_result = isc_mutex_unlock(&T3_mx);
649 if (isc_result != ISC_R_SUCCESS) {
650 t_info("isc_mutex_unlock failed %s\n",
651 isc_result_totext(isc_result));
652 ++T3_nprobs;
654 isc_event_free(&event);
657 static void
658 t3_event2(isc_task_t *task, isc_event_t *event) {
659 task = task;
661 ++T3_nevents;
662 isc_event_free(&event);
665 static int
666 t_tasks3(void) {
667 int cnt;
668 int result;
669 char *p;
670 isc_mem_t *mctx;
671 isc_taskmgr_t *tmgr;
672 isc_task_t *task;
673 unsigned int workers;
674 isc_event_t *event;
675 isc_result_t isc_result;
676 isc_eventtype_t event_type;
678 T3_flag = 0;
679 T3_nevents = 0;
680 T3_nsdevents = 0;
681 T3_nfails = 0;
682 T3_nprobs = 0;
684 event_type = 3;
686 workers = 2;
687 p = t_getenv("ISC_TASK_WORKERS");
688 if (p != NULL)
689 workers = atoi(p);
691 mctx = NULL;
692 isc_result = isc_mem_create(0, 0, &mctx);
693 if (isc_result != ISC_R_SUCCESS) {
694 t_info("isc_mem_create failed %s\n",
695 isc_result_totext(isc_result));
696 return(T_UNRESOLVED);
699 isc_result = isc_mutex_init(&T3_mx);
700 if (isc_result != ISC_R_SUCCESS) {
701 t_info("isc_mutex_init failed %s\n",
702 isc_result_totext(isc_result));
703 isc_mem_destroy(&mctx);
704 return(T_UNRESOLVED);
707 isc_result = isc_condition_init(&T3_cv);
708 if (isc_result != ISC_R_SUCCESS) {
709 t_info("isc_condition_init failed %s\n",
710 isc_result_totext(isc_result));
711 isc_mem_destroy(&mctx);
712 return(T_UNRESOLVED);
715 tmgr = NULL;
716 isc_result = isc_taskmgr_create(mctx, workers, 0, &tmgr);
717 if (isc_result != ISC_R_SUCCESS) {
718 t_info("isc_taskmgr_create failed %s\n",
719 isc_result_totext(isc_result));
720 isc_mem_destroy(&mctx);
721 return(T_UNRESOLVED);
724 isc_result = isc_mutex_lock(&T3_mx);
725 if (isc_result != ISC_R_SUCCESS) {
726 t_info("isc_mutex_lock failed %s\n",
727 isc_result_totext(isc_result));
728 isc_taskmgr_destroy(&tmgr);
729 isc_mem_destroy(&mctx);
730 return(T_UNRESOLVED);
733 task = NULL;
734 isc_result = isc_task_create(tmgr, 0, &task);
735 if (isc_result != ISC_R_SUCCESS) {
736 t_info("isc_task_create failed %s\n",
737 isc_result_totext(isc_result));
738 isc_mutex_unlock(&T3_mx);
739 isc_taskmgr_destroy(&tmgr);
740 isc_mem_destroy(&mctx);
741 return(T_UNRESOLVED);
745 * This event causes the task to wait on T3_cv.
747 event = isc_event_allocate(mctx, &senders[1], event_type, t3_event1,
748 NULL, sizeof(*event));
749 isc_task_send(task, &event);
752 * Now we fill up the task's event queue with some events.
754 for (cnt = 0; cnt < T3_NEVENTS; ++cnt) {
755 event = isc_event_allocate(mctx, &senders[1], event_type,
756 t3_event2, NULL, sizeof(*event));
757 isc_task_send(task, &event);
761 * Now we register two shutdown events.
763 isc_result = isc_task_onshutdown(task, t3_sde1, NULL);
764 if (isc_result != ISC_R_SUCCESS) {
765 t_info("isc_task_send failed %s\n",
766 isc_result_totext(isc_result));
767 isc_mutex_unlock(&T3_mx);
768 isc_task_destroy(&task);
769 isc_taskmgr_destroy(&tmgr);
770 isc_mem_destroy(&mctx);
771 return(T_UNRESOLVED);
774 isc_result = isc_task_onshutdown(task, t3_sde2, NULL);
775 if (isc_result != ISC_R_SUCCESS) {
776 t_info("isc_task_send failed %s\n",
777 isc_result_totext(isc_result));
778 isc_mutex_unlock(&T3_mx);
779 isc_task_destroy(&task);
780 isc_taskmgr_destroy(&tmgr);
781 isc_mem_destroy(&mctx);
782 return(T_UNRESOLVED);
785 isc_task_shutdown(task);
788 * Now we free the task by signaling T3_cv.
790 T3_flag = 1;
791 isc_result = isc_condition_signal(&T3_cv);
792 if (isc_result != ISC_R_SUCCESS) {
793 t_info("isc_task_send failed %s\n",
794 isc_result_totext(isc_result));
795 ++T3_nprobs;
798 isc_result = isc_mutex_unlock(&T3_mx);
799 if (isc_result != ISC_R_SUCCESS) {
800 t_info("isc_task_send failed %s\n",
801 isc_result_totext(isc_result));
802 ++T3_nprobs;
806 isc_task_detach(&task);
807 isc_taskmgr_destroy(&tmgr);
808 isc_mem_destroy(&mctx);
810 if (T3_nsdevents != 2) {
811 t_info("T3_nsdevents == %d, expected 2\n", T3_nsdevents);
812 ++T3_nfails;
815 if (T3_nevents != T3_nevents) {
816 t_info("T3_nevents == %d, expected 2\n", T3_nevents);
817 ++T3_nfails;
820 result = T_UNRESOLVED;
822 if (T3_nfails != 0)
823 result = T_FAIL;
824 else if ((T3_nfails == 0) && (T3_nprobs == 0))
825 result = T_PASS;
827 return(result);
830 static const char *a3 = "When isc_task_shutdown() is called, any shutdown "
831 "events that have been requested via prior "
832 "isc_task_onshutdown() calls are posted in "
833 "LIFO order.";
834 static void
835 t3(void) {
836 t_assert("tasks", 3, T_REQUIRED, "%s", a3);
838 if (threaded)
839 t_result(t_tasks3());
840 else
841 require_threads();
844 static isc_mutex_t T4_mx;
845 static isc_condition_t T4_cv;
846 static int T4_flag;
847 static int T4_nprobs;
848 static int T4_nfails;
850 static void
851 t4_event1(isc_task_t *task, isc_event_t *event) {
852 isc_result_t isc_result;
854 UNUSED(task);
856 isc_result = isc_mutex_lock(&T4_mx);
857 if (isc_result != ISC_R_SUCCESS) {
858 t_info("isc_mutex_lock failed %s\n",
859 isc_result_totext(isc_result));
860 ++T4_nprobs;
862 while (T4_flag != 1) {
863 (void) isc_condition_wait(&T4_cv, &T4_mx);
866 isc_result = isc_mutex_unlock(&T4_mx);
867 if (isc_result != ISC_R_SUCCESS) {
868 t_info("isc_mutex_unlock failed %s\n",
869 isc_result_totext(isc_result));
870 ++T4_nprobs;
872 isc_event_free(&event);
875 static void
876 t4_sde(isc_task_t *task, isc_event_t *event) {
877 UNUSED(task);
880 * No-op.
883 isc_event_free(&event);
886 static int
887 t_tasks4(void) {
888 int result;
889 char *p;
890 isc_mem_t *mctx;
891 isc_taskmgr_t *tmgr;
892 isc_task_t *task;
893 unsigned int workers;
894 isc_result_t isc_result;
895 isc_eventtype_t event_type;
896 isc_event_t *event;
898 T4_nprobs = 0;
899 T4_nfails = 0;
900 T4_flag = 0;
902 result = T_UNRESOLVED;
903 event_type = 4;
905 workers = 2;
906 p = t_getenv("ISC_TASK_WORKERS");
907 if (p != NULL)
908 workers = atoi(p);
910 mctx = NULL;
911 isc_result = isc_mem_create(0, 0, &mctx);
912 if (isc_result != ISC_R_SUCCESS) {
913 t_info("isc_mem_create failed %s\n",
914 isc_result_totext(isc_result));
915 return(T_UNRESOLVED);
918 isc_result = isc_mutex_init(&T4_mx);
919 if (isc_result != ISC_R_SUCCESS) {
920 t_info("isc_mutex_init failed %s\n",
921 isc_result_totext(isc_result));
922 isc_mem_destroy(&mctx);
923 return(T_UNRESOLVED);
926 isc_result = isc_condition_init(&T4_cv);
927 if (isc_result != ISC_R_SUCCESS) {
928 t_info("isc_condition_init failed %s\n",
929 isc_result_totext(isc_result));
930 DESTROYLOCK(&T4_mx);
931 isc_mem_destroy(&mctx);
932 return(T_UNRESOLVED);
935 tmgr = NULL;
936 isc_result = isc_taskmgr_create(mctx, workers, 0, &tmgr);
937 if (isc_result != ISC_R_SUCCESS) {
938 t_info("isc_taskmgr_create failed %s\n",
939 isc_result_totext(isc_result));
940 DESTROYLOCK(&T4_mx);
941 isc_condition_destroy(&T4_cv);
942 isc_mem_destroy(&mctx);
943 return(T_UNRESOLVED);
946 isc_result = isc_mutex_lock(&T4_mx);
947 if (isc_result != ISC_R_SUCCESS) {
948 t_info("isc_mutex_lock failed %s\n",
949 isc_result_totext(isc_result));
950 DESTROYLOCK(&T4_mx);
951 isc_condition_destroy(&T4_cv);
952 isc_taskmgr_destroy(&tmgr);
953 isc_mem_destroy(&mctx);
954 return(T_UNRESOLVED);
957 task = NULL;
958 isc_result = isc_task_create(tmgr, 0, &task);
959 if (isc_result != ISC_R_SUCCESS) {
960 t_info("isc_task_create failed %s\n",
961 isc_result_totext(isc_result));
962 DESTROYLOCK(&T4_mx);
963 isc_condition_destroy(&T4_cv);
964 isc_taskmgr_destroy(&tmgr);
965 isc_mem_destroy(&mctx);
966 return(T_UNRESOLVED);
970 * This event causes the task to wait on T4_cv.
972 event = isc_event_allocate(mctx, &senders[1], event_type, t4_event1,
973 NULL, sizeof(*event));
974 isc_task_send(task, &event);
976 isc_task_shutdown(task);
978 isc_result = isc_task_onshutdown(task, t4_sde, NULL);
979 if (isc_result != ISC_R_SHUTTINGDOWN) {
980 t_info("isc_task_onshutdown returned %s\n",
981 isc_result_totext(isc_result));
982 ++T4_nfails;
986 * Release the task.
988 T4_flag = 1;
990 isc_result = isc_condition_signal(&T4_cv);
991 if (isc_result != ISC_R_SUCCESS) {
992 t_info("isc_condition_signal failed %s\n",
993 isc_result_totext(isc_result));
994 ++T4_nprobs;
997 isc_result = isc_mutex_unlock(&T4_mx);
998 if (isc_result != ISC_R_SUCCESS) {
999 t_info("isc_mutex_unlock failed %s\n",
1000 isc_result_totext(isc_result));
1001 ++T4_nprobs;
1004 isc_task_detach(&task);
1005 isc_taskmgr_destroy(&tmgr);
1006 isc_mem_destroy(&mctx);
1007 isc_condition_destroy(&T4_cv);
1008 DESTROYLOCK(&T4_mx);
1010 result = T_UNRESOLVED;
1012 if (T4_nfails != 0)
1013 result = T_FAIL;
1014 else if ((T4_nfails == 0) && (T4_nprobs == 0))
1015 result = T_PASS;
1017 return(result);
1020 static const char *a4 =
1021 "After isc_task_shutdown() has been called, any call to "
1022 "isc_task_onshutdown() will return ISC_R_SHUTTINGDOWN.";
1024 static void
1025 t4(void) {
1026 t_assert("tasks", 4, T_REQUIRED, "%s", a4);
1028 if (threaded)
1029 t_result(t_tasks4());
1030 else
1031 require_threads();
1034 static int T7_nprobs;
1035 static int T7_eflag;
1036 static int T7_sdflag;
1037 static isc_mutex_t T7_mx;
1038 static isc_condition_t T7_cv;
1040 static int T7_nfails;
1042 static void
1043 t7_event1(isc_task_t *task, isc_event_t *event) {
1044 UNUSED(task);
1046 ++T7_eflag;
1048 isc_event_free(&event);
1051 static void
1052 t7_sde(isc_task_t *task, isc_event_t *event) {
1053 isc_result_t isc_result;
1055 UNUSED(task);
1057 isc_result = isc_mutex_lock(&T7_mx);
1058 if (isc_result != ISC_R_SUCCESS) {
1059 t_info("isc_mutex_lock failed %s\n",
1060 isc_result_totext(isc_result));
1061 ++T7_nprobs;
1064 ++T7_sdflag;
1066 isc_result = isc_condition_signal(&T7_cv);
1067 if (isc_result != ISC_R_SUCCESS) {
1068 t_info("isc_condition_signal failed %s\n",
1069 isc_result_totext(isc_result));
1070 ++T7_nprobs;
1073 isc_result = isc_mutex_unlock(&T7_mx);
1074 if (isc_result != ISC_R_SUCCESS) {
1075 t_info("isc_mutex_unlock failed %s\n",
1076 isc_result_totext(isc_result));
1077 ++T7_nprobs;
1080 isc_event_free(&event);
1083 static int
1084 t_tasks7(void) {
1085 int result;
1086 char *p;
1087 isc_mem_t *mctx;
1088 isc_taskmgr_t *tmgr;
1089 isc_task_t *task;
1090 unsigned int workers;
1091 isc_result_t isc_result;
1092 isc_eventtype_t event_type;
1093 isc_event_t *event;
1094 isc_time_t now;
1095 isc_interval_t interval;
1097 T7_nprobs = 0;
1098 T7_nfails = 0;
1099 T7_sdflag = 0;
1100 T7_eflag = 0;
1102 result = T_UNRESOLVED;
1103 event_type = 7;
1105 workers = 2;
1106 p = t_getenv("ISC_TASK_WORKERS");
1107 if (p != NULL)
1108 workers = atoi(p);
1110 mctx = NULL;
1111 isc_result = isc_mem_create(0, 0, &mctx);
1112 if (isc_result != ISC_R_SUCCESS) {
1113 t_info("isc_mem_create failed %s\n",
1114 isc_result_totext(isc_result));
1115 return(T_UNRESOLVED);
1118 isc_result = isc_mutex_init(&T7_mx);
1119 if (isc_result != ISC_R_SUCCESS) {
1120 t_info("isc_mutex_init failed %s\n",
1121 isc_result_totext(isc_result));
1122 isc_mem_destroy(&mctx);
1123 return(T_UNRESOLVED);
1126 isc_result = isc_condition_init(&T7_cv);
1127 if (isc_result != ISC_R_SUCCESS) {
1128 t_info("isc_condition_init failed %s\n",
1129 isc_result_totext(isc_result));
1130 DESTROYLOCK(&T7_mx);
1131 isc_mem_destroy(&mctx);
1132 return(T_UNRESOLVED);
1135 tmgr = NULL;
1136 isc_result = isc_taskmgr_create(mctx, workers, 0, &tmgr);
1137 if (isc_result != ISC_R_SUCCESS) {
1138 t_info("isc_taskmgr_create failed %s\n",
1139 isc_result_totext(isc_result));
1140 DESTROYLOCK(&T7_mx);
1141 isc_condition_destroy(&T7_cv);
1142 isc_mem_destroy(&mctx);
1143 return(T_UNRESOLVED);
1146 isc_result = isc_mutex_lock(&T7_mx);
1147 if (isc_result != ISC_R_SUCCESS) {
1148 t_info("isc_mutex_lock failed %s\n",
1149 isc_result_totext(isc_result));
1150 DESTROYLOCK(&T7_mx);
1151 isc_condition_destroy(&T7_cv);
1152 isc_taskmgr_destroy(&tmgr);
1153 isc_mem_destroy(&mctx);
1154 return(T_FAIL);
1157 task = NULL;
1158 isc_result = isc_task_create(tmgr, 0, &task);
1159 if (isc_result != ISC_R_SUCCESS) {
1160 t_info("isc_task_create failed %s\n",
1161 isc_result_totext(isc_result));
1162 DESTROYLOCK(&T7_mx);
1163 isc_condition_destroy(&T7_cv);
1164 isc_taskmgr_destroy(&tmgr);
1165 isc_mem_destroy(&mctx);
1166 return(T_FAIL);
1169 isc_result = isc_task_onshutdown(task, t7_sde, NULL);
1170 if (isc_result != ISC_R_SUCCESS) {
1171 t_info("isc_task_onshutdown returned %s\n",
1172 isc_result_totext(isc_result));
1173 DESTROYLOCK(&T7_mx);
1174 isc_condition_destroy(&T7_cv);
1175 isc_task_destroy(&task);
1176 isc_taskmgr_destroy(&tmgr);
1177 isc_mem_destroy(&mctx);
1178 return(T_UNRESOLVED);
1181 event = isc_event_allocate(mctx, &senders[1], event_type, t7_event1,
1182 NULL, sizeof(*event));
1183 isc_task_send(task, &event);
1185 isc_task_shutdown(task);
1187 interval.seconds = 5;
1188 interval.nanoseconds = 0;
1190 while (T7_sdflag == 0) {
1191 isc_result = isc_time_nowplusinterval(&now, &interval);
1192 if (isc_result != ISC_R_SUCCESS) {
1193 t_info("isc_time_nowplusinterval failed %s\n",
1194 isc_result_totext(isc_result));
1195 DESTROYLOCK(&T7_mx);
1196 isc_condition_destroy(&T7_cv);
1197 isc_task_destroy(&task);
1198 isc_taskmgr_destroy(&tmgr);
1199 isc_mem_destroy(&mctx);
1200 return(T_UNRESOLVED);
1203 isc_result = isc_condition_waituntil(&T7_cv, &T7_mx, &now);
1204 if (isc_result != ISC_R_SUCCESS) {
1205 t_info("isc_condition_waituntil returned %s\n",
1206 isc_result_totext(isc_result));
1207 DESTROYLOCK(&T7_mx);
1208 isc_condition_destroy(&T7_cv);
1209 isc_task_destroy(&task);
1210 isc_taskmgr_destroy(&tmgr);
1211 isc_mem_destroy(&mctx);
1212 return(T_FAIL);
1216 isc_result = isc_mutex_unlock(&T7_mx);
1217 if (isc_result != ISC_R_SUCCESS) {
1218 t_info("isc_mutex_unlock failed %s\n",
1219 isc_result_totext(isc_result));
1220 ++T7_nprobs;
1223 isc_task_detach(&task);
1224 isc_taskmgr_destroy(&tmgr);
1225 isc_mem_destroy(&mctx);
1226 isc_condition_destroy(&T7_cv);
1227 DESTROYLOCK(&T7_mx);
1229 result = T_UNRESOLVED;
1231 if (T7_eflag == 0)
1232 ++T7_nfails;
1234 if (T7_nfails != 0)
1235 result = T_FAIL;
1236 else if ((T7_nfails == 0) && (T7_nprobs == 0))
1237 result = T_PASS;
1239 return(result);
1242 static const char *a7 = "A call to isc_task_create() creates a task that can "
1243 "receive events.";
1245 static void
1246 t7(void) {
1247 t_assert("tasks", 7, T_REQUIRED, "%s", a7);
1249 if (threaded)
1250 t_result(t_tasks7());
1251 else
1252 require_threads();
1255 #define T10_SENDERCNT 3
1256 #define T10_TYPECNT 4
1257 #define T10_TAGCNT 5
1258 #define T10_NEVENTS (T10_SENDERCNT*T10_TYPECNT*T10_TAGCNT)
1259 #define T_CONTROL 99999
1261 static int T10_nprobs;
1262 static int T10_nfails;
1263 static int T10_startflag;
1264 static int T10_shutdownflag;
1265 static int T10_eventcnt;
1266 static isc_mutex_t T10_mx;
1267 static isc_condition_t T10_cv;
1269 static void *T10_purge_sender;
1270 static isc_eventtype_t T10_purge_type_first;
1271 static isc_eventtype_t T10_purge_type_last;
1272 static void *T10_purge_tag;
1273 static int T10_testrange;
1275 static void
1276 t10_event1(isc_task_t *task, isc_event_t *event) {
1277 isc_result_t isc_result;
1279 task = task;
1281 isc_result = isc_mutex_lock(&T10_mx);
1282 if (isc_result != ISC_R_SUCCESS) {
1283 t_info("isc_mutex_lock failed %s\n",
1284 isc_result_totext(isc_result));
1285 ++T10_nprobs;
1288 while (T10_startflag == 0) {
1289 isc_result = isc_condition_wait(&T10_cv, &T10_mx);
1290 if (isc_result != ISC_R_SUCCESS) {
1291 t_info("isc_mutex_lock failed %s\n",
1292 isc_result_totext(isc_result));
1293 ++T10_nprobs;
1297 isc_result = isc_mutex_unlock(&T10_mx);
1298 if (isc_result != ISC_R_SUCCESS) {
1299 t_info("isc_mutex_unlock failed %s\n",
1300 isc_result_totext(isc_result));
1301 ++T10_nprobs;
1304 isc_event_free(&event);
1307 static void
1308 t10_event2(isc_task_t *task, isc_event_t *event) {
1310 int sender_match;
1311 int type_match;
1312 int tag_match;
1314 task = task;
1316 sender_match = 0;
1317 type_match = 0;
1318 tag_match = 0;
1320 if (T_debug) {
1321 t_info("Event %p,%d,%p,%s\n",
1322 event->ev_sender,
1323 (int)event->ev_type,
1324 event->ev_tag,
1325 event->ev_attributes & ISC_EVENTATTR_NOPURGE ?
1326 "NP" : "P");
1329 if ((T10_purge_sender == NULL) ||
1330 (T10_purge_sender == event->ev_sender)) {
1331 sender_match = 1;
1333 if (T10_testrange == 0) {
1334 if (T10_purge_type_first == event->ev_type) {
1335 type_match = 1;
1337 } else {
1338 if ((T10_purge_type_first <= event->ev_type) &&
1339 (event->ev_type <= T10_purge_type_last)) {
1340 type_match = 1;
1343 if ((T10_purge_tag == NULL) ||
1344 (T10_purge_tag == event->ev_tag)) {
1345 tag_match = 1;
1348 if (sender_match && type_match && tag_match) {
1349 if (event->ev_attributes & ISC_EVENTATTR_NOPURGE) {
1350 t_info("event %p,%d,%p matched but was not purgable\n",
1351 event->ev_sender, (int)event->ev_type,
1352 event->ev_tag);
1353 ++T10_eventcnt;
1354 } else {
1355 t_info("*** event %p,%d,%p not purged\n",
1356 event->ev_sender, (int)event->ev_type,
1357 event->ev_tag);
1359 } else {
1360 ++T10_eventcnt;
1362 isc_event_free(&event);
1366 static void
1367 t10_sde(isc_task_t *task, isc_event_t *event) {
1368 isc_result_t isc_result;
1370 task = task;
1372 isc_result = isc_mutex_lock(&T10_mx);
1373 if (isc_result != ISC_R_SUCCESS) {
1374 t_info("isc_mutex_lock failed %s\n",
1375 isc_result_totext(isc_result));
1376 ++T10_nprobs;
1379 ++T10_shutdownflag;
1381 isc_result = isc_condition_signal(&T10_cv);
1382 if (isc_result != ISC_R_SUCCESS) {
1383 t_info("isc_condition_signal failed %s\n",
1384 isc_result_totext(isc_result));
1385 ++T10_nprobs;
1388 isc_result = isc_mutex_unlock(&T10_mx);
1389 if (isc_result != ISC_R_SUCCESS) {
1390 t_info("isc_mutex_unlock failed %s\n",
1391 isc_result_totext(isc_result));
1392 ++T10_nprobs;
1395 isc_event_free(&event);
1398 static void
1399 t_taskpurge_x(int sender, int type, int tag, void *purge_sender,
1400 int purge_type_first, int purge_type_last, void *purge_tag,
1401 int exp_nevents, int *nfails, int *nprobs, int testrange)
1403 char *p;
1404 isc_mem_t *mctx;
1405 isc_taskmgr_t *tmgr;
1406 isc_task_t *task;
1407 unsigned int workers;
1408 isc_result_t isc_result;
1409 isc_event_t *event;
1410 isc_time_t now;
1411 isc_interval_t interval;
1412 int sender_cnt;
1413 int type_cnt;
1414 int tag_cnt;
1415 int event_cnt;
1416 int cnt;
1417 int nevents;
1418 isc_event_t *eventtab[T10_NEVENTS];
1421 T10_startflag = 0;
1422 T10_shutdownflag = 0;
1423 T10_eventcnt = 0;
1424 T10_purge_sender = purge_sender;
1425 T10_purge_type_first = (isc_eventtype_t) purge_type_first;
1426 T10_purge_type_last = (isc_eventtype_t) purge_type_last;
1427 T10_purge_tag = purge_tag;
1428 T10_testrange = testrange;
1430 workers = 2;
1431 p = t_getenv("ISC_TASK_WORKERS");
1432 if (p != NULL)
1433 workers = atoi(p);
1435 mctx = NULL;
1436 isc_result = isc_mem_create(0, 0, &mctx);
1437 if (isc_result != ISC_R_SUCCESS) {
1438 t_info("isc_mem_create failed %s\n",
1439 isc_result_totext(isc_result));
1440 ++*nprobs;
1441 return;
1444 isc_result = isc_mutex_init(&T10_mx);
1445 if (isc_result != ISC_R_SUCCESS) {
1446 t_info("isc_mutex_init failed %s\n",
1447 isc_result_totext(isc_result));
1448 isc_mem_destroy(&mctx);
1449 ++*nprobs;
1450 return;
1453 isc_result = isc_condition_init(&T10_cv);
1454 if (isc_result != ISC_R_SUCCESS) {
1455 t_info("isc_condition_init failed %s\n",
1456 isc_result_totext(isc_result));
1457 isc_mem_destroy(&mctx);
1458 DESTROYLOCK(&T10_mx);
1459 ++*nprobs;
1460 return;
1463 tmgr = NULL;
1464 isc_result = isc_taskmgr_create(mctx, workers, 0, &tmgr);
1465 if (isc_result != ISC_R_SUCCESS) {
1466 t_info("isc_taskmgr_create failed %s\n",
1467 isc_result_totext(isc_result));
1468 isc_mem_destroy(&mctx);
1469 DESTROYLOCK(&T10_mx);
1470 isc_condition_destroy(&T10_cv);
1471 ++*nprobs;
1472 return;
1475 task = NULL;
1476 isc_result = isc_task_create(tmgr, 0, &task);
1477 if (isc_result != ISC_R_SUCCESS) {
1478 t_info("isc_task_create failed %s\n",
1479 isc_result_totext(isc_result));
1480 isc_taskmgr_destroy(&tmgr);
1481 isc_mem_destroy(&mctx);
1482 DESTROYLOCK(&T10_mx);
1483 isc_condition_destroy(&T10_cv);
1484 ++*nprobs;
1485 return;
1488 isc_result = isc_task_onshutdown(task, t10_sde, NULL);
1489 if (isc_result != ISC_R_SUCCESS) {
1490 t_info("isc_task_onshutdown returned %s\n",
1491 isc_result_totext(isc_result));
1492 isc_task_destroy(&task);
1493 isc_taskmgr_destroy(&tmgr);
1494 isc_mem_destroy(&mctx);
1495 DESTROYLOCK(&T10_mx);
1496 isc_condition_destroy(&T10_cv);
1497 ++*nprobs;
1498 return;
1502 * Block the task on T10_cv.
1504 event = isc_event_allocate(mctx, (void *)1, (isc_eventtype_t)T_CONTROL,
1505 t10_event1, NULL, sizeof(*event));
1507 isc_task_send(task, &event);
1510 * Fill the task's queue with some messages with varying
1511 * sender, type, tag, and purgable attribute values.
1514 event_cnt = 0;
1515 for (sender_cnt = 0; sender_cnt < T10_SENDERCNT; ++sender_cnt) {
1516 for (type_cnt = 0; type_cnt < T10_TYPECNT; ++type_cnt) {
1517 for (tag_cnt = 0; tag_cnt < T10_TAGCNT; ++tag_cnt) {
1518 eventtab[event_cnt] =
1519 isc_event_allocate(mctx,
1520 &senders[sender + sender_cnt],
1521 (isc_eventtype_t)(type + type_cnt),
1522 t10_event2, NULL, sizeof(*event));
1524 eventtab[event_cnt]->ev_tag =
1525 (void *)((uintptr_t)tag + tag_cnt);
1528 * Make all odd message non-purgable.
1530 if ((sender_cnt % 2) && (type_cnt %2) &&
1531 (tag_cnt %2))
1532 eventtab[event_cnt]->ev_attributes |=
1533 ISC_EVENTATTR_NOPURGE;
1534 ++event_cnt;
1539 for (cnt = 0; cnt < event_cnt; ++cnt)
1540 isc_task_send(task, &eventtab[cnt]);
1542 if (T_debug)
1543 t_info("%d events queued\n", cnt);
1545 if (testrange == 0) {
1547 * We're testing isc_task_purge.
1549 nevents = isc_task_purge(task, purge_sender,
1550 (isc_eventtype_t)purge_type_first,
1551 purge_tag);
1552 if (nevents != exp_nevents) {
1553 t_info("*** isc_task_purge returned %d, expected %d\n",
1554 nevents, exp_nevents);
1555 ++*nfails;
1556 } else if (T_debug)
1557 t_info("isc_task_purge returned %d\n", nevents);
1558 } else {
1560 * We're testing isc_task_purgerange.
1562 nevents = isc_task_purgerange(task, purge_sender,
1563 (isc_eventtype_t)purge_type_first,
1564 (isc_eventtype_t)purge_type_last,
1565 purge_tag);
1566 if (nevents != exp_nevents) {
1567 t_info("*** isc_task_purgerange returned %d, "
1568 "expected %d\n", nevents, exp_nevents);
1569 ++*nfails;
1570 } else if (T_debug)
1571 t_info("isc_task_purgerange returned %d\n", nevents);
1574 isc_result = isc_mutex_lock(&T10_mx);
1575 if (isc_result != ISC_R_SUCCESS) {
1576 t_info("isc_mutex_lock failed %s\n",
1577 isc_result_totext(isc_result));
1578 isc_task_destroy(&task);
1579 isc_taskmgr_destroy(&tmgr);
1580 isc_mem_destroy(&mctx);
1581 DESTROYLOCK(&T10_mx);
1582 isc_condition_destroy(&T10_cv);
1583 ++*nprobs;
1584 return;
1588 * Unblock the task, allowing event processing.
1590 T10_startflag = 1;
1591 isc_result = isc_condition_signal(&T10_cv);
1592 if (isc_result != ISC_R_SUCCESS) {
1593 t_info("isc_condition_signal failed %s\n",
1594 isc_result_totext(isc_result));
1595 ++*nprobs;
1598 isc_task_shutdown(task);
1600 interval.seconds = 5;
1601 interval.nanoseconds = 0;
1604 * Wait for shutdown processing to complete.
1606 while (T10_shutdownflag == 0) {
1607 isc_result = isc_time_nowplusinterval(&now, &interval);
1608 if (isc_result != ISC_R_SUCCESS) {
1609 t_info("isc_time_nowplusinterval failed %s\n",
1610 isc_result_totext(isc_result));
1611 isc_task_detach(&task);
1612 isc_taskmgr_destroy(&tmgr);
1613 isc_mem_destroy(&mctx);
1614 DESTROYLOCK(&T10_mx);
1615 isc_condition_destroy(&T10_cv);
1616 ++*nprobs;
1617 return;
1620 isc_result = isc_condition_waituntil(&T10_cv, &T10_mx, &now);
1621 if (isc_result != ISC_R_SUCCESS) {
1622 t_info("isc_condition_waituntil returned %s\n",
1623 isc_result_totext(isc_result));
1624 isc_task_detach(&task);
1625 isc_taskmgr_destroy(&tmgr);
1626 isc_mem_destroy(&mctx);
1627 DESTROYLOCK(&T10_mx);
1628 isc_condition_destroy(&T10_cv);
1629 ++*nfails;
1630 return;
1634 isc_result = isc_mutex_unlock(&T10_mx);
1635 if (isc_result != ISC_R_SUCCESS) {
1636 t_info("isc_mutex_unlock failed %s\n",
1637 isc_result_totext(isc_result));
1638 ++*nprobs;
1641 isc_task_detach(&task);
1642 isc_taskmgr_destroy(&tmgr);
1643 isc_mem_destroy(&mctx);
1644 DESTROYLOCK(&T10_mx);
1645 isc_condition_destroy(&T10_cv);
1647 if (T_debug)
1648 t_info("task processed %d events\n", T10_eventcnt);
1650 if ((T10_eventcnt + nevents) != event_cnt) {
1651 t_info("*** processed %d, purged %d, total %d\n",
1652 T10_eventcnt, nevents, event_cnt);
1653 ++*nfails;
1657 static int
1658 t_tasks10(void) {
1659 int result;
1661 T10_nprobs = 0;
1662 T10_nfails = 0;
1665 * Try purging on a specific sender.
1667 t_info("testing purge on 2,4,8 expecting 1\n");
1668 t_taskpurge_x(1, 4, 7, &senders[2], 4, 4, (void *)8, 1, &T10_nfails,
1669 &T10_nprobs, 0);
1672 * Try purging on all senders.
1674 t_info("testing purge on 0,4,8 expecting 3\n");
1675 t_taskpurge_x(1, 4, 7, NULL, 4, 4, (void *)8, 3, &T10_nfails,
1676 &T10_nprobs, 0);
1679 * Try purging on all senders, specified type, all tags.
1681 t_info("testing purge on 0,4,0 expecting 15\n");
1682 t_taskpurge_x(1, 4, 7, NULL, 4, 4, NULL, 15, &T10_nfails,
1683 &T10_nprobs, 0);
1686 * Try purging on a specified tag, no such type.
1688 t_info("testing purge on 0,99,8 expecting 0\n");
1689 t_taskpurge_x(1, 4, 7, NULL, 99, 99, (void *)8, 0, &T10_nfails,
1690 &T10_nprobs, 0);
1693 * Try purging on specified sender, type, all tags.
1695 t_info("testing purge on 0,5,0 expecting 5\n");
1696 t_taskpurge_x(1, 4, 7, &senders[3], 5, 5, NULL, 5, &T10_nfails,
1697 &T10_nprobs, 0);
1699 result = T_UNRESOLVED;
1701 if ((T10_nfails == 0) && (T10_nprobs == 0))
1702 result = T_PASS;
1703 else if (T10_nfails != 0)
1704 result = T_FAIL;
1706 return(result);
1709 static const char *a10 =
1710 "A call to isc_task_purge(task, sender, type, tag) "
1711 "purges all events of type 'type' and with tag 'tag' "
1712 "not marked as unpurgable from sender from the task's "
1713 "queue and returns the number of events purged.";
1715 static void
1716 t10(void) {
1717 t_assert("tasks", 10, T_REQUIRED, "%s", a10);
1719 if (threaded)
1720 t_result(t_tasks10());
1721 else
1722 require_threads();
1725 static int T11_nprobs;
1726 static int T11_nfails;
1727 static int T11_startflag;
1728 static int T11_shutdownflag;
1729 static int T11_eventcnt;
1730 static isc_mutex_t T11_mx;
1731 static isc_condition_t T11_cv;
1733 static void
1734 t11_event1(isc_task_t *task, isc_event_t *event) {
1735 isc_result_t isc_result;
1737 task = task;
1739 isc_result = isc_mutex_lock(&T11_mx);
1740 if (isc_result != ISC_R_SUCCESS) {
1741 t_info("isc_mutex_lock failed %s\n",
1742 isc_result_totext(isc_result));
1743 ++T11_nprobs;
1746 while (T11_startflag == 0) {
1747 isc_result = isc_condition_wait(&T11_cv, &T11_mx);
1748 if (isc_result != ISC_R_SUCCESS) {
1749 t_info("isc_mutex_lock failed %s\n",
1750 isc_result_totext(isc_result));
1751 ++T11_nprobs;
1755 isc_result = isc_mutex_unlock(&T11_mx);
1756 if (isc_result != ISC_R_SUCCESS) {
1757 t_info("isc_mutex_unlock failed %s\n",
1758 isc_result_totext(isc_result));
1759 ++T11_nprobs;
1762 isc_event_free(&event);
1765 static void
1766 t11_event2(isc_task_t *task, isc_event_t *event) {
1767 UNUSED(task);
1769 ++T11_eventcnt;
1770 isc_event_free(&event);
1774 static void
1775 t11_sde(isc_task_t *task, isc_event_t *event) {
1776 isc_result_t isc_result;
1778 UNUSED(task);
1780 isc_result = isc_mutex_lock(&T11_mx);
1781 if (isc_result != ISC_R_SUCCESS) {
1782 t_info("isc_mutex_lock failed %s\n",
1783 isc_result_totext(isc_result));
1784 ++T11_nprobs;
1787 ++T11_shutdownflag;
1789 isc_result = isc_condition_signal(&T11_cv);
1790 if (isc_result != ISC_R_SUCCESS) {
1791 t_info("isc_condition_signal failed %s\n",
1792 isc_result_totext(isc_result));
1793 ++T11_nprobs;
1796 isc_result = isc_mutex_unlock(&T11_mx);
1797 if (isc_result != ISC_R_SUCCESS) {
1798 t_info("isc_mutex_unlock failed %s\n",
1799 isc_result_totext(isc_result));
1800 ++T11_nprobs;
1803 isc_event_free(&event);
1806 static int
1807 t_tasks11(int purgable) {
1808 char *p;
1809 isc_mem_t *mctx;
1810 isc_taskmgr_t *tmgr;
1811 isc_task_t *task;
1812 isc_boolean_t rval;
1813 unsigned int workers;
1814 isc_result_t isc_result;
1815 isc_event_t *event1;
1816 isc_event_t *event2, *event2_clone;
1817 isc_time_t now;
1818 isc_interval_t interval;
1819 int result;
1821 T11_startflag = 0;
1822 T11_shutdownflag = 0;
1823 T11_eventcnt = 0;
1825 workers = 2;
1826 p = t_getenv("ISC_TASK_WORKERS");
1827 if (p != NULL)
1828 workers = atoi(p);
1830 mctx = NULL;
1831 isc_result = isc_mem_create(0, 0, &mctx);
1832 if (isc_result != ISC_R_SUCCESS) {
1833 t_info("isc_mem_create failed %s\n",
1834 isc_result_totext(isc_result));
1835 return(T_UNRESOLVED);
1838 isc_result = isc_mutex_init(&T11_mx);
1839 if (isc_result != ISC_R_SUCCESS) {
1840 t_info("isc_mutex_init failed %s\n",
1841 isc_result_totext(isc_result));
1842 isc_mem_destroy(&mctx);
1843 return(T_UNRESOLVED);
1846 isc_result = isc_condition_init(&T11_cv);
1847 if (isc_result != ISC_R_SUCCESS) {
1848 t_info("isc_condition_init failed %s\n",
1849 isc_result_totext(isc_result));
1850 isc_mem_destroy(&mctx);
1851 DESTROYLOCK(&T11_mx);
1852 return(T_UNRESOLVED);
1855 tmgr = NULL;
1856 isc_result = isc_taskmgr_create(mctx, workers, 0, &tmgr);
1857 if (isc_result != ISC_R_SUCCESS) {
1858 t_info("isc_taskmgr_create failed %s\n",
1859 isc_result_totext(isc_result));
1860 isc_mem_destroy(&mctx);
1861 DESTROYLOCK(&T11_mx);
1862 isc_condition_destroy(&T11_cv);
1863 return(T_UNRESOLVED);
1866 task = NULL;
1867 isc_result = isc_task_create(tmgr, 0, &task);
1868 if (isc_result != ISC_R_SUCCESS) {
1869 t_info("isc_task_create failed %s\n",
1870 isc_result_totext(isc_result));
1871 isc_taskmgr_destroy(&tmgr);
1872 isc_mem_destroy(&mctx);
1873 DESTROYLOCK(&T11_mx);
1874 isc_condition_destroy(&T11_cv);
1875 return(T_UNRESOLVED);
1878 isc_result = isc_task_onshutdown(task, t11_sde, NULL);
1879 if (isc_result != ISC_R_SUCCESS) {
1880 t_info("isc_task_onshutdown returned %s\n",
1881 isc_result_totext(isc_result));
1882 isc_task_destroy(&task);
1883 isc_taskmgr_destroy(&tmgr);
1884 isc_mem_destroy(&mctx);
1885 DESTROYLOCK(&T11_mx);
1886 isc_condition_destroy(&T11_cv);
1887 return(T_UNRESOLVED);
1891 * Block the task on T11_cv.
1893 event1 = isc_event_allocate(mctx, (void *)1, (isc_eventtype_t)1,
1894 t11_event1, NULL, sizeof(*event1));
1896 isc_task_send(task, &event1);
1898 event2 = isc_event_allocate(mctx, (void *)1, (isc_eventtype_t)1,
1899 t11_event2, NULL, sizeof(*event2));
1900 event2_clone = event2;
1901 if (purgable)
1902 event2->ev_attributes &= ~ISC_EVENTATTR_NOPURGE;
1903 else
1904 event2->ev_attributes |= ISC_EVENTATTR_NOPURGE;
1906 isc_task_send(task, &event2);
1908 rval = isc_task_purgeevent(task, event2_clone);
1909 if (rval != (purgable ? ISC_TRUE : ISC_FALSE)) {
1910 t_info("isc_task_purgeevent returned %s, expected %s\n",
1911 (rval ? "ISC_TRUE" : "ISC_FALSE"),
1912 (purgable ? "ISC_TRUE" : "ISC_FALSE"));
1913 ++T11_nfails;
1916 isc_result = isc_mutex_lock(&T11_mx);
1917 if (isc_result != ISC_R_SUCCESS) {
1918 t_info("isc_mutex_lock failed %s\n",
1919 isc_result_totext(isc_result));
1920 ++T11_nprobs;
1924 * Unblock the task, allowing event processing.
1926 T11_startflag = 1;
1927 isc_result = isc_condition_signal(&T11_cv);
1928 if (isc_result != ISC_R_SUCCESS) {
1929 t_info("isc_condition_signal failed %s\n",
1930 isc_result_totext(isc_result));
1931 ++T11_nprobs;
1934 isc_task_shutdown(task);
1936 interval.seconds = 5;
1937 interval.nanoseconds = 0;
1940 * Wait for shutdown processing to complete.
1942 while (T11_shutdownflag == 0) {
1943 isc_result = isc_time_nowplusinterval(&now, &interval);
1944 if (isc_result != ISC_R_SUCCESS) {
1945 t_info("isc_time_nowplusinterval failed %s\n",
1946 isc_result_totext(isc_result));
1947 ++T11_nprobs;
1950 isc_result = isc_condition_waituntil(&T11_cv, &T11_mx, &now);
1951 if (isc_result != ISC_R_SUCCESS) {
1952 t_info("isc_condition_waituntil returned %s\n",
1953 isc_result_totext(isc_result));
1954 ++T11_nprobs;
1958 isc_result = isc_mutex_unlock(&T11_mx);
1959 if (isc_result != ISC_R_SUCCESS) {
1960 t_info("isc_mutex_unlock failed %s\n",
1961 isc_result_totext(isc_result));
1962 ++T11_nprobs;
1965 isc_task_detach(&task);
1966 isc_taskmgr_destroy(&tmgr);
1967 isc_mem_destroy(&mctx);
1968 DESTROYLOCK(&T11_mx);
1969 isc_condition_destroy(&T11_cv);
1971 if (T11_eventcnt != (purgable ? 0 : 1)) {
1972 t_info("Event was %s purged\n",
1973 (purgable ? "not" : "unexpectedly"));
1974 ++T11_nfails;
1977 result = T_UNRESOLVED;
1979 if ((T11_nfails == 0) && (T11_nprobs == 0))
1980 result = T_PASS;
1981 else if (T11_nfails)
1982 result = T_FAIL;
1984 return(result);
1987 static const char *a11 =
1988 "When the event is marked as purgable, a call to "
1989 "isc_task_purgeevent(task, event) purges the event 'event' "
1990 "from the task's queue and returns ISC_TRUE.";
1992 static void
1993 t11(void) {
1994 t_assert("tasks", 11, T_REQUIRED, "%s", a11);
1996 if (threaded)
1997 t_result(t_tasks11(1));
1998 else
1999 require_threads();
2002 static const char *a12 =
2003 "When the event is not marked as purgable, a call to "
2004 "isc_task_purgeevent(task, event) does not purge the "
2005 "event 'event' from the task's queue and returns "
2006 "ISC_FALSE.";
2008 static int
2009 t_tasks12(void) {
2010 return(t_tasks11(0));
2013 static void
2014 t12(void) {
2015 t_assert("tasks", 12, T_REQUIRED, "%s", a12);
2017 if (threaded)
2018 t_result(t_tasks12());
2019 else
2020 require_threads();
2023 static int T13_nfails;
2024 static int T13_nprobs;
2026 static const char *a13 =
2027 "A call to "
2028 "isc_event_purgerange(task, sender, first, last, tag) "
2029 "purges all events not marked unpurgable from "
2030 "sender 'sender' and of type within the range 'first' "
2031 "to 'last' inclusive from the task's event queue and "
2032 "returns the number of tasks purged.";
2034 static int
2035 t_tasks13(void) {
2036 int result;
2038 T13_nfails = 0;
2039 T13_nprobs = 0;
2042 * First let's try the same cases we used in t10.
2046 * Try purging on a specific sender.
2048 t_info("testing purge on 2,4,8 expecting 1\n");
2049 t_taskpurge_x(1, 4, 7, &senders[2], 4, 4, (void *)8, 1,
2050 &T13_nfails, &T13_nprobs, 1);
2053 * Try purging on all senders.
2055 t_info("testing purge on 0,4,8 expecting 3\n");
2056 t_taskpurge_x(1, 4, 7, NULL, 4, 4, (void *)8, 3,
2057 &T13_nfails, &T13_nprobs, 1);
2060 * Try purging on all senders, specified type, all tags.
2062 t_info("testing purge on 0,4,0 expecting 15\n");
2063 t_taskpurge_x(1, 4, 7, NULL, 4, 4, NULL, 15, &T13_nfails, &T13_nprobs, 1);
2066 * Try purging on a specified tag, no such type.
2068 t_info("testing purge on 0,99,8 expecting 0\n");
2069 t_taskpurge_x(1, 4, 7, NULL, 99, 99, (void *)8, 0,
2070 &T13_nfails, &T13_nprobs, 1);
2073 * Try purging on specified sender, type, all tags.
2075 t_info("testing purge on 3,5,0 expecting 5\n");
2076 t_taskpurge_x(1, 4, 7, &senders[3], 5, 5, 0, 5, &T13_nfails, &T13_nprobs, 1);
2079 * Now let's try some ranges.
2082 t_info("testing purgerange on 2,4-5,8 expecting 2\n");
2083 t_taskpurge_x(1, 4, 7, &senders[2], 4, 5, (void *)8, 1,
2084 &T13_nfails, &T13_nprobs, 1);
2087 * Try purging on all senders.
2089 t_info("testing purge on 0,4-5,8 expecting 5\n");
2090 t_taskpurge_x(1, 4, 7, NULL, 4, 5, (void *)8, 5,
2091 &T13_nfails, &T13_nprobs, 1);
2094 * Try purging on all senders, specified type, all tags.
2096 t_info("testing purge on 0,5-6,0 expecting 28\n");
2097 t_taskpurge_x(1, 4, 7, NULL, 5, 6, NULL, 28, &T13_nfails, &T13_nprobs, 1);
2100 * Try purging on a specified tag, no such type.
2102 t_info("testing purge on 0,99-101,8 expecting 0\n");
2103 t_taskpurge_x(1, 4, 7, NULL, 99, 101, (void *)8, 0,
2104 &T13_nfails, &T13_nprobs, 1);
2107 * Try purging on specified sender, type, all tags.
2109 t_info("testing purge on 3,5-6,0 expecting 10\n");
2110 t_taskpurge_x(1, 4, 7, &senders[3], 5, 6, NULL, 10, &T13_nfails,
2111 &T13_nprobs, 1);
2113 result = T_UNRESOLVED;
2115 if ((T13_nfails == 0) && (T13_nprobs == 0))
2116 result = T_PASS;
2117 else if (T13_nfails)
2118 result = T_FAIL;
2120 return (result);
2123 static void
2124 t13(void) {
2125 t_assert("tasks", 13, T_REQUIRED, "%s", a13);
2127 if (threaded)
2128 t_result(t_tasks13());
2129 else
2130 require_threads();
2133 #define T14_NTASKS 10
2134 #define T14_EXCLTASK 6
2136 int t14_exclusiveerror = ISC_R_SUCCESS;
2137 int t14_error = 0;
2138 int t14_done = 0;
2140 int spin(int n);
2142 int t14_active[T14_NTASKS];
2144 static void
2145 t14_callback(isc_task_t *task, isc_event_t *event) {
2146 int taskno = *(int *)(event->ev_arg);
2149 t_info("task enter %d\n", taskno);
2150 if (taskno == T14_EXCLTASK) {
2151 int i;
2152 t14_exclusiveerror = isc_task_beginexclusive(task);
2153 if (t14_exclusiveerror == ISC_R_SUCCESS)
2154 t_info("task %d got exclusive access\n", taskno);
2155 else
2156 t_info("task %d failed to got exclusive access: %d\n",
2157 taskno, t14_exclusiveerror);
2158 for (i = 0; i < T14_NTASKS; i++) {
2159 t_info("task %d state %d\n", i , t14_active[i]);
2160 if (t14_active[i])
2161 t14_error++;
2163 isc_task_endexclusive(task);
2164 t14_done = 1;
2165 } else {
2166 t14_active[taskno]++;
2167 (void) spin(10000000);
2168 t14_active[taskno]--;
2170 t_info("task exit %d\n", taskno);
2171 if (t14_done) {
2172 isc_mem_put(event->ev_destroy_arg, event->ev_arg, sizeof (int));
2173 isc_event_free(&event);
2174 } else {
2175 isc_task_send(task, &event);
2179 int spin(int n) {
2180 int i;
2181 int r = 0;
2182 for (i = 0; i < n; i++) {
2183 r += i;
2184 if (r > 1000000)
2185 r = 0;
2187 return (r);
2190 static int
2191 t_tasks14(void) {
2192 char *p;
2193 isc_mem_t *mctx;
2194 isc_taskmgr_t *manager;
2195 isc_task_t *tasks[T14_NTASKS];
2196 unsigned int workers;
2197 isc_result_t isc_result;
2198 int i;
2200 manager = NULL;
2201 mctx = NULL;
2203 for (i = 0; i < T14_NTASKS; i++)
2204 tasks[i] = NULL;
2206 workers = 4;
2207 p = t_getenv("ISC_TASK_WORKERS");
2208 if (p != NULL)
2209 workers = atoi(p);
2210 if (workers < 1) {
2211 t_info("Bad config value for ISC_TASK_WORKERS, %d\n", workers);
2212 return(T_UNRESOLVED);
2215 isc_result = isc_mem_create(0, 0, &mctx);
2216 if (isc_result != ISC_R_SUCCESS) {
2217 t_info("isc_mem_create failed %d\n", isc_result);
2218 return(T_UNRESOLVED);
2221 isc_result = isc_taskmgr_create(mctx, workers, 0, &manager);
2222 if (isc_result != ISC_R_SUCCESS) {
2223 t_info("isc_taskmgr_create failed %d\n", isc_result);
2224 return(T_FAIL);
2227 for (i = 0; i < T14_NTASKS; i++) {
2228 isc_event_t *event;
2229 int *v;
2231 isc_result = isc_task_create(manager, 0, &tasks[i]);
2232 if (isc_result != ISC_R_SUCCESS) {
2233 t_info("isc_task_create failed %d\n", isc_result);
2234 return(T_FAIL);
2237 v = isc_mem_get(mctx, sizeof *v);
2238 if (v == NULL) {
2239 isc_task_detach(&tasks[i]);
2240 t_info("isc_mem_get failed\n");
2241 return(T_FAIL);
2243 *v = i;
2245 event = isc_event_allocate(mctx, NULL, 1, t14_callback,
2246 v, sizeof(*event));
2247 if (event == NULL) {
2248 isc_mem_put(mctx, v, sizeof *v);
2249 t_info("isc_event_allocate failed\n");
2250 return(T_UNRESOLVED);
2252 isc_task_send(tasks[i], &event);
2255 for (i = 0; i < T14_NTASKS; i++) {
2256 isc_task_detach(&tasks[i]);
2259 isc_taskmgr_destroy(&manager);
2261 if (t14_exclusiveerror != ISC_R_SUCCESS || t14_error) {
2262 if (t14_exclusiveerror != ISC_R_SUCCESS)
2263 t_info("isc_task_beginexclusive() failed\n");
2264 if (t14_error)
2265 t_info("mutual access occurred\n");
2266 return(T_FAIL);
2269 isc_mem_destroy(&mctx);
2270 return(T_PASS);
2273 static void
2274 t14(void) {
2275 int result;
2277 t_assert("tasks", 14, T_REQUIRED, "%s",
2278 "isc_task_beginexclusive() gets exclusive access");
2279 result = t_tasks14();
2280 t_result(result);
2283 testspec_t T_testlist[] = {
2284 { t1, "basic task subsystem" },
2285 { t2, "maxtasks" },
2286 { t3, "isc_task_shutdown" },
2287 { t4, "isc_task_shutdown" },
2288 { t7, "isc_task_create" },
2289 { t10, "isc_task_purge" },
2290 { t11, "isc_task_purgeevent" },
2291 { t12, "isc_task_purgeevent" },
2292 { t13, "isc_task_purgerange" },
2293 { t14, "isc_task_beginexclusive" },
2294 { NULL, NULL }