1 /* $NetBSD: t_tasks.c,v 1.7 2014/12/10 04:37:54 christos Exp $ */
2
3 /*
4 * Copyright (C) 2004, 2005, 2007, 2009, 2011, 2013, 2014 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1998-2001 Internet Software Consortium.
6 *
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.
10 *
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.
18 */
19
20 /* Id: t_tasks.c,v 1.49 2011/07/27 07:45:55 marka Exp */
21
22 #include <config.h>
23
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>
36
37 #include <tests/t_api.h>
38
39
40 #ifdef ISC_PLATFORM_USETHREADS
41 isc_boolean_t threaded = ISC_TRUE;
42 #else
43 isc_boolean_t threaded = ISC_FALSE;
44 #endif
45
46 static int senders[4];
47
48 static void
require_threads(void)49 require_threads(void) {
50 t_info("This test requires threads\n");
51 t_result(T_THREADONLY);
52 return;
53 }
54
55 static void
t1_callback(isc_task_t * task,isc_event_t * event)56 t1_callback(isc_task_t *task, isc_event_t *event) {
57 int i;
58 int j;
59
60 UNUSED(task);
61
62 j = 0;
63
64 for (i = 0; i < 1000000; i++)
65 j += 100;
66
67 t_info("task %s\n", (char *)event->ev_arg);
68 isc_event_free(&event);
69 }
70
71 static void
t1_shutdown(isc_task_t * task,isc_event_t * event)72 t1_shutdown(isc_task_t *task, isc_event_t *event) {
73
74 UNUSED(task);
75
76 t_info("shutdown %s\n", (char *)event->ev_arg);
77 isc_event_free(&event);
78 }
79
80 static void
my_tick(isc_task_t * task,isc_event_t * event)81 my_tick(isc_task_t *task, isc_event_t *event) {
82
83 UNUSED(task);
84
85 t_info("%s\n", (char *)event->ev_arg);
86 isc_event_free(&event);
87 }
88
89 /*
90 * Adapted from RTH's original task_test program
91 */
92
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";
99
100 static int
t_tasks1(void)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;
117
118 manager = NULL;
119 task1 = NULL;
120 task2 = NULL;
121 task3 = NULL;
122 task4 = NULL;
123 mctx = NULL;
124
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);
132 }
133
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);
138 }
139
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);
144 }
145
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);
150 }
151
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);
156 }
157
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);
162 }
163
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);
168 }
169
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);
174 }
175
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);
180 }
181
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);
186 }
187
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);
192 }
193
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);
199 }
200
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);
210 }
211
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);
221 }
222
223
224 #ifndef WIN32
225 sleep(2);
226 #else
227 Sleep(2000);
228 #endif
229
230 /*
231 * Note: (void *)1 is used as a sender here, since some compilers
232 * don't like casting a function pointer to a (void *).
233 *
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.
237 */
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);
243 }
244
245 isc_task_send(task1, &event);
246
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);
252 }
253
254 isc_task_send(task1, &event);
255
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);
261 }
262
263 isc_task_send(task1, &event);
264
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);
270 }
271
272 isc_task_send(task1, &event);
273
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);
279 }
280
281 isc_task_send(task1, &event);
282
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);
288 }
289
290 isc_task_send(task1, &event);
291
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);
297 }
298
299 isc_task_send(task1, &event);
300
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);
306 }
307
308 isc_task_send(task1, &event);
309
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);
315 }
316
317 isc_task_send(task1, &event);
318
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);
324 }
325
326 isc_task_send(task2, &event);
327
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);
333 }
334
335 isc_task_send(task3, &event);
336
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);
342 }
343
344 isc_task_send(task4, &event);
345
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);
351 }
352
353 isc_task_send(task2, &event);
354
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);
360 }
361
362 isc_task_send(task3, &event);
363
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);
369 }
370
371 isc_task_send(task4, &event);
372
373 (void)isc_task_purge(task3, NULL, 0, 0);
374
375 isc_task_detach(&task1);
376 isc_task_detach(&task2);
377 isc_task_detach(&task3);
378 isc_task_detach(&task4);
379
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);
389
390 isc_mem_destroy(&mctx);
391 return(T_PASS);
392 }
393
394 static const char *a1 = "The task subsystem can create and manage tasks";
395
396 static void
t1(void)397 t1(void) {
398 int result;
399
400 t_assert("tasks", 1, T_REQUIRED, "%s", a1);
401 result = t_tasks1();
402 t_result(result);
403 }
404
405 #define T2_NTASKS 10000
406
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;
416
417 static void
t2_shutdown(isc_task_t * task,isc_event_t * event)418 t2_shutdown(isc_task_t *task, isc_event_t *event) {
419
420 isc_result_t isc_result;
421
422 UNUSED(task);
423
424 if (event->ev_arg != NULL) {
425 isc_task_destroy((isc_task_t**) &event->ev_arg);
426 }
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;
432 }
433
434 T2_done = 1;
435
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;
440 }
441
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;
446 }
447
448 isc_event_free(&T2_event);
449 isc_taskmgr_destroy(&T2_manager);
450 isc_mem_destroy(&T2_mctx);
451 }
452 }
453
454 static void
t2_callback(isc_task_t * task,isc_event_t * event)455 t2_callback(isc_task_t *task, isc_event_t *event) {
456 isc_result_t isc_result;
457 isc_task_t *newtask;
458
459 ++T2_ntasks;
460
461 if (T_debug && ((T2_ntasks % 100) == 0)) {
462 t_info("T2_ntasks %d\n", T2_ntasks);
463 }
464
465 if (event->ev_arg) {
466
467 event->ev_arg = (void *)(((uintptr_t) event->ev_arg) - 1);
468
469 /*
470 * Create a new task and forward the message.
471 */
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;
478 }
479
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;
487 }
488
489 isc_task_send(newtask, &event);
490 } else {
491 /*
492 * Time to unwind, shutdown should perc back up.
493 */
494 isc_task_destroy(&task);
495 }
496 }
497
498 static int
t_tasks2(void)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;
506
507 T2_manager = NULL;
508 T2_done = 0;
509 T2_nprobs = 0;
510 T2_nfails = 0;
511 T2_ntasks = 0;
512
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);
520 }
521
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);
531 }
532
533 t_info("Testing with %lu tasks\n", (unsigned long)ntasks);
534
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);
539 }
540
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);
545 }
546
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);
551 }
552
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);
557 }
558
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);
564 }
565
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);
570 }
571
572 t2_callback(NULL, T2_event);
573
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);
579 }
580 }
581
582 result = T_UNRESOLVED;
583
584 if ((T2_nfails == 0) && (T2_nprobs == 0))
585 result = T_PASS;
586 else if (T2_nfails != 0)
587 result = T_FAIL;
588
589 return(result);
590 }
591
592 static const char *a2 = "The task subsystem can create ISC_TASKS_MIN tasks";
593
594 static void
t2(void)595 t2(void) {
596 t_assert("tasks", 2, T_REQUIRED, "%s", a2);
597
598 if (threaded)
599 t_result(t_tasks2());
600 else
601 require_threads();
602 }
603
604 #define T3_NEVENTS 256
605
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;
613
614 static void
t3_sde1(isc_task_t * task,isc_event_t * event)615 t3_sde1(isc_task_t *task, isc_event_t *event) {
616
617 UNUSED(task);
618
619 if (T3_nevents != T3_NEVENTS) {
620 t_info("Some events were not processed\n");
621 ++T3_nprobs;
622 }
623 if (T3_nsdevents == 1) {
624 ++T3_nsdevents;
625 } else {
626 t_info("Shutdown events not processed in LIFO order\n");
627 ++T3_nfails;
628 }
629 isc_event_free(&event);
630 }
631
632 static void
t3_sde2(isc_task_t * task,isc_event_t * event)633 t3_sde2(isc_task_t *task, isc_event_t *event) {
634
635 UNUSED(task);
636
637 if (T3_nevents != T3_NEVENTS) {
638 t_info("Some events were not processed\n");
639 ++T3_nprobs;
640 }
641 if (T3_nsdevents == 0) {
642 ++T3_nsdevents;
643 } else {
644 t_info("Shutdown events not processed in LIFO order\n");
645 ++T3_nfails;
646 }
647 isc_event_free(&event);
648 }
649
650 static void
t3_event1(isc_task_t * task,isc_event_t * event)651 t3_event1(isc_task_t *task, isc_event_t *event) {
652 isc_result_t isc_result;
653
654 UNUSED(task);
655
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;
661 }
662 while (T3_flag != 1) {
663 (void) isc_condition_wait(&T3_cv, &T3_mx);
664 }
665
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;
671 }
672 isc_event_free(&event);
673 }
674
675 static void
t3_event2(isc_task_t * task,isc_event_t * event)676 t3_event2(isc_task_t *task, isc_event_t *event) {
677 UNUSED(task);
678
679 ++T3_nevents;
680 isc_event_free(&event);
681 }
682
683 static int
t_tasks3(void)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;
695
696 T3_flag = 0;
697 T3_nevents = 0;
698 T3_nsdevents = 0;
699 T3_nfails = 0;
700 T3_nprobs = 0;
701
702 event_type = 3;
703
704 workers = 2;
705 p = t_getenv("ISC_TASK_WORKERS");
706 if (p != NULL)
707 workers = atoi(p);
708
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);
715 }
716
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);
723 }
724
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);
731 }
732
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);
740 }
741
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);
749 }
750
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);
760 }
761
762 /*
763 * This event causes the task to wait on T3_cv.
764 */
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);
774 }
775 isc_task_send(task, &event);
776
777 /*
778 * Now we fill up the task's event queue with some events.
779 */
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);
790 }
791 isc_task_send(task, &event);
792 }
793
794 /*
795 * Now we register two shutdown events.
796 */
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);
806 }
807
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);
817 }
818
819 isc_task_shutdown(task);
820
821 /*
822 * Now we free the task by signaling T3_cv.
823 */
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;
830 }
831
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;
837 }
838
839
840 isc_task_detach(&task);
841 isc_taskmgr_destroy(&tmgr);
842 isc_mem_destroy(&mctx);
843
844 if (T3_nsdevents != 2) {
845 t_info("T3_nsdevents == %d, expected 2\n", T3_nsdevents);
846 ++T3_nfails;
847 }
848
849 result = T_UNRESOLVED;
850
851 if (T3_nfails != 0)
852 result = T_FAIL;
853 else if ((T3_nfails == 0) && (T3_nprobs == 0))
854 result = T_PASS;
855
856 return(result);
857 }
858
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
t3(void)864 t3(void) {
865 t_assert("tasks", 3, T_REQUIRED, "%s", a3);
866
867 if (threaded)
868 t_result(t_tasks3());
869 else
870 require_threads();
871 }
872
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;
878
879 static void
t4_event1(isc_task_t * task,isc_event_t * event)880 t4_event1(isc_task_t *task, isc_event_t *event) {
881 isc_result_t isc_result;
882
883 UNUSED(task);
884
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;
890 }
891 while (T4_flag != 1) {
892 (void) isc_condition_wait(&T4_cv, &T4_mx);
893 }
894
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;
900 }
901 isc_event_free(&event);
902 }
903
904 static void
t4_sde(isc_task_t * task,isc_event_t * event)905 t4_sde(isc_task_t *task, isc_event_t *event) {
906 UNUSED(task);
907
908 /*
909 * No-op.
910 */
911
912 isc_event_free(&event);
913 }
914
915 static int
t_tasks4(void)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;
926
927 T4_nprobs = 0;
928 T4_nfails = 0;
929 T4_flag = 0;
930
931 event_type = 4;
932
933 workers = 2;
934 p = t_getenv("ISC_TASK_WORKERS");
935 if (p != NULL)
936 workers = atoi(p);
937
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);
944 }
945
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);
952 }
953
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);
961 }
962
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);
972 }
973
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);
983 }
984
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);
995 }
996
997 /*
998 * This event causes the task to wait on T4_cv.
999 */
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);
1010 }
1011 isc_task_send(task, &event);
1012
1013 isc_task_shutdown(task);
1014
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;
1020 }
1021
1022 /*
1023 * Release the task.
1024 */
1025 T4_flag = 1;
1026
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;
1032 }
1033
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;
1039 }
1040
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);
1046
1047 result = T_UNRESOLVED;
1048
1049 if (T4_nfails != 0)
1050 result = T_FAIL;
1051 else if ((T4_nfails == 0) && (T4_nprobs == 0))
1052 result = T_PASS;
1053
1054 return(result);
1055 }
1056
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.";
1060
1061 static void
t4(void)1062 t4(void) {
1063 t_assert("tasks", 4, T_REQUIRED, "%s", a4);
1064
1065 if (threaded)
1066 t_result(t_tasks4());
1067 else
1068 require_threads();
1069 }
1070
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;
1076
1077 static int T7_nfails;
1078
1079 static void
t7_event1(isc_task_t * task,isc_event_t * event)1080 t7_event1(isc_task_t *task, isc_event_t *event) {
1081 UNUSED(task);
1082
1083 ++T7_eflag;
1084
1085 isc_event_free(&event);
1086 }
1087
1088 static void
t7_sde(isc_task_t * task,isc_event_t * event)1089 t7_sde(isc_task_t *task, isc_event_t *event) {
1090 isc_result_t isc_result;
1091
1092 UNUSED(task);
1093
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;
1099 }
1100
1101 ++T7_sdflag;
1102
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;
1108 }
1109
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;
1115 }
1116
1117 isc_event_free(&event);
1118 }
1119
1120 static int
t_tasks7(void)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;
1133
1134 T7_nprobs = 0;
1135 T7_nfails = 0;
1136 T7_sdflag = 0;
1137 T7_eflag = 0;
1138
1139 event_type = 7;
1140
1141 workers = 2;
1142 p = t_getenv("ISC_TASK_WORKERS");
1143 if (p != NULL)
1144 workers = atoi(p);
1145
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);
1152 }
1153
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);
1160 }
1161
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);
1169 }
1170
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);
1180 }
1181
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);
1191 }
1192
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);
1203 }
1204
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);
1215 }
1216
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);
1227 }
1228 isc_task_send(task, &event);
1229
1230 isc_task_shutdown(task);
1231
1232 isc_interval_set(&interval, 5, 0);
1233
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);
1245 }
1246
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);
1257 }
1258 }
1259
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;
1265 }
1266
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);
1272
1273 result = T_UNRESOLVED;
1274
1275 if (T7_eflag == 0)
1276 ++T7_nfails;
1277
1278 if (T7_nfails != 0)
1279 result = T_FAIL;
1280 else if ((T7_nfails == 0) && (T7_nprobs == 0))
1281 result = T_PASS;
1282
1283 return(result);
1284 }
1285
1286 static const char *a7 = "A call to isc_task_create() creates a task that can "
1287 "receive events.";
1288
1289 static void
t7(void)1290 t7(void) {
1291 t_assert("tasks", 7, T_REQUIRED, "%s", a7);
1292
1293 if (threaded)
1294 t_result(t_tasks7());
1295 else
1296 require_threads();
1297 }
1298
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
1304
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;
1312
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;
1318
1319 static void
t10_event1(isc_task_t * task,isc_event_t * event)1320 t10_event1(isc_task_t *task, isc_event_t *event) {
1321 isc_result_t isc_result;
1322
1323 UNUSED(task);
1324
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;
1330 }
1331
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;
1338 }
1339 }
1340
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;
1346 }
1347
1348 isc_event_free(&event);
1349 }
1350
1351 static void
t10_event2(isc_task_t * task,isc_event_t * event)1352 t10_event2(isc_task_t *task, isc_event_t *event) {
1353
1354 int sender_match;
1355 int type_match;
1356 int tag_match;
1357
1358 UNUSED(task);
1359
1360 sender_match = 0;
1361 type_match = 0;
1362 tag_match = 0;
1363
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");
1371 }
1372
1373 if ((T10_purge_sender == NULL) ||
1374 (T10_purge_sender == event->ev_sender)) {
1375 sender_match = 1;
1376 }
1377 if (T10_testrange == 0) {
1378 if (T10_purge_type_first == event->ev_type) {
1379 type_match = 1;
1380 }
1381 } else {
1382 if ((T10_purge_type_first <= event->ev_type) &&
1383 (event->ev_type <= T10_purge_type_last)) {
1384 type_match = 1;
1385 }
1386 }
1387 if ((T10_purge_tag == NULL) ||
1388 (T10_purge_tag == event->ev_tag)) {
1389 tag_match = 1;
1390 }
1391
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);
1402 }
1403 } else {
1404 ++T10_eventcnt;
1405 }
1406 isc_event_free(&event);
1407 }
1408
1409
1410 static void
t10_sde(isc_task_t * task,isc_event_t * event)1411 t10_sde(isc_task_t *task, isc_event_t *event) {
1412 isc_result_t isc_result;
1413
1414 UNUSED(task);
1415
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;
1421 }
1422
1423 ++T10_shutdownflag;
1424
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;
1430 }
1431
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;
1437 }
1438
1439 isc_event_free(&event);
1440 }
1441
1442 static void
t_taskpurge_x(int sender,int type,int tag,void * purge_sender,int purge_type_first,int purge_type_last,void * purge_tag,int exp_nevents,int * nfails,int * nprobs,int testrange)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)
1446 {
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];
1463
1464
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;
1473
1474 workers = 2;
1475 p = t_getenv("ISC_TASK_WORKERS");
1476 if (p != NULL)
1477 workers = atoi(p);
1478
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;
1486 }
1487
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;
1495 }
1496
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;
1505 }
1506
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;
1517 }
1518
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;
1530 }
1531
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;
1543 }
1544
1545 /*
1546 * Block the task on T10_cv.
1547 */
1548 event = isc_event_allocate(mctx, (void *)1, (isc_eventtype_t)T_CONTROL,
1549 t10_event1, NULL, sizeof(*event));
1550
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;
1560 }
1561 isc_task_send(task, &event);
1562
1563 /*
1564 * Fill the task's queue with some messages with varying
1565 * sender, type, tag, and purgable attribute values.
1566 */
1567
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));
1577
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;
1587 }
1588
1589 eventtab[event_cnt]->ev_tag =
1590 (void *)((uintptr_t)tag + tag_cnt);
1591
1592 /*
1593 * Make all odd message non-purgable.
1594 */
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;
1600 }
1601 }
1602 }
1603
1604 for (cnt = 0; cnt < event_cnt; ++cnt)
1605 isc_task_send(task, &eventtab[cnt]);
1606
1607 if (T_debug)
1608 t_info("%d events queued\n", cnt);
1609
1610 if (testrange == 0) {
1611 /*
1612 * We're testing isc_task_purge.
1613 */
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 {
1624 /*
1625 * We're testing isc_task_purgerange.
1626 */
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);
1637 }
1638
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;
1650 }
1651
1652 /*
1653 * Unblock the task, allowing event processing.
1654 */
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;
1661 }
1662
1663 isc_task_shutdown(task);
1664
1665 isc_interval_set(&interval, 5, 0);
1666
1667 /*
1668 * Wait for shutdown processing to complete.
1669 */
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;
1682 }
1683
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;
1695 }
1696 }
1697
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;
1703 }
1704
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);
1710
1711 if (T_debug)
1712 t_info("task processed %d events\n", T10_eventcnt);
1713
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;
1718 }
1719 }
1720
1721 static int
t_tasks10(void)1722 t_tasks10(void) {
1723 int result;
1724
1725 T10_nprobs = 0;
1726 T10_nfails = 0;
1727
1728 /*
1729 * Try purging on a specific sender.
1730 */
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);
1734
1735 /*
1736 * Try purging on all senders.
1737 */
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);
1741
1742 /*
1743 * Try purging on all senders, specified type, all tags.
1744 */
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);
1748
1749 /*
1750 * Try purging on a specified tag, no such type.
1751 */
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);
1755
1756 /*
1757 * Try purging on specified sender, type, all tags.
1758 */
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);
1762
1763 result = T_UNRESOLVED;
1764
1765 if ((T10_nfails == 0) && (T10_nprobs == 0))
1766 result = T_PASS;
1767 else if (T10_nfails != 0)
1768 result = T_FAIL;
1769
1770 return(result);
1771 }
1772
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.";
1778
1779 static void
t10(void)1780 t10(void) {
1781 t_assert("tasks", 10, T_REQUIRED, "%s", a10);
1782
1783 if (threaded)
1784 t_result(t_tasks10());
1785 else
1786 require_threads();
1787 }
1788
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;
1796
1797 static void
t11_event1(isc_task_t * task,isc_event_t * event)1798 t11_event1(isc_task_t *task, isc_event_t *event) {
1799 isc_result_t isc_result;
1800
1801 UNUSED(task);
1802
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;
1808 }
1809
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;
1816 }
1817 }
1818
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;
1824 }
1825
1826 isc_event_free(&event);
1827 }
1828
1829 static void
t11_event2(isc_task_t * task,isc_event_t * event)1830 t11_event2(isc_task_t *task, isc_event_t *event) {
1831 UNUSED(task);
1832
1833 ++T11_eventcnt;
1834 isc_event_free(&event);
1835 }
1836
1837
1838 static void
t11_sde(isc_task_t * task,isc_event_t * event)1839 t11_sde(isc_task_t *task, isc_event_t *event) {
1840 isc_result_t isc_result;
1841
1842 UNUSED(task);
1843
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;
1849 }
1850
1851 ++T11_shutdownflag;
1852
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;
1858 }
1859
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;
1865 }
1866
1867 isc_event_free(&event);
1868 }
1869
1870 static int
t_tasks11(int purgable)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;
1884
1885 T11_startflag = 0;
1886 T11_shutdownflag = 0;
1887 T11_eventcnt = 0;
1888
1889 workers = 2;
1890 p = t_getenv("ISC_TASK_WORKERS");
1891 if (p != NULL)
1892 workers = atoi(p);
1893
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);
1900 }
1901
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);
1908 }
1909
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);
1917 }
1918
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);
1928 }
1929
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);
1940 }
1941
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);
1952 }
1953
1954 /*
1955 * Block the task on T11_cv.
1956 */
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);
1967 }
1968 isc_task_send(task, &event1);
1969
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);
1980 }
1981 event2_clone = event2;
1982 if (purgable)
1983 event2->ev_attributes &= ~ISC_EVENTATTR_NOPURGE;
1984 else
1985 event2->ev_attributes |= ISC_EVENTATTR_NOPURGE;
1986
1987 isc_task_send(task, &event2);
1988
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;
1995 }
1996
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;
2002 }
2003
2004 /*
2005 * Unblock the task, allowing event processing.
2006 */
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;
2013 }
2014
2015 isc_task_shutdown(task);
2016
2017 isc_interval_set(&interval, 5, 0);
2018
2019 /*
2020 * Wait for shutdown processing to complete.
2021 */
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;
2028 }
2029
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;
2035 }
2036 }
2037
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;
2043 }
2044
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);
2050
2051 if (T11_eventcnt != (purgable ? 0 : 1)) {
2052 t_info("Event was %s purged\n",
2053 (purgable ? "not" : "unexpectedly"));
2054 ++T11_nfails;
2055 }
2056
2057 result = T_UNRESOLVED;
2058
2059 if ((T11_nfails == 0) && (T11_nprobs == 0))
2060 result = T_PASS;
2061 else if (T11_nfails)
2062 result = T_FAIL;
2063
2064 return(result);
2065 }
2066
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.";
2071
2072 static void
t11(void)2073 t11(void) {
2074 t_assert("tasks", 11, T_REQUIRED, "%s", a11);
2075
2076 if (threaded)
2077 t_result(t_tasks11(1));
2078 else
2079 require_threads();
2080 }
2081
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.";
2087
2088 static int
t_tasks12(void)2089 t_tasks12(void) {
2090 return(t_tasks11(0));
2091 }
2092
2093 static void
t12(void)2094 t12(void) {
2095 t_assert("tasks", 12, T_REQUIRED, "%s", a12);
2096
2097 if (threaded)
2098 t_result(t_tasks12());
2099 else
2100 require_threads();
2101 }
2102
2103 static int T13_nfails;
2104 static int T13_nprobs;
2105
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.";
2113
2114 static int
t_tasks13(void)2115 t_tasks13(void) {
2116 int result;
2117
2118 T13_nfails = 0;
2119 T13_nprobs = 0;
2120
2121 /*
2122 * First let's try the same cases we used in t10.
2123 */
2124
2125 /*
2126 * Try purging on a specific sender.
2127 */
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);
2131
2132 /*
2133 * Try purging on all senders.
2134 */
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);
2138
2139 /*
2140 * Try purging on all senders, specified type, all tags.
2141 */
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);
2144
2145 /*
2146 * Try purging on a specified tag, no such type.
2147 */
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);
2151
2152 /*
2153 * Try purging on specified sender, type, all tags.
2154 */
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);
2157
2158 /*
2159 * Now let's try some ranges.
2160 */
2161
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);
2165
2166 /*
2167 * Try purging on all senders.
2168 */
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);
2172
2173 /*
2174 * Try purging on all senders, specified type, all tags.
2175 */
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);
2178
2179 /*
2180 * Try purging on a specified tag, no such type.
2181 */
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);
2185
2186 /*
2187 * Try purging on specified sender, type, all tags.
2188 */
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);
2192
2193 result = T_UNRESOLVED;
2194
2195 if ((T13_nfails == 0) && (T13_nprobs == 0))
2196 result = T_PASS;
2197 else if (T13_nfails)
2198 result = T_FAIL;
2199
2200 return (result);
2201 }
2202
2203 static void
t13(void)2204 t13(void) {
2205 t_assert("tasks", 13, T_REQUIRED, "%s", a13);
2206
2207 if (threaded)
2208 t_result(t_tasks13());
2209 else
2210 require_threads();
2211 }
2212
2213 #define T14_NTASKS 10
2214 #define T14_EXCLTASK 6
2215
2216 int t14_exclusiveerror = ISC_R_SUCCESS;
2217 int t14_error = 0;
2218 int t14_done = 0;
2219
2220 int spin(int n);
2221
2222 int t14_active[T14_NTASKS];
2223
2224 static void
t14_callback(isc_task_t * task,isc_event_t * event)2225 t14_callback(isc_task_t *task, isc_event_t *event) {
2226 int taskno = *(int *)(event->ev_arg);
2227
2228
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++;
2242 }
2243 isc_task_endexclusive(task);
2244 t14_done = 1;
2245 } else {
2246 t14_active[taskno]++;
2247 (void) spin(10000000);
2248 t14_active[taskno]--;
2249 }
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);
2256 }
2257 }
2258
spin(int n)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;
2266 }
2267 return (r);
2268 }
2269
2270 static int
t_tasks14(void)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;
2279
2280 manager = NULL;
2281 mctx = NULL;
2282
2283 for (i = 0; i < T14_NTASKS; i++)
2284 tasks[i] = NULL;
2285
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);
2293 }
2294
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);
2299 }
2300
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);
2305 }
2306
2307 for (i = 0; i < T14_NTASKS; i++) {
2308 isc_event_t *event;
2309 int *v;
2310
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);
2315 }
2316
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);
2322 }
2323 *v = i;
2324
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);
2331 }
2332 isc_task_send(tasks[i], &event);
2333 }
2334
2335 for (i = 0; i < T14_NTASKS; i++) {
2336 isc_task_detach(&tasks[i]);
2337 }
2338
2339 isc_taskmgr_destroy(&manager);
2340
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);
2347 }
2348
2349 isc_mem_destroy(&mctx);
2350 return(T_PASS);
2351 }
2352
2353 static void
t14(void)2354 t14(void) {
2355 int result;
2356
2357 t_assert("tasks", 14, T_REQUIRED, "%s",
2358 "isc_task_beginexclusive() gets exclusive access");
2359 result = t_tasks14();
2360 t_result(result);
2361 }
2362
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 }
2375 };
2376
2377 #ifdef WIN32
2378 int
main(int argc,char ** argv)2379 main(int argc, char **argv) {
2380 t_settests(T_testlist);
2381 return (t_main(argc, argv));
2382 }
2383 #endif
2384