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 49 require_threads(void) { 50 t_info("This test requires threads\n"); 51 t_result(T_THREADONLY); 52 return; 53 } 54 55 static void 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 2089 t_tasks12(void) { 2090 return(t_tasks11(0)); 2091 } 2092 2093 static 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 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 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 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 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 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 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 2379 main(int argc, char **argv) { 2380 t_settests(T_testlist); 2381 return (t_main(argc, argv)); 2382 } 2383 #endif 2384