1/* 2 * Copyright (C) 2004, 2005, 2007, 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (C) 1998-2001 Internet Software Consortium. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15 * PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18/* $Id$ */ 19 20#include <config.h> 21 22#include <stdlib.h> 23#include <unistd.h> 24#ifdef HAVE_INTTYPES_H 25#include <inttypes.h> /* uintptr_t */ 26#endif 27#include <isc/condition.h> 28#include <isc/mem.h> 29#include <isc/platform.h> 30#include <isc/task.h> 31#include <isc/time.h> 32#include <isc/timer.h> 33#include <isc/util.h> 34 35#include <tests/t_api.h> 36 37 38#ifdef ISC_PLATFORM_USETHREADS 39isc_boolean_t threaded = ISC_TRUE; 40#else 41isc_boolean_t threaded = ISC_FALSE; 42#endif 43 44static int senders[4]; 45 46static void 47require_threads(void) { 48 t_info("This test requires threads\n"); 49 t_result(T_THREADONLY); 50 return; 51} 52 53static void 54t1_callback(isc_task_t *task, isc_event_t *event) { 55 int i; 56 int j; 57 58 UNUSED(task); 59 60 j = 0; 61 62 for (i = 0; i < 1000000; i++) 63 j += 100; 64 65 t_info("task %s\n", (char *)event->ev_arg); 66 isc_event_free(&event); 67} 68 69static void 70t1_shutdown(isc_task_t *task, isc_event_t *event) { 71 72 UNUSED(task); 73 74 t_info("shutdown %s\n", (char *)event->ev_arg); 75 isc_event_free(&event); 76} 77 78static void 79my_tick(isc_task_t *task, isc_event_t *event) { 80 81 UNUSED(task); 82 83 t_info("%s\n", (char *)event->ev_arg); 84 isc_event_free(&event); 85} 86 87/* 88 * Adapted from RTH's original task_test program 89 */ 90 91static int 92t_tasks1(void) { 93 char *p; 94 isc_mem_t *mctx; 95 isc_taskmgr_t *manager; 96 isc_task_t *task1; 97 isc_task_t *task2; 98 isc_task_t *task3; 99 isc_task_t *task4; 100 isc_event_t *event; 101 unsigned int workers; 102 isc_timermgr_t *timgr; 103 isc_timer_t *ti1; 104 isc_timer_t *ti2; 105 isc_result_t isc_result; 106 struct isc_time absolute; 107 struct isc_interval interval; 108 109 manager = NULL; 110 task1 = NULL; 111 task2 = NULL; 112 task3 = NULL; 113 task4 = NULL; 114 mctx = NULL; 115 116 workers = 2; 117 p = t_getenv("ISC_TASK_WORKERS"); 118 if (p != NULL) 119 workers = atoi(p); 120 if (workers < 1) { 121 t_info("Bad config value for ISC_TASK_WORKERS, %d\n", workers); 122 return(T_UNRESOLVED); 123 } 124 125 isc_result = isc_mem_create(0, 0, &mctx); 126 if (isc_result != ISC_R_SUCCESS) { 127 t_info("isc_mem_create failed %d\n", isc_result); 128 return(T_UNRESOLVED); 129 } 130 131 isc_result = isc_taskmgr_create(mctx, workers, 0, &manager); 132 if (isc_result != ISC_R_SUCCESS) { 133 t_info("isc_taskmgr_create failed %d\n", isc_result); 134 return(T_FAIL); 135 } 136 137 isc_result = isc_task_create(manager, 0, &task1); 138 if (isc_result != ISC_R_SUCCESS) { 139 t_info("isc_task_create failed %d\n", isc_result); 140 return(T_FAIL); 141 } 142 143 isc_result = isc_task_create(manager, 0, &task2); 144 if (isc_result != ISC_R_SUCCESS) { 145 t_info("isc_task_create failed %d\n", isc_result); 146 return(T_FAIL); 147 } 148 149 isc_result = isc_task_create(manager, 0, &task3); 150 if (isc_result != ISC_R_SUCCESS) { 151 t_info("isc_task_create failed %d\n", isc_result); 152 return(T_FAIL); 153 } 154 155 isc_result = isc_task_create(manager, 0, &task4); 156 if (isc_result != ISC_R_SUCCESS) { 157 t_info("isc_task_create failed %d\n", isc_result); 158 return(T_FAIL); 159 } 160 161 isc_result = isc_task_onshutdown(task1, t1_shutdown, "1"); 162 if (isc_result != ISC_R_SUCCESS) { 163 t_info("isc_task_onshutdown failed %d\n", isc_result); 164 return(T_FAIL); 165 } 166 167 isc_result = isc_task_onshutdown(task2, t1_shutdown, "2"); 168 if (isc_result != ISC_R_SUCCESS) { 169 t_info("isc_task_onshutdown failed %d\n", isc_result); 170 return(T_FAIL); 171 } 172 173 isc_result = isc_task_onshutdown(task3, t1_shutdown, "3"); 174 if (isc_result != ISC_R_SUCCESS) { 175 t_info("isc_task_onshutdown failed %d\n", isc_result); 176 return(T_FAIL); 177 } 178 179 isc_result = isc_task_onshutdown(task4, t1_shutdown, "4"); 180 if (isc_result != ISC_R_SUCCESS) { 181 t_info("isc_task_onshutdown failed %d\n", isc_result); 182 return(T_FAIL); 183 } 184 185 timgr = NULL; 186 isc_result = isc_timermgr_create(mctx, &timgr); 187 if (isc_result != ISC_R_SUCCESS) { 188 t_info("isc_timermgr_create %d\n", isc_result); 189 return(T_UNRESOLVED); 190 } 191 192 ti1 = NULL; 193 isc_time_settoepoch(&absolute); 194 isc_interval_set(&interval, 1, 0); 195 isc_result = isc_timer_create(timgr, isc_timertype_ticker, 196 &absolute, &interval, 197 task1, my_tick, "tick", &ti1); 198 if (isc_result != ISC_R_SUCCESS) { 199 t_info("isc_timer_create %d\n", isc_result); 200 return(T_UNRESOLVED); 201 } 202 203 ti2 = NULL; 204 isc_time_settoepoch(&absolute); 205 isc_interval_set(&interval, 1, 0); 206 isc_result = isc_timer_create(timgr, isc_timertype_ticker, 207 &absolute, &interval, 208 task2, my_tick, "tock", &ti2); 209 if (isc_result != ISC_R_SUCCESS) { 210 t_info("isc_timer_create %d\n", isc_result); 211 return(T_UNRESOLVED); 212 } 213 214 215 sleep(2); 216 217 /* 218 * Note: (void *)1 is used as a sender here, since some compilers 219 * don't like casting a function pointer to a (void *). 220 * 221 * In a real use, it is more likely the sender would be a 222 * structure (socket, timer, task, etc) but this is just a test 223 * program. 224 */ 225 event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "1", 226 sizeof(*event)); 227 if (event == NULL) { 228 t_info("isc_event_allocate failed\n"); 229 return(T_UNRESOLVED); 230 } 231 232 isc_task_send(task1, &event); 233 234 event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "1", 235 sizeof(*event)); 236 if (event == NULL) { 237 t_info("isc_event_allocate failed\n"); 238 return(T_UNRESOLVED); 239 } 240 241 isc_task_send(task1, &event); 242 243 event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "1", 244 sizeof(*event)); 245 if (event == NULL) { 246 t_info("isc_event_allocate failed\n"); 247 return(T_UNRESOLVED); 248 } 249 250 isc_task_send(task1, &event); 251 252 event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "1", 253 sizeof(*event)); 254 if (event == NULL) { 255 t_info("isc_event_allocate failed\n"); 256 return(T_UNRESOLVED); 257 } 258 259 isc_task_send(task1, &event); 260 261 event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "1", 262 sizeof(*event)); 263 if (event == NULL) { 264 t_info("isc_event_allocate failed\n"); 265 return(T_UNRESOLVED); 266 } 267 268 isc_task_send(task1, &event); 269 270 event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "1", 271 sizeof(*event)); 272 if (event == NULL) { 273 t_info("isc_event_allocate failed\n"); 274 return(T_UNRESOLVED); 275 } 276 277 isc_task_send(task1, &event); 278 279 event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "1", 280 sizeof(*event)); 281 if (event == NULL) { 282 t_info("isc_event_allocate failed\n"); 283 return(T_UNRESOLVED); 284 } 285 286 isc_task_send(task1, &event); 287 288 event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "1", 289 sizeof(*event)); 290 if (event == NULL) { 291 t_info("isc_event_allocate failed\n"); 292 return(T_UNRESOLVED); 293 } 294 295 isc_task_send(task1, &event); 296 297 event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "1", 298 sizeof(*event)); 299 if (event == NULL) { 300 t_info("isc_event_allocate failed\n"); 301 return(T_UNRESOLVED); 302 } 303 304 isc_task_send(task1, &event); 305 306 event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "2", 307 sizeof(*event)); 308 if (event == NULL) { 309 t_info("isc_event_allocate failed\n"); 310 return(T_UNRESOLVED); 311 } 312 313 isc_task_send(task2, &event); 314 315 event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "3", 316 sizeof(*event)); 317 if (event == NULL) { 318 t_info("isc_event_allocate failed\n"); 319 return(T_UNRESOLVED); 320 } 321 322 isc_task_send(task3, &event); 323 324 event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "4", 325 sizeof(*event)); 326 if (event == NULL) { 327 t_info("isc_event_allocate failed\n"); 328 return(T_UNRESOLVED); 329 } 330 331 isc_task_send(task4, &event); 332 333 event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "2", 334 sizeof(*event)); 335 if (event == NULL) { 336 t_info("isc_event_allocate failed\n"); 337 return(T_UNRESOLVED); 338 } 339 340 isc_task_send(task2, &event); 341 342 event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "3", 343 sizeof(*event)); 344 if (event == NULL) { 345 t_info("isc_event_allocate failed\n"); 346 return(T_UNRESOLVED); 347 } 348 349 isc_task_send(task3, &event); 350 351 event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "4", 352 sizeof(*event)); 353 if (event == NULL) { 354 t_info("isc_event_allocate failed\n"); 355 return(T_UNRESOLVED); 356 } 357 358 isc_task_send(task4, &event); 359 360 (void)isc_task_purge(task3, NULL, 0, 0); 361 362 isc_task_detach(&task1); 363 isc_task_detach(&task2); 364 isc_task_detach(&task3); 365 isc_task_detach(&task4); 366 367 sleep(10); 368 isc_timer_detach(&ti1); 369 isc_timer_detach(&ti2); 370 isc_timermgr_destroy(&timgr); 371 isc_taskmgr_destroy(&manager); 372 373 isc_mem_destroy(&mctx); 374 return(T_PASS); 375} 376 377static const char *a1 = "The task subsystem can create and manage tasks"; 378 379static void 380t1(void) { 381 int result; 382 383 t_assert("tasks", 1, T_REQUIRED, "%s", a1); 384 result = t_tasks1(); 385 t_result(result); 386} 387 388#define T2_NTASKS 10000 389 390static isc_event_t *T2_event; 391static isc_taskmgr_t *T2_manager; 392static isc_mem_t *T2_mctx; 393static isc_condition_t T2_cv; 394static isc_mutex_t T2_mx; 395static int T2_done; 396static int T2_nprobs; 397static int T2_nfails; 398static int T2_ntasks; 399 400static void 401t2_shutdown(isc_task_t *task, isc_event_t *event) { 402 403 isc_result_t isc_result; 404 405 UNUSED(task); 406 407 if (event->ev_arg != NULL) { 408 isc_task_destroy((isc_task_t**) &event->ev_arg); 409 } 410 else { 411 isc_result = isc_mutex_lock(&T2_mx); 412 if (isc_result != ISC_R_SUCCESS) { 413 t_info("isc_mutex_lock failed %d\n", isc_result); 414 ++T2_nprobs; 415 } 416 417 T2_done = 1; 418 419 isc_result = isc_condition_signal(&T2_cv); 420 if (isc_result != ISC_R_SUCCESS) { 421 t_info("isc_condition_signal failed %d\n", isc_result); 422 ++T2_nprobs; 423 } 424 425 isc_result = isc_mutex_unlock(&T2_mx); 426 if (isc_result != ISC_R_SUCCESS) { 427 t_info("isc_mutex_unlock failed %d\n", isc_result); 428 ++T2_nprobs; 429 } 430 431 isc_event_free(&T2_event); 432 isc_taskmgr_destroy(&T2_manager); 433 isc_mem_destroy(&T2_mctx); 434 } 435} 436 437static void 438t2_callback(isc_task_t *task, isc_event_t *event) { 439 isc_result_t isc_result; 440 isc_task_t *newtask; 441 442 ++T2_ntasks; 443 444 if (T_debug && ((T2_ntasks % 100) == 0)) { 445 t_info("T2_ntasks %d\n", T2_ntasks); 446 } 447 448 if (event->ev_arg) { 449 450 event->ev_arg = (void *)(((uintptr_t) event->ev_arg) - 1); 451 452 /* 453 * Create a new task and forward the message. 454 */ 455 newtask = NULL; 456 isc_result = isc_task_create(T2_manager, 0, &newtask); 457 if (isc_result != ISC_R_SUCCESS) { 458 t_info("isc_task_create failed %d\n", isc_result); 459 ++T2_nfails; 460 return; 461 } 462 463 isc_result = isc_task_onshutdown(newtask, t2_shutdown, 464 (void *)task); 465 if (isc_result != ISC_R_SUCCESS) { 466 t_info("isc_task_onshutdown failed %d\n", 467 isc_result); 468 ++T2_nfails; 469 return; 470 } 471 472 isc_task_send(newtask, &event); 473 } else { 474 /* 475 * Time to unwind, shutdown should perc back up. 476 */ 477 isc_task_destroy(&task); 478 } 479} 480 481static int 482t_tasks2(void) { 483 uintptr_t ntasks; 484 int result; 485 char *p; 486 isc_event_t *event; 487 unsigned int workers; 488 isc_result_t isc_result; 489 490 T2_manager = NULL; 491 T2_done = 0; 492 T2_nprobs = 0; 493 T2_nfails = 0; 494 T2_ntasks = 0; 495 496 workers = 2; 497 p = t_getenv("ISC_TASK_WORKERS"); 498 if (p != NULL) 499 workers = atoi(p); 500 if (workers < 1) { 501 t_info("Bad config value for ISC_TASK_WORKERS, %d\n", workers); 502 return(T_UNRESOLVED); 503 } 504 505 p = t_getenv("ISC_TASKS_MIN"); 506 if (p != NULL) 507 ntasks = atoi(p); 508 else 509 ntasks = T2_NTASKS; 510 if (ntasks == 0U) { 511 t_info("Bad config value for ISC_TASKS_MIN, %lu\n", 512 (unsigned long)ntasks); 513 return(T_UNRESOLVED); 514 } 515 516 t_info("Testing with %lu tasks\n", (unsigned long)ntasks); 517 518 isc_result = isc_mutex_init(&T2_mx); 519 if (isc_result != ISC_R_SUCCESS) { 520 t_info("isc_mutex_init failed %d\n", isc_result); 521 return(T_UNRESOLVED); 522 } 523 524 isc_result = isc_condition_init(&T2_cv); 525 if (isc_result != ISC_R_SUCCESS) { 526 t_info("isc_condition_init failed %d\n", isc_result); 527 return(T_UNRESOLVED); 528 } 529 530 isc_result = isc_mem_create(0, 0, &T2_mctx); 531 if (isc_result != ISC_R_SUCCESS) { 532 t_info("isc_mem_create failed %d\n", isc_result); 533 return(T_UNRESOLVED); 534 } 535 536 isc_result = isc_taskmgr_create(T2_mctx, workers, 0, &T2_manager); 537 if (isc_result != ISC_R_SUCCESS) { 538 t_info("isc_taskmgr_create failed %d\n", isc_result); 539 return(T_FAIL); 540 } 541 542 T2_event = isc_event_allocate(T2_mctx, (void *)1, 1, t2_callback, 543 (void *)ntasks, sizeof(*event)); 544 if (T2_event == NULL) { 545 t_info("isc_event_allocate failed\n"); 546 return(T_UNRESOLVED); 547 } 548 549 isc_result = isc_mutex_lock(&T2_mx); 550 if (isc_result != ISC_R_SUCCESS) { 551 t_info("isc_mutex_lock failed %d\n", isc_result); 552 return(T_UNRESOLVED); 553 } 554 555 t2_callback(NULL, T2_event); 556 557 while (T2_done == 0) { 558 isc_result = isc_condition_wait(&T2_cv, &T2_mx); 559 if (isc_result != ISC_R_SUCCESS) { 560 t_info("isc_condition_wait failed %d\n", isc_result); 561 return(T_UNRESOLVED); 562 } 563 } 564 565 result = T_UNRESOLVED; 566 567 if ((T2_nfails == 0) && (T2_nprobs == 0)) 568 result = T_PASS; 569 else if (T2_nfails != 0) 570 result = T_FAIL; 571 572 return(result); 573} 574 575static const char *a2 = "The task subsystem can create ISC_TASKS_MIN tasks"; 576 577static void 578t2(void) { 579 t_assert("tasks", 2, T_REQUIRED, "%s", a2); 580 581 if (threaded) 582 t_result(t_tasks2()); 583 else 584 require_threads(); 585} 586 587#define T3_NEVENTS 256 588 589static int T3_flag; 590static int T3_nevents; 591static int T3_nsdevents; 592static isc_mutex_t T3_mx; 593static isc_condition_t T3_cv; 594static int T3_nfails; 595static int T3_nprobs; 596 597static void 598t3_sde1(isc_task_t *task, isc_event_t *event) { 599 600 UNUSED(task); 601 602 if (T3_nevents != T3_NEVENTS) { 603 t_info("Some events were not processed\n"); 604 ++T3_nprobs; 605 } 606 if (T3_nsdevents == 1) { 607 ++T3_nsdevents; 608 } else { 609 t_info("Shutdown events not processed in LIFO order\n"); 610 ++T3_nfails; 611 } 612 isc_event_free(&event); 613} 614 615static void 616t3_sde2(isc_task_t *task, isc_event_t *event) { 617 618 UNUSED(task); 619 620 if (T3_nevents != T3_NEVENTS) { 621 t_info("Some events were not processed\n"); 622 ++T3_nprobs; 623 } 624 if (T3_nsdevents == 0) { 625 ++T3_nsdevents; 626 } else { 627 t_info("Shutdown events not processed in LIFO order\n"); 628 ++T3_nfails; 629 } 630 isc_event_free(&event); 631} 632 633static void 634t3_event1(isc_task_t *task, isc_event_t *event) { 635 isc_result_t isc_result; 636 637 UNUSED(task); 638 639 isc_result = isc_mutex_lock(&T3_mx); 640 if (isc_result != ISC_R_SUCCESS) { 641 t_info("isc_mutex_lock failed %s\n", 642 isc_result_totext(isc_result)); 643 ++T3_nprobs; 644 } 645 while (T3_flag != 1) { 646 (void) isc_condition_wait(&T3_cv, &T3_mx); 647 } 648 649 isc_result = isc_mutex_unlock(&T3_mx); 650 if (isc_result != ISC_R_SUCCESS) { 651 t_info("isc_mutex_unlock failed %s\n", 652 isc_result_totext(isc_result)); 653 ++T3_nprobs; 654 } 655 isc_event_free(&event); 656} 657 658static void 659t3_event2(isc_task_t *task, isc_event_t *event) { 660 UNUSED(task); 661 662 ++T3_nevents; 663 isc_event_free(&event); 664} 665 666static int 667t_tasks3(void) { 668 int cnt; 669 int result; 670 char *p; 671 isc_mem_t *mctx; 672 isc_taskmgr_t *tmgr; 673 isc_task_t *task; 674 unsigned int workers; 675 isc_event_t *event; 676 isc_result_t isc_result; 677 isc_eventtype_t event_type; 678 679 T3_flag = 0; 680 T3_nevents = 0; 681 T3_nsdevents = 0; 682 T3_nfails = 0; 683 T3_nprobs = 0; 684 685 event_type = 3; 686 687 workers = 2; 688 p = t_getenv("ISC_TASK_WORKERS"); 689 if (p != NULL) 690 workers = atoi(p); 691 692 mctx = NULL; 693 isc_result = isc_mem_create(0, 0, &mctx); 694 if (isc_result != ISC_R_SUCCESS) { 695 t_info("isc_mem_create failed %s\n", 696 isc_result_totext(isc_result)); 697 return(T_UNRESOLVED); 698 } 699 700 isc_result = isc_mutex_init(&T3_mx); 701 if (isc_result != ISC_R_SUCCESS) { 702 t_info("isc_mutex_init failed %s\n", 703 isc_result_totext(isc_result)); 704 isc_mem_destroy(&mctx); 705 return(T_UNRESOLVED); 706 } 707 708 isc_result = isc_condition_init(&T3_cv); 709 if (isc_result != ISC_R_SUCCESS) { 710 t_info("isc_condition_init failed %s\n", 711 isc_result_totext(isc_result)); 712 isc_mem_destroy(&mctx); 713 return(T_UNRESOLVED); 714 } 715 716 tmgr = NULL; 717 isc_result = isc_taskmgr_create(mctx, workers, 0, &tmgr); 718 if (isc_result != ISC_R_SUCCESS) { 719 t_info("isc_taskmgr_create failed %s\n", 720 isc_result_totext(isc_result)); 721 isc_mem_destroy(&mctx); 722 return(T_UNRESOLVED); 723 } 724 725 isc_result = isc_mutex_lock(&T3_mx); 726 if (isc_result != ISC_R_SUCCESS) { 727 t_info("isc_mutex_lock failed %s\n", 728 isc_result_totext(isc_result)); 729 isc_taskmgr_destroy(&tmgr); 730 isc_mem_destroy(&mctx); 731 return(T_UNRESOLVED); 732 } 733 734 task = NULL; 735 isc_result = isc_task_create(tmgr, 0, &task); 736 if (isc_result != ISC_R_SUCCESS) { 737 t_info("isc_task_create failed %s\n", 738 isc_result_totext(isc_result)); 739 (void) isc_mutex_unlock(&T3_mx); 740 isc_taskmgr_destroy(&tmgr); 741 isc_mem_destroy(&mctx); 742 return(T_UNRESOLVED); 743 } 744 745 /* 746 * This event causes the task to wait on T3_cv. 747 */ 748 event = isc_event_allocate(mctx, &senders[1], event_type, t3_event1, 749 NULL, sizeof(*event)); 750 if (event == NULL) { 751 t_info("isc_event_allocate failed\n"); 752 (void) isc_mutex_unlock(&T3_mx); 753 isc_task_destroy(&task); 754 isc_taskmgr_destroy(&tmgr); 755 isc_mem_destroy(&mctx); 756 return(T_UNRESOLVED); 757 } 758 isc_task_send(task, &event); 759 760 /* 761 * Now we fill up the task's event queue with some events. 762 */ 763 for (cnt = 0; cnt < T3_NEVENTS; ++cnt) { 764 event = isc_event_allocate(mctx, &senders[1], event_type, 765 t3_event2, NULL, sizeof(*event)); 766 if (event == NULL) { 767 t_info("isc_event_allocate failed\n"); 768 (void) isc_mutex_unlock(&T3_mx); 769 isc_task_destroy(&task); 770 isc_taskmgr_destroy(&tmgr); 771 isc_mem_destroy(&mctx); 772 return(T_UNRESOLVED); 773 } 774 isc_task_send(task, &event); 775 } 776 777 /* 778 * Now we register two shutdown events. 779 */ 780 isc_result = isc_task_onshutdown(task, t3_sde1, NULL); 781 if (isc_result != ISC_R_SUCCESS) { 782 t_info("isc_task_send failed %s\n", 783 isc_result_totext(isc_result)); 784 (void) isc_mutex_unlock(&T3_mx); 785 isc_task_destroy(&task); 786 isc_taskmgr_destroy(&tmgr); 787 isc_mem_destroy(&mctx); 788 return(T_UNRESOLVED); 789 } 790 791 isc_result = isc_task_onshutdown(task, t3_sde2, NULL); 792 if (isc_result != ISC_R_SUCCESS) { 793 t_info("isc_task_send failed %s\n", 794 isc_result_totext(isc_result)); 795 (void) isc_mutex_unlock(&T3_mx); 796 isc_task_destroy(&task); 797 isc_taskmgr_destroy(&tmgr); 798 isc_mem_destroy(&mctx); 799 return(T_UNRESOLVED); 800 } 801 802 isc_task_shutdown(task); 803 804 /* 805 * Now we free the task by signaling T3_cv. 806 */ 807 T3_flag = 1; 808 isc_result = isc_condition_signal(&T3_cv); 809 if (isc_result != ISC_R_SUCCESS) { 810 t_info("isc_condition_signal failed %s\n", 811 isc_result_totext(isc_result)); 812 ++T3_nprobs; 813 } 814 815 isc_result = isc_mutex_unlock(&T3_mx); 816 if (isc_result != ISC_R_SUCCESS) { 817 t_info("isc_mutex_unlock failed %s\n", 818 isc_result_totext(isc_result)); 819 ++T3_nprobs; 820 } 821 822 823 isc_task_detach(&task); 824 isc_taskmgr_destroy(&tmgr); 825 isc_mem_destroy(&mctx); 826 827 if (T3_nsdevents != 2) { 828 t_info("T3_nsdevents == %d, expected 2\n", T3_nsdevents); 829 ++T3_nfails; 830 } 831 832 result = T_UNRESOLVED; 833 834 if (T3_nfails != 0) 835 result = T_FAIL; 836 else if ((T3_nfails == 0) && (T3_nprobs == 0)) 837 result = T_PASS; 838 839 return(result); 840} 841 842static const char *a3 = "When isc_task_shutdown() is called, any shutdown " 843 "events that have been requested via prior " 844 "isc_task_onshutdown() calls are posted in " 845 "LIFO order."; 846static void 847t3(void) { 848 t_assert("tasks", 3, T_REQUIRED, "%s", a3); 849 850 if (threaded) 851 t_result(t_tasks3()); 852 else 853 require_threads(); 854} 855 856static isc_mutex_t T4_mx; 857static isc_condition_t T4_cv; 858static int T4_flag; 859static int T4_nprobs; 860static int T4_nfails; 861 862static void 863t4_event1(isc_task_t *task, isc_event_t *event) { 864 isc_result_t isc_result; 865 866 UNUSED(task); 867 868 isc_result = isc_mutex_lock(&T4_mx); 869 if (isc_result != ISC_R_SUCCESS) { 870 t_info("isc_mutex_lock failed %s\n", 871 isc_result_totext(isc_result)); 872 ++T4_nprobs; 873 } 874 while (T4_flag != 1) { 875 (void) isc_condition_wait(&T4_cv, &T4_mx); 876 } 877 878 isc_result = isc_mutex_unlock(&T4_mx); 879 if (isc_result != ISC_R_SUCCESS) { 880 t_info("isc_mutex_unlock failed %s\n", 881 isc_result_totext(isc_result)); 882 ++T4_nprobs; 883 } 884 isc_event_free(&event); 885} 886 887static void 888t4_sde(isc_task_t *task, isc_event_t *event) { 889 UNUSED(task); 890 891 /* 892 * No-op. 893 */ 894 895 isc_event_free(&event); 896} 897 898static int 899t_tasks4(void) { 900 int result; 901 char *p; 902 isc_mem_t *mctx; 903 isc_taskmgr_t *tmgr; 904 isc_task_t *task; 905 unsigned int workers; 906 isc_result_t isc_result; 907 isc_eventtype_t event_type; 908 isc_event_t *event; 909 910 T4_nprobs = 0; 911 T4_nfails = 0; 912 T4_flag = 0; 913 914 event_type = 4; 915 916 workers = 2; 917 p = t_getenv("ISC_TASK_WORKERS"); 918 if (p != NULL) 919 workers = atoi(p); 920 921 mctx = NULL; 922 isc_result = isc_mem_create(0, 0, &mctx); 923 if (isc_result != ISC_R_SUCCESS) { 924 t_info("isc_mem_create failed %s\n", 925 isc_result_totext(isc_result)); 926 return(T_UNRESOLVED); 927 } 928 929 isc_result = isc_mutex_init(&T4_mx); 930 if (isc_result != ISC_R_SUCCESS) { 931 t_info("isc_mutex_init failed %s\n", 932 isc_result_totext(isc_result)); 933 isc_mem_destroy(&mctx); 934 return(T_UNRESOLVED); 935 } 936 937 isc_result = isc_condition_init(&T4_cv); 938 if (isc_result != ISC_R_SUCCESS) { 939 t_info("isc_condition_init failed %s\n", 940 isc_result_totext(isc_result)); 941 DESTROYLOCK(&T4_mx); 942 isc_mem_destroy(&mctx); 943 return(T_UNRESOLVED); 944 } 945 946 tmgr = NULL; 947 isc_result = isc_taskmgr_create(mctx, workers, 0, &tmgr); 948 if (isc_result != ISC_R_SUCCESS) { 949 t_info("isc_taskmgr_create failed %s\n", 950 isc_result_totext(isc_result)); 951 DESTROYLOCK(&T4_mx); 952 (void) isc_condition_destroy(&T4_cv); 953 isc_mem_destroy(&mctx); 954 return(T_UNRESOLVED); 955 } 956 957 isc_result = isc_mutex_lock(&T4_mx); 958 if (isc_result != ISC_R_SUCCESS) { 959 t_info("isc_mutex_lock failed %s\n", 960 isc_result_totext(isc_result)); 961 DESTROYLOCK(&T4_mx); 962 (void) isc_condition_destroy(&T4_cv); 963 isc_taskmgr_destroy(&tmgr); 964 isc_mem_destroy(&mctx); 965 return(T_UNRESOLVED); 966 } 967 968 task = NULL; 969 isc_result = isc_task_create(tmgr, 0, &task); 970 if (isc_result != ISC_R_SUCCESS) { 971 t_info("isc_task_create failed %s\n", 972 isc_result_totext(isc_result)); 973 DESTROYLOCK(&T4_mx); 974 (void) isc_condition_destroy(&T4_cv); 975 isc_taskmgr_destroy(&tmgr); 976 isc_mem_destroy(&mctx); 977 return(T_UNRESOLVED); 978 } 979 980 /* 981 * This event causes the task to wait on T4_cv. 982 */ 983 event = isc_event_allocate(mctx, &senders[1], event_type, t4_event1, 984 NULL, sizeof(*event)); 985 if (event == NULL) { 986 t_info("isc_event_allocate failed\n"); 987 DESTROYLOCK(&T4_mx); 988 isc_task_destroy(&task); 989 (void) isc_condition_destroy(&T4_cv); 990 isc_taskmgr_destroy(&tmgr); 991 isc_mem_destroy(&mctx); 992 return(T_UNRESOLVED); 993 } 994 isc_task_send(task, &event); 995 996 isc_task_shutdown(task); 997 998 isc_result = isc_task_onshutdown(task, t4_sde, NULL); 999 if (isc_result != ISC_R_SHUTTINGDOWN) { 1000 t_info("isc_task_onshutdown returned %s\n", 1001 isc_result_totext(isc_result)); 1002 ++T4_nfails; 1003 } 1004 1005 /* 1006 * Release the task. 1007 */ 1008 T4_flag = 1; 1009 1010 isc_result = isc_condition_signal(&T4_cv); 1011 if (isc_result != ISC_R_SUCCESS) { 1012 t_info("isc_condition_signal failed %s\n", 1013 isc_result_totext(isc_result)); 1014 ++T4_nprobs; 1015 } 1016 1017 isc_result = isc_mutex_unlock(&T4_mx); 1018 if (isc_result != ISC_R_SUCCESS) { 1019 t_info("isc_mutex_unlock failed %s\n", 1020 isc_result_totext(isc_result)); 1021 ++T4_nprobs; 1022 } 1023 1024 isc_task_detach(&task); 1025 isc_taskmgr_destroy(&tmgr); 1026 isc_mem_destroy(&mctx); 1027 (void) isc_condition_destroy(&T4_cv); 1028 DESTROYLOCK(&T4_mx); 1029 1030 result = T_UNRESOLVED; 1031 1032 if (T4_nfails != 0) 1033 result = T_FAIL; 1034 else if ((T4_nfails == 0) && (T4_nprobs == 0)) 1035 result = T_PASS; 1036 1037 return(result); 1038} 1039 1040static const char *a4 = 1041 "After isc_task_shutdown() has been called, any call to " 1042 "isc_task_onshutdown() will return ISC_R_SHUTTINGDOWN."; 1043 1044static void 1045t4(void) { 1046 t_assert("tasks", 4, T_REQUIRED, "%s", a4); 1047 1048 if (threaded) 1049 t_result(t_tasks4()); 1050 else 1051 require_threads(); 1052} 1053 1054static int T7_nprobs; 1055static int T7_eflag; 1056static int T7_sdflag; 1057static isc_mutex_t T7_mx; 1058static isc_condition_t T7_cv; 1059 1060static int T7_nfails; 1061 1062static void 1063t7_event1(isc_task_t *task, isc_event_t *event) { 1064 UNUSED(task); 1065 1066 ++T7_eflag; 1067 1068 isc_event_free(&event); 1069} 1070 1071static void 1072t7_sde(isc_task_t *task, isc_event_t *event) { 1073 isc_result_t isc_result; 1074 1075 UNUSED(task); 1076 1077 isc_result = isc_mutex_lock(&T7_mx); 1078 if (isc_result != ISC_R_SUCCESS) { 1079 t_info("isc_mutex_lock failed %s\n", 1080 isc_result_totext(isc_result)); 1081 ++T7_nprobs; 1082 } 1083 1084 ++T7_sdflag; 1085 1086 isc_result = isc_condition_signal(&T7_cv); 1087 if (isc_result != ISC_R_SUCCESS) { 1088 t_info("isc_condition_signal failed %s\n", 1089 isc_result_totext(isc_result)); 1090 ++T7_nprobs; 1091 } 1092 1093 isc_result = isc_mutex_unlock(&T7_mx); 1094 if (isc_result != ISC_R_SUCCESS) { 1095 t_info("isc_mutex_unlock failed %s\n", 1096 isc_result_totext(isc_result)); 1097 ++T7_nprobs; 1098 } 1099 1100 isc_event_free(&event); 1101} 1102 1103static int 1104t_tasks7(void) { 1105 int result; 1106 char *p; 1107 isc_mem_t *mctx; 1108 isc_taskmgr_t *tmgr; 1109 isc_task_t *task; 1110 unsigned int workers; 1111 isc_result_t isc_result; 1112 isc_eventtype_t event_type; 1113 isc_event_t *event; 1114 isc_time_t now; 1115 isc_interval_t interval; 1116 1117 T7_nprobs = 0; 1118 T7_nfails = 0; 1119 T7_sdflag = 0; 1120 T7_eflag = 0; 1121 1122 event_type = 7; 1123 1124 workers = 2; 1125 p = t_getenv("ISC_TASK_WORKERS"); 1126 if (p != NULL) 1127 workers = atoi(p); 1128 1129 mctx = NULL; 1130 isc_result = isc_mem_create(0, 0, &mctx); 1131 if (isc_result != ISC_R_SUCCESS) { 1132 t_info("isc_mem_create failed %s\n", 1133 isc_result_totext(isc_result)); 1134 return(T_UNRESOLVED); 1135 } 1136 1137 isc_result = isc_mutex_init(&T7_mx); 1138 if (isc_result != ISC_R_SUCCESS) { 1139 t_info("isc_mutex_init failed %s\n", 1140 isc_result_totext(isc_result)); 1141 isc_mem_destroy(&mctx); 1142 return(T_UNRESOLVED); 1143 } 1144 1145 isc_result = isc_condition_init(&T7_cv); 1146 if (isc_result != ISC_R_SUCCESS) { 1147 t_info("isc_condition_init failed %s\n", 1148 isc_result_totext(isc_result)); 1149 DESTROYLOCK(&T7_mx); 1150 isc_mem_destroy(&mctx); 1151 return(T_UNRESOLVED); 1152 } 1153 1154 tmgr = NULL; 1155 isc_result = isc_taskmgr_create(mctx, workers, 0, &tmgr); 1156 if (isc_result != ISC_R_SUCCESS) { 1157 t_info("isc_taskmgr_create failed %s\n", 1158 isc_result_totext(isc_result)); 1159 DESTROYLOCK(&T7_mx); 1160 (void) isc_condition_destroy(&T7_cv); 1161 isc_mem_destroy(&mctx); 1162 return(T_UNRESOLVED); 1163 } 1164 1165 isc_result = isc_mutex_lock(&T7_mx); 1166 if (isc_result != ISC_R_SUCCESS) { 1167 t_info("isc_mutex_lock failed %s\n", 1168 isc_result_totext(isc_result)); 1169 DESTROYLOCK(&T7_mx); 1170 (void) isc_condition_destroy(&T7_cv); 1171 isc_taskmgr_destroy(&tmgr); 1172 isc_mem_destroy(&mctx); 1173 return(T_FAIL); 1174 } 1175 1176 task = NULL; 1177 isc_result = isc_task_create(tmgr, 0, &task); 1178 if (isc_result != ISC_R_SUCCESS) { 1179 t_info("isc_task_create failed %s\n", 1180 isc_result_totext(isc_result)); 1181 DESTROYLOCK(&T7_mx); 1182 (void) isc_condition_destroy(&T7_cv); 1183 isc_taskmgr_destroy(&tmgr); 1184 isc_mem_destroy(&mctx); 1185 return(T_FAIL); 1186 } 1187 1188 isc_result = isc_task_onshutdown(task, t7_sde, NULL); 1189 if (isc_result != ISC_R_SUCCESS) { 1190 t_info("isc_task_onshutdown returned %s\n", 1191 isc_result_totext(isc_result)); 1192 DESTROYLOCK(&T7_mx); 1193 (void) isc_condition_destroy(&T7_cv); 1194 isc_task_destroy(&task); 1195 isc_taskmgr_destroy(&tmgr); 1196 isc_mem_destroy(&mctx); 1197 return(T_UNRESOLVED); 1198 } 1199 1200 event = isc_event_allocate(mctx, &senders[1], event_type, t7_event1, 1201 NULL, sizeof(*event)); 1202 if (event == NULL) { 1203 t_info("isc_event_allocate failed\n"); 1204 DESTROYLOCK(&T7_mx); 1205 (void) isc_condition_destroy(&T7_cv); 1206 isc_task_destroy(&task); 1207 isc_taskmgr_destroy(&tmgr); 1208 isc_mem_destroy(&mctx); 1209 return(T_UNRESOLVED); 1210 } 1211 isc_task_send(task, &event); 1212 1213 isc_task_shutdown(task); 1214 1215 interval.seconds = 5; 1216 interval.nanoseconds = 0; 1217 1218 while (T7_sdflag == 0) { 1219 isc_result = isc_time_nowplusinterval(&now, &interval); 1220 if (isc_result != ISC_R_SUCCESS) { 1221 t_info("isc_time_nowplusinterval failed %s\n", 1222 isc_result_totext(isc_result)); 1223 DESTROYLOCK(&T7_mx); 1224 (void) isc_condition_destroy(&T7_cv); 1225 isc_task_destroy(&task); 1226 isc_taskmgr_destroy(&tmgr); 1227 isc_mem_destroy(&mctx); 1228 return(T_UNRESOLVED); 1229 } 1230 1231 isc_result = isc_condition_waituntil(&T7_cv, &T7_mx, &now); 1232 if (isc_result != ISC_R_SUCCESS) { 1233 t_info("isc_condition_waituntil returned %s\n", 1234 isc_result_totext(isc_result)); 1235 DESTROYLOCK(&T7_mx); 1236 (void) isc_condition_destroy(&T7_cv); 1237 isc_task_destroy(&task); 1238 isc_taskmgr_destroy(&tmgr); 1239 isc_mem_destroy(&mctx); 1240 return(T_FAIL); 1241 } 1242 } 1243 1244 isc_result = isc_mutex_unlock(&T7_mx); 1245 if (isc_result != ISC_R_SUCCESS) { 1246 t_info("isc_mutex_unlock failed %s\n", 1247 isc_result_totext(isc_result)); 1248 ++T7_nprobs; 1249 } 1250 1251 isc_task_detach(&task); 1252 isc_taskmgr_destroy(&tmgr); 1253 isc_mem_destroy(&mctx); 1254 (void) isc_condition_destroy(&T7_cv); 1255 DESTROYLOCK(&T7_mx); 1256 1257 result = T_UNRESOLVED; 1258 1259 if (T7_eflag == 0) 1260 ++T7_nfails; 1261 1262 if (T7_nfails != 0) 1263 result = T_FAIL; 1264 else if ((T7_nfails == 0) && (T7_nprobs == 0)) 1265 result = T_PASS; 1266 1267 return(result); 1268} 1269 1270static const char *a7 = "A call to isc_task_create() creates a task that can " 1271 "receive events."; 1272 1273static void 1274t7(void) { 1275 t_assert("tasks", 7, T_REQUIRED, "%s", a7); 1276 1277 if (threaded) 1278 t_result(t_tasks7()); 1279 else 1280 require_threads(); 1281} 1282 1283#define T10_SENDERCNT 3 1284#define T10_TYPECNT 4 1285#define T10_TAGCNT 5 1286#define T10_NEVENTS (T10_SENDERCNT*T10_TYPECNT*T10_TAGCNT) 1287#define T_CONTROL 99999 1288 1289static int T10_nprobs; 1290static int T10_nfails; 1291static int T10_startflag; 1292static int T10_shutdownflag; 1293static int T10_eventcnt; 1294static isc_mutex_t T10_mx; 1295static isc_condition_t T10_cv; 1296 1297static void *T10_purge_sender; 1298static isc_eventtype_t T10_purge_type_first; 1299static isc_eventtype_t T10_purge_type_last; 1300static void *T10_purge_tag; 1301static int T10_testrange; 1302 1303static void 1304t10_event1(isc_task_t *task, isc_event_t *event) { 1305 isc_result_t isc_result; 1306 1307 UNUSED(task); 1308 1309 isc_result = isc_mutex_lock(&T10_mx); 1310 if (isc_result != ISC_R_SUCCESS) { 1311 t_info("isc_mutex_lock failed %s\n", 1312 isc_result_totext(isc_result)); 1313 ++T10_nprobs; 1314 } 1315 1316 while (T10_startflag == 0) { 1317 isc_result = isc_condition_wait(&T10_cv, &T10_mx); 1318 if (isc_result != ISC_R_SUCCESS) { 1319 t_info("isc_mutex_lock failed %s\n", 1320 isc_result_totext(isc_result)); 1321 ++T10_nprobs; 1322 } 1323 } 1324 1325 isc_result = isc_mutex_unlock(&T10_mx); 1326 if (isc_result != ISC_R_SUCCESS) { 1327 t_info("isc_mutex_unlock failed %s\n", 1328 isc_result_totext(isc_result)); 1329 ++T10_nprobs; 1330 } 1331 1332 isc_event_free(&event); 1333} 1334 1335static void 1336t10_event2(isc_task_t *task, isc_event_t *event) { 1337 1338 int sender_match; 1339 int type_match; 1340 int tag_match; 1341 1342 UNUSED(task); 1343 1344 sender_match = 0; 1345 type_match = 0; 1346 tag_match = 0; 1347 1348 if (T_debug) { 1349 t_info("Event %p,%d,%p,%s\n", 1350 event->ev_sender, 1351 (int)event->ev_type, 1352 event->ev_tag, 1353 event->ev_attributes & ISC_EVENTATTR_NOPURGE ? 1354 "NP" : "P"); 1355 } 1356 1357 if ((T10_purge_sender == NULL) || 1358 (T10_purge_sender == event->ev_sender)) { 1359 sender_match = 1; 1360 } 1361 if (T10_testrange == 0) { 1362 if (T10_purge_type_first == event->ev_type) { 1363 type_match = 1; 1364 } 1365 } else { 1366 if ((T10_purge_type_first <= event->ev_type) && 1367 (event->ev_type <= T10_purge_type_last)) { 1368 type_match = 1; 1369 } 1370 } 1371 if ((T10_purge_tag == NULL) || 1372 (T10_purge_tag == event->ev_tag)) { 1373 tag_match = 1; 1374 } 1375 1376 if (sender_match && type_match && tag_match) { 1377 if (event->ev_attributes & ISC_EVENTATTR_NOPURGE) { 1378 t_info("event %p,%d,%p matched but was not purgable\n", 1379 event->ev_sender, (int)event->ev_type, 1380 event->ev_tag); 1381 ++T10_eventcnt; 1382 } else { 1383 t_info("*** event %p,%d,%p not purged\n", 1384 event->ev_sender, (int)event->ev_type, 1385 event->ev_tag); 1386 } 1387 } else { 1388 ++T10_eventcnt; 1389 } 1390 isc_event_free(&event); 1391} 1392 1393 1394static void 1395t10_sde(isc_task_t *task, isc_event_t *event) { 1396 isc_result_t isc_result; 1397 1398 UNUSED(task); 1399 1400 isc_result = isc_mutex_lock(&T10_mx); 1401 if (isc_result != ISC_R_SUCCESS) { 1402 t_info("isc_mutex_lock failed %s\n", 1403 isc_result_totext(isc_result)); 1404 ++T10_nprobs; 1405 } 1406 1407 ++T10_shutdownflag; 1408 1409 isc_result = isc_condition_signal(&T10_cv); 1410 if (isc_result != ISC_R_SUCCESS) { 1411 t_info("isc_condition_signal failed %s\n", 1412 isc_result_totext(isc_result)); 1413 ++T10_nprobs; 1414 } 1415 1416 isc_result = isc_mutex_unlock(&T10_mx); 1417 if (isc_result != ISC_R_SUCCESS) { 1418 t_info("isc_mutex_unlock failed %s\n", 1419 isc_result_totext(isc_result)); 1420 ++T10_nprobs; 1421 } 1422 1423 isc_event_free(&event); 1424} 1425 1426static void 1427t_taskpurge_x(int sender, int type, int tag, void *purge_sender, 1428 int purge_type_first, int purge_type_last, void *purge_tag, 1429 int exp_nevents, int *nfails, int *nprobs, int testrange) 1430{ 1431 char *p; 1432 isc_mem_t *mctx; 1433 isc_taskmgr_t *tmgr; 1434 isc_task_t *task; 1435 unsigned int workers; 1436 isc_result_t isc_result; 1437 isc_event_t *event; 1438 isc_time_t now; 1439 isc_interval_t interval; 1440 int sender_cnt; 1441 int type_cnt; 1442 int tag_cnt; 1443 int event_cnt; 1444 int cnt; 1445 int nevents; 1446 isc_event_t *eventtab[T10_NEVENTS]; 1447 1448 1449 T10_startflag = 0; 1450 T10_shutdownflag = 0; 1451 T10_eventcnt = 0; 1452 T10_purge_sender = purge_sender; 1453 T10_purge_type_first = (isc_eventtype_t) purge_type_first; 1454 T10_purge_type_last = (isc_eventtype_t) purge_type_last; 1455 T10_purge_tag = purge_tag; 1456 T10_testrange = testrange; 1457 1458 workers = 2; 1459 p = t_getenv("ISC_TASK_WORKERS"); 1460 if (p != NULL) 1461 workers = atoi(p); 1462 1463 mctx = NULL; 1464 isc_result = isc_mem_create(0, 0, &mctx); 1465 if (isc_result != ISC_R_SUCCESS) { 1466 t_info("isc_mem_create failed %s\n", 1467 isc_result_totext(isc_result)); 1468 ++*nprobs; 1469 return; 1470 } 1471 1472 isc_result = isc_mutex_init(&T10_mx); 1473 if (isc_result != ISC_R_SUCCESS) { 1474 t_info("isc_mutex_init failed %s\n", 1475 isc_result_totext(isc_result)); 1476 isc_mem_destroy(&mctx); 1477 ++*nprobs; 1478 return; 1479 } 1480 1481 isc_result = isc_condition_init(&T10_cv); 1482 if (isc_result != ISC_R_SUCCESS) { 1483 t_info("isc_condition_init failed %s\n", 1484 isc_result_totext(isc_result)); 1485 isc_mem_destroy(&mctx); 1486 DESTROYLOCK(&T10_mx); 1487 ++*nprobs; 1488 return; 1489 } 1490 1491 tmgr = NULL; 1492 isc_result = isc_taskmgr_create(mctx, workers, 0, &tmgr); 1493 if (isc_result != ISC_R_SUCCESS) { 1494 t_info("isc_taskmgr_create failed %s\n", 1495 isc_result_totext(isc_result)); 1496 isc_mem_destroy(&mctx); 1497 DESTROYLOCK(&T10_mx); 1498 (void) isc_condition_destroy(&T10_cv); 1499 ++*nprobs; 1500 return; 1501 } 1502 1503 task = NULL; 1504 isc_result = isc_task_create(tmgr, 0, &task); 1505 if (isc_result != ISC_R_SUCCESS) { 1506 t_info("isc_task_create failed %s\n", 1507 isc_result_totext(isc_result)); 1508 isc_taskmgr_destroy(&tmgr); 1509 isc_mem_destroy(&mctx); 1510 DESTROYLOCK(&T10_mx); 1511 (void) isc_condition_destroy(&T10_cv); 1512 ++*nprobs; 1513 return; 1514 } 1515 1516 isc_result = isc_task_onshutdown(task, t10_sde, NULL); 1517 if (isc_result != ISC_R_SUCCESS) { 1518 t_info("isc_task_onshutdown returned %s\n", 1519 isc_result_totext(isc_result)); 1520 isc_task_destroy(&task); 1521 isc_taskmgr_destroy(&tmgr); 1522 isc_mem_destroy(&mctx); 1523 DESTROYLOCK(&T10_mx); 1524 (void) isc_condition_destroy(&T10_cv); 1525 ++*nprobs; 1526 return; 1527 } 1528 1529 /* 1530 * Block the task on T10_cv. 1531 */ 1532 event = isc_event_allocate(mctx, (void *)1, (isc_eventtype_t)T_CONTROL, 1533 t10_event1, NULL, sizeof(*event)); 1534 1535 if (event == NULL) { 1536 t_info("isc_event_allocate failed\n"); 1537 isc_task_destroy(&task); 1538 isc_taskmgr_destroy(&tmgr); 1539 isc_mem_destroy(&mctx); 1540 DESTROYLOCK(&T10_mx); 1541 (void) isc_condition_destroy(&T10_cv); 1542 ++*nprobs; 1543 return; 1544 } 1545 isc_task_send(task, &event); 1546 1547 /* 1548 * Fill the task's queue with some messages with varying 1549 * sender, type, tag, and purgable attribute values. 1550 */ 1551 1552 event_cnt = 0; 1553 for (sender_cnt = 0; sender_cnt < T10_SENDERCNT; ++sender_cnt) { 1554 for (type_cnt = 0; type_cnt < T10_TYPECNT; ++type_cnt) { 1555 for (tag_cnt = 0; tag_cnt < T10_TAGCNT; ++tag_cnt) { 1556 eventtab[event_cnt] = 1557 isc_event_allocate(mctx, 1558 &senders[sender + sender_cnt], 1559 (isc_eventtype_t)(type + type_cnt), 1560 t10_event2, NULL, sizeof(*event)); 1561 1562 if (eventtab[event_cnt] == NULL) { 1563 t_info("isc_event_allocate failed\n"); 1564 isc_task_destroy(&task); 1565 isc_taskmgr_destroy(&tmgr); 1566 isc_mem_destroy(&mctx); 1567 DESTROYLOCK(&T10_mx); 1568 (void) isc_condition_destroy(&T10_cv); 1569 ++*nprobs; 1570 return; 1571 } 1572 1573 eventtab[event_cnt]->ev_tag = 1574 (void *)((uintptr_t)tag + tag_cnt); 1575 1576 /* 1577 * Make all odd message non-purgable. 1578 */ 1579 if ((sender_cnt % 2) && (type_cnt %2) && 1580 (tag_cnt %2)) 1581 eventtab[event_cnt]->ev_attributes |= 1582 ISC_EVENTATTR_NOPURGE; 1583 ++event_cnt; 1584 } 1585 } 1586 } 1587 1588 for (cnt = 0; cnt < event_cnt; ++cnt) 1589 isc_task_send(task, &eventtab[cnt]); 1590 1591 if (T_debug) 1592 t_info("%d events queued\n", cnt); 1593 1594 if (testrange == 0) { 1595 /* 1596 * We're testing isc_task_purge. 1597 */ 1598 nevents = isc_task_purge(task, purge_sender, 1599 (isc_eventtype_t)purge_type_first, 1600 purge_tag); 1601 if (nevents != exp_nevents) { 1602 t_info("*** isc_task_purge returned %d, expected %d\n", 1603 nevents, exp_nevents); 1604 ++*nfails; 1605 } else if (T_debug) 1606 t_info("isc_task_purge returned %d\n", nevents); 1607 } else { 1608 /* 1609 * We're testing isc_task_purgerange. 1610 */ 1611 nevents = isc_task_purgerange(task, purge_sender, 1612 (isc_eventtype_t)purge_type_first, 1613 (isc_eventtype_t)purge_type_last, 1614 purge_tag); 1615 if (nevents != exp_nevents) { 1616 t_info("*** isc_task_purgerange returned %d, " 1617 "expected %d\n", nevents, exp_nevents); 1618 ++*nfails; 1619 } else if (T_debug) 1620 t_info("isc_task_purgerange returned %d\n", nevents); 1621 } 1622 1623 isc_result = isc_mutex_lock(&T10_mx); 1624 if (isc_result != ISC_R_SUCCESS) { 1625 t_info("isc_mutex_lock failed %s\n", 1626 isc_result_totext(isc_result)); 1627 isc_task_destroy(&task); 1628 isc_taskmgr_destroy(&tmgr); 1629 isc_mem_destroy(&mctx); 1630 DESTROYLOCK(&T10_mx); 1631 (void) isc_condition_destroy(&T10_cv); 1632 ++*nprobs; 1633 return; 1634 } 1635 1636 /* 1637 * Unblock the task, allowing event processing. 1638 */ 1639 T10_startflag = 1; 1640 isc_result = isc_condition_signal(&T10_cv); 1641 if (isc_result != ISC_R_SUCCESS) { 1642 t_info("isc_condition_signal failed %s\n", 1643 isc_result_totext(isc_result)); 1644 ++*nprobs; 1645 } 1646 1647 isc_task_shutdown(task); 1648 1649 interval.seconds = 5; 1650 interval.nanoseconds = 0; 1651 1652 /* 1653 * Wait for shutdown processing to complete. 1654 */ 1655 while (T10_shutdownflag == 0) { 1656 isc_result = isc_time_nowplusinterval(&now, &interval); 1657 if (isc_result != ISC_R_SUCCESS) { 1658 t_info("isc_time_nowplusinterval failed %s\n", 1659 isc_result_totext(isc_result)); 1660 isc_task_detach(&task); 1661 isc_taskmgr_destroy(&tmgr); 1662 isc_mem_destroy(&mctx); 1663 DESTROYLOCK(&T10_mx); 1664 (void) isc_condition_destroy(&T10_cv); 1665 ++*nprobs; 1666 return; 1667 } 1668 1669 isc_result = isc_condition_waituntil(&T10_cv, &T10_mx, &now); 1670 if (isc_result != ISC_R_SUCCESS) { 1671 t_info("isc_condition_waituntil returned %s\n", 1672 isc_result_totext(isc_result)); 1673 isc_task_detach(&task); 1674 isc_taskmgr_destroy(&tmgr); 1675 isc_mem_destroy(&mctx); 1676 DESTROYLOCK(&T10_mx); 1677 (void) isc_condition_destroy(&T10_cv); 1678 ++*nfails; 1679 return; 1680 } 1681 } 1682 1683 isc_result = isc_mutex_unlock(&T10_mx); 1684 if (isc_result != ISC_R_SUCCESS) { 1685 t_info("isc_mutex_unlock failed %s\n", 1686 isc_result_totext(isc_result)); 1687 ++*nprobs; 1688 } 1689 1690 isc_task_detach(&task); 1691 isc_taskmgr_destroy(&tmgr); 1692 isc_mem_destroy(&mctx); 1693 DESTROYLOCK(&T10_mx); 1694 (void) isc_condition_destroy(&T10_cv); 1695 1696 if (T_debug) 1697 t_info("task processed %d events\n", T10_eventcnt); 1698 1699 if ((T10_eventcnt + nevents) != event_cnt) { 1700 t_info("*** processed %d, purged %d, total %d\n", 1701 T10_eventcnt, nevents, event_cnt); 1702 ++*nfails; 1703 } 1704} 1705 1706static int 1707t_tasks10(void) { 1708 int result; 1709 1710 T10_nprobs = 0; 1711 T10_nfails = 0; 1712 1713 /* 1714 * Try purging on a specific sender. 1715 */ 1716 t_info("testing purge on 2,4,8 expecting 1\n"); 1717 t_taskpurge_x(1, 4, 7, &senders[2], 4, 4, (void *)8, 1, &T10_nfails, 1718 &T10_nprobs, 0); 1719 1720 /* 1721 * Try purging on all senders. 1722 */ 1723 t_info("testing purge on 0,4,8 expecting 3\n"); 1724 t_taskpurge_x(1, 4, 7, NULL, 4, 4, (void *)8, 3, &T10_nfails, 1725 &T10_nprobs, 0); 1726 1727 /* 1728 * Try purging on all senders, specified type, all tags. 1729 */ 1730 t_info("testing purge on 0,4,0 expecting 15\n"); 1731 t_taskpurge_x(1, 4, 7, NULL, 4, 4, NULL, 15, &T10_nfails, 1732 &T10_nprobs, 0); 1733 1734 /* 1735 * Try purging on a specified tag, no such type. 1736 */ 1737 t_info("testing purge on 0,99,8 expecting 0\n"); 1738 t_taskpurge_x(1, 4, 7, NULL, 99, 99, (void *)8, 0, &T10_nfails, 1739 &T10_nprobs, 0); 1740 1741 /* 1742 * Try purging on specified sender, type, all tags. 1743 */ 1744 t_info("testing purge on 0,5,0 expecting 5\n"); 1745 t_taskpurge_x(1, 4, 7, &senders[3], 5, 5, NULL, 5, &T10_nfails, 1746 &T10_nprobs, 0); 1747 1748 result = T_UNRESOLVED; 1749 1750 if ((T10_nfails == 0) && (T10_nprobs == 0)) 1751 result = T_PASS; 1752 else if (T10_nfails != 0) 1753 result = T_FAIL; 1754 1755 return(result); 1756} 1757 1758static const char *a10 = 1759 "A call to isc_task_purge(task, sender, type, tag) " 1760 "purges all events of type 'type' and with tag 'tag' " 1761 "not marked as unpurgable from sender from the task's " 1762 "queue and returns the number of events purged."; 1763 1764static void 1765t10(void) { 1766 t_assert("tasks", 10, T_REQUIRED, "%s", a10); 1767 1768 if (threaded) 1769 t_result(t_tasks10()); 1770 else 1771 require_threads(); 1772} 1773 1774static int T11_nprobs; 1775static int T11_nfails; 1776static int T11_startflag; 1777static int T11_shutdownflag; 1778static int T11_eventcnt; 1779static isc_mutex_t T11_mx; 1780static isc_condition_t T11_cv; 1781 1782static void 1783t11_event1(isc_task_t *task, isc_event_t *event) { 1784 isc_result_t isc_result; 1785 1786 UNUSED(task); 1787 1788 isc_result = isc_mutex_lock(&T11_mx); 1789 if (isc_result != ISC_R_SUCCESS) { 1790 t_info("isc_mutex_lock failed %s\n", 1791 isc_result_totext(isc_result)); 1792 ++T11_nprobs; 1793 } 1794 1795 while (T11_startflag == 0) { 1796 isc_result = isc_condition_wait(&T11_cv, &T11_mx); 1797 if (isc_result != ISC_R_SUCCESS) { 1798 t_info("isc_mutex_lock failed %s\n", 1799 isc_result_totext(isc_result)); 1800 ++T11_nprobs; 1801 } 1802 } 1803 1804 isc_result = isc_mutex_unlock(&T11_mx); 1805 if (isc_result != ISC_R_SUCCESS) { 1806 t_info("isc_mutex_unlock failed %s\n", 1807 isc_result_totext(isc_result)); 1808 ++T11_nprobs; 1809 } 1810 1811 isc_event_free(&event); 1812} 1813 1814static void 1815t11_event2(isc_task_t *task, isc_event_t *event) { 1816 UNUSED(task); 1817 1818 ++T11_eventcnt; 1819 isc_event_free(&event); 1820} 1821 1822 1823static void 1824t11_sde(isc_task_t *task, isc_event_t *event) { 1825 isc_result_t isc_result; 1826 1827 UNUSED(task); 1828 1829 isc_result = isc_mutex_lock(&T11_mx); 1830 if (isc_result != ISC_R_SUCCESS) { 1831 t_info("isc_mutex_lock failed %s\n", 1832 isc_result_totext(isc_result)); 1833 ++T11_nprobs; 1834 } 1835 1836 ++T11_shutdownflag; 1837 1838 isc_result = isc_condition_signal(&T11_cv); 1839 if (isc_result != ISC_R_SUCCESS) { 1840 t_info("isc_condition_signal failed %s\n", 1841 isc_result_totext(isc_result)); 1842 ++T11_nprobs; 1843 } 1844 1845 isc_result = isc_mutex_unlock(&T11_mx); 1846 if (isc_result != ISC_R_SUCCESS) { 1847 t_info("isc_mutex_unlock failed %s\n", 1848 isc_result_totext(isc_result)); 1849 ++T11_nprobs; 1850 } 1851 1852 isc_event_free(&event); 1853} 1854 1855static int 1856t_tasks11(int purgable) { 1857 char *p; 1858 isc_mem_t *mctx; 1859 isc_taskmgr_t *tmgr; 1860 isc_task_t *task; 1861 isc_boolean_t rval; 1862 unsigned int workers; 1863 isc_result_t isc_result; 1864 isc_event_t *event1; 1865 isc_event_t *event2, *event2_clone; 1866 isc_time_t now; 1867 isc_interval_t interval; 1868 int result; 1869 1870 T11_startflag = 0; 1871 T11_shutdownflag = 0; 1872 T11_eventcnt = 0; 1873 1874 workers = 2; 1875 p = t_getenv("ISC_TASK_WORKERS"); 1876 if (p != NULL) 1877 workers = atoi(p); 1878 1879 mctx = NULL; 1880 isc_result = isc_mem_create(0, 0, &mctx); 1881 if (isc_result != ISC_R_SUCCESS) { 1882 t_info("isc_mem_create failed %s\n", 1883 isc_result_totext(isc_result)); 1884 return(T_UNRESOLVED); 1885 } 1886 1887 isc_result = isc_mutex_init(&T11_mx); 1888 if (isc_result != ISC_R_SUCCESS) { 1889 t_info("isc_mutex_init failed %s\n", 1890 isc_result_totext(isc_result)); 1891 isc_mem_destroy(&mctx); 1892 return(T_UNRESOLVED); 1893 } 1894 1895 isc_result = isc_condition_init(&T11_cv); 1896 if (isc_result != ISC_R_SUCCESS) { 1897 t_info("isc_condition_init failed %s\n", 1898 isc_result_totext(isc_result)); 1899 isc_mem_destroy(&mctx); 1900 DESTROYLOCK(&T11_mx); 1901 return(T_UNRESOLVED); 1902 } 1903 1904 tmgr = NULL; 1905 isc_result = isc_taskmgr_create(mctx, workers, 0, &tmgr); 1906 if (isc_result != ISC_R_SUCCESS) { 1907 t_info("isc_taskmgr_create failed %s\n", 1908 isc_result_totext(isc_result)); 1909 isc_mem_destroy(&mctx); 1910 DESTROYLOCK(&T11_mx); 1911 (void) isc_condition_destroy(&T11_cv); 1912 return(T_UNRESOLVED); 1913 } 1914 1915 task = NULL; 1916 isc_result = isc_task_create(tmgr, 0, &task); 1917 if (isc_result != ISC_R_SUCCESS) { 1918 t_info("isc_task_create failed %s\n", 1919 isc_result_totext(isc_result)); 1920 isc_taskmgr_destroy(&tmgr); 1921 isc_mem_destroy(&mctx); 1922 DESTROYLOCK(&T11_mx); 1923 (void) isc_condition_destroy(&T11_cv); 1924 return(T_UNRESOLVED); 1925 } 1926 1927 isc_result = isc_task_onshutdown(task, t11_sde, NULL); 1928 if (isc_result != ISC_R_SUCCESS) { 1929 t_info("isc_task_onshutdown returned %s\n", 1930 isc_result_totext(isc_result)); 1931 isc_task_destroy(&task); 1932 isc_taskmgr_destroy(&tmgr); 1933 isc_mem_destroy(&mctx); 1934 DESTROYLOCK(&T11_mx); 1935 (void) isc_condition_destroy(&T11_cv); 1936 return(T_UNRESOLVED); 1937 } 1938 1939 /* 1940 * Block the task on T11_cv. 1941 */ 1942 event1 = isc_event_allocate(mctx, (void *)1, (isc_eventtype_t)1, 1943 t11_event1, NULL, sizeof(*event1)); 1944 if (event1 == NULL) { 1945 t_info("isc_event_allocate failed\n"); 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 isc_task_send(task, &event1); 1954 1955 event2 = isc_event_allocate(mctx, (void *)1, (isc_eventtype_t)1, 1956 t11_event2, NULL, sizeof(*event2)); 1957 if (event2 == NULL) { 1958 t_info("isc_event_allocate failed\n"); 1959 isc_task_destroy(&task); 1960 isc_taskmgr_destroy(&tmgr); 1961 isc_mem_destroy(&mctx); 1962 DESTROYLOCK(&T11_mx); 1963 (void) isc_condition_destroy(&T11_cv); 1964 return(T_UNRESOLVED); 1965 } 1966 event2_clone = event2; 1967 if (purgable) 1968 event2->ev_attributes &= ~ISC_EVENTATTR_NOPURGE; 1969 else 1970 event2->ev_attributes |= ISC_EVENTATTR_NOPURGE; 1971 1972 isc_task_send(task, &event2); 1973 1974 rval = isc_task_purgeevent(task, event2_clone); 1975 if (rval != (purgable ? ISC_TRUE : ISC_FALSE)) { 1976 t_info("isc_task_purgeevent returned %s, expected %s\n", 1977 (rval ? "ISC_TRUE" : "ISC_FALSE"), 1978 (purgable ? "ISC_TRUE" : "ISC_FALSE")); 1979 ++T11_nfails; 1980 } 1981 1982 isc_result = isc_mutex_lock(&T11_mx); 1983 if (isc_result != ISC_R_SUCCESS) { 1984 t_info("isc_mutex_lock failed %s\n", 1985 isc_result_totext(isc_result)); 1986 ++T11_nprobs; 1987 } 1988 1989 /* 1990 * Unblock the task, allowing event processing. 1991 */ 1992 T11_startflag = 1; 1993 isc_result = isc_condition_signal(&T11_cv); 1994 if (isc_result != ISC_R_SUCCESS) { 1995 t_info("isc_condition_signal failed %s\n", 1996 isc_result_totext(isc_result)); 1997 ++T11_nprobs; 1998 } 1999 2000 isc_task_shutdown(task); 2001 2002 interval.seconds = 5; 2003 interval.nanoseconds = 0; 2004 2005 /* 2006 * Wait for shutdown processing to complete. 2007 */ 2008 while (T11_shutdownflag == 0) { 2009 isc_result = isc_time_nowplusinterval(&now, &interval); 2010 if (isc_result != ISC_R_SUCCESS) { 2011 t_info("isc_time_nowplusinterval failed %s\n", 2012 isc_result_totext(isc_result)); 2013 ++T11_nprobs; 2014 } 2015 2016 isc_result = isc_condition_waituntil(&T11_cv, &T11_mx, &now); 2017 if (isc_result != ISC_R_SUCCESS) { 2018 t_info("isc_condition_waituntil returned %s\n", 2019 isc_result_totext(isc_result)); 2020 ++T11_nprobs; 2021 } 2022 } 2023 2024 isc_result = isc_mutex_unlock(&T11_mx); 2025 if (isc_result != ISC_R_SUCCESS) { 2026 t_info("isc_mutex_unlock failed %s\n", 2027 isc_result_totext(isc_result)); 2028 ++T11_nprobs; 2029 } 2030 2031 isc_task_detach(&task); 2032 isc_taskmgr_destroy(&tmgr); 2033 isc_mem_destroy(&mctx); 2034 DESTROYLOCK(&T11_mx); 2035 (void) isc_condition_destroy(&T11_cv); 2036 2037 if (T11_eventcnt != (purgable ? 0 : 1)) { 2038 t_info("Event was %s purged\n", 2039 (purgable ? "not" : "unexpectedly")); 2040 ++T11_nfails; 2041 } 2042 2043 result = T_UNRESOLVED; 2044 2045 if ((T11_nfails == 0) && (T11_nprobs == 0)) 2046 result = T_PASS; 2047 else if (T11_nfails) 2048 result = T_FAIL; 2049 2050 return(result); 2051} 2052 2053static const char *a11 = 2054 "When the event is marked as purgable, a call to " 2055 "isc_task_purgeevent(task, event) purges the event 'event' " 2056 "from the task's queue and returns ISC_TRUE."; 2057 2058static void 2059t11(void) { 2060 t_assert("tasks", 11, T_REQUIRED, "%s", a11); 2061 2062 if (threaded) 2063 t_result(t_tasks11(1)); 2064 else 2065 require_threads(); 2066} 2067 2068static const char *a12 = 2069 "When the event is not marked as purgable, a call to " 2070 "isc_task_purgeevent(task, event) does not purge the " 2071 "event 'event' from the task's queue and returns " 2072 "ISC_FALSE."; 2073 2074static int 2075t_tasks12(void) { 2076 return(t_tasks11(0)); 2077} 2078 2079static void 2080t12(void) { 2081 t_assert("tasks", 12, T_REQUIRED, "%s", a12); 2082 2083 if (threaded) 2084 t_result(t_tasks12()); 2085 else 2086 require_threads(); 2087} 2088 2089static int T13_nfails; 2090static int T13_nprobs; 2091 2092static const char *a13 = 2093 "A call to " 2094 "isc_event_purgerange(task, sender, first, last, tag) " 2095 "purges all events not marked unpurgable from " 2096 "sender 'sender' and of type within the range 'first' " 2097 "to 'last' inclusive from the task's event queue and " 2098 "returns the number of tasks purged."; 2099 2100static int 2101t_tasks13(void) { 2102 int result; 2103 2104 T13_nfails = 0; 2105 T13_nprobs = 0; 2106 2107 /* 2108 * First let's try the same cases we used in t10. 2109 */ 2110 2111 /* 2112 * Try purging on a specific sender. 2113 */ 2114 t_info("testing purge on 2,4,8 expecting 1\n"); 2115 t_taskpurge_x(1, 4, 7, &senders[2], 4, 4, (void *)8, 1, 2116 &T13_nfails, &T13_nprobs, 1); 2117 2118 /* 2119 * Try purging on all senders. 2120 */ 2121 t_info("testing purge on 0,4,8 expecting 3\n"); 2122 t_taskpurge_x(1, 4, 7, NULL, 4, 4, (void *)8, 3, 2123 &T13_nfails, &T13_nprobs, 1); 2124 2125 /* 2126 * Try purging on all senders, specified type, all tags. 2127 */ 2128 t_info("testing purge on 0,4,0 expecting 15\n"); 2129 t_taskpurge_x(1, 4, 7, NULL, 4, 4, NULL, 15, &T13_nfails, &T13_nprobs, 1); 2130 2131 /* 2132 * Try purging on a specified tag, no such type. 2133 */ 2134 t_info("testing purge on 0,99,8 expecting 0\n"); 2135 t_taskpurge_x(1, 4, 7, NULL, 99, 99, (void *)8, 0, 2136 &T13_nfails, &T13_nprobs, 1); 2137 2138 /* 2139 * Try purging on specified sender, type, all tags. 2140 */ 2141 t_info("testing purge on 3,5,0 expecting 5\n"); 2142 t_taskpurge_x(1, 4, 7, &senders[3], 5, 5, 0, 5, &T13_nfails, &T13_nprobs, 1); 2143 2144 /* 2145 * Now let's try some ranges. 2146 */ 2147 2148 t_info("testing purgerange on 2,4-5,8 expecting 2\n"); 2149 t_taskpurge_x(1, 4, 7, &senders[2], 4, 5, (void *)8, 1, 2150 &T13_nfails, &T13_nprobs, 1); 2151 2152 /* 2153 * Try purging on all senders. 2154 */ 2155 t_info("testing purge on 0,4-5,8 expecting 5\n"); 2156 t_taskpurge_x(1, 4, 7, NULL, 4, 5, (void *)8, 5, 2157 &T13_nfails, &T13_nprobs, 1); 2158 2159 /* 2160 * Try purging on all senders, specified type, all tags. 2161 */ 2162 t_info("testing purge on 0,5-6,0 expecting 28\n"); 2163 t_taskpurge_x(1, 4, 7, NULL, 5, 6, NULL, 28, &T13_nfails, &T13_nprobs, 1); 2164 2165 /* 2166 * Try purging on a specified tag, no such type. 2167 */ 2168 t_info("testing purge on 0,99-101,8 expecting 0\n"); 2169 t_taskpurge_x(1, 4, 7, NULL, 99, 101, (void *)8, 0, 2170 &T13_nfails, &T13_nprobs, 1); 2171 2172 /* 2173 * Try purging on specified sender, type, all tags. 2174 */ 2175 t_info("testing purge on 3,5-6,0 expecting 10\n"); 2176 t_taskpurge_x(1, 4, 7, &senders[3], 5, 6, NULL, 10, &T13_nfails, 2177 &T13_nprobs, 1); 2178 2179 result = T_UNRESOLVED; 2180 2181 if ((T13_nfails == 0) && (T13_nprobs == 0)) 2182 result = T_PASS; 2183 else if (T13_nfails) 2184 result = T_FAIL; 2185 2186 return (result); 2187} 2188 2189static void 2190t13(void) { 2191 t_assert("tasks", 13, T_REQUIRED, "%s", a13); 2192 2193 if (threaded) 2194 t_result(t_tasks13()); 2195 else 2196 require_threads(); 2197} 2198 2199#define T14_NTASKS 10 2200#define T14_EXCLTASK 6 2201 2202int t14_exclusiveerror = ISC_R_SUCCESS; 2203int t14_error = 0; 2204int t14_done = 0; 2205 2206int spin(int n); 2207 2208int t14_active[T14_NTASKS]; 2209 2210static void 2211t14_callback(isc_task_t *task, isc_event_t *event) { 2212 int taskno = *(int *)(event->ev_arg); 2213 2214 2215 t_info("task enter %d\n", taskno); 2216 if (taskno == T14_EXCLTASK) { 2217 int i; 2218 t14_exclusiveerror = isc_task_beginexclusive(task); 2219 if (t14_exclusiveerror == ISC_R_SUCCESS) 2220 t_info("task %d got exclusive access\n", taskno); 2221 else 2222 t_info("task %d failed to got exclusive access: %d\n", 2223 taskno, t14_exclusiveerror); 2224 for (i = 0; i < T14_NTASKS; i++) { 2225 t_info("task %d state %d\n", i , t14_active[i]); 2226 if (t14_active[i]) 2227 t14_error++; 2228 } 2229 isc_task_endexclusive(task); 2230 t14_done = 1; 2231 } else { 2232 t14_active[taskno]++; 2233 (void) spin(10000000); 2234 t14_active[taskno]--; 2235 } 2236 t_info("task exit %d\n", taskno); 2237 if (t14_done) { 2238 isc_mem_put(event->ev_destroy_arg, event->ev_arg, sizeof (int)); 2239 isc_event_free(&event); 2240 } else { 2241 isc_task_send(task, &event); 2242 } 2243} 2244 2245int spin(int n) { 2246 int i; 2247 int r = 0; 2248 for (i = 0; i < n; i++) { 2249 r += i; 2250 if (r > 1000000) 2251 r = 0; 2252 } 2253 return (r); 2254} 2255 2256static int 2257t_tasks14(void) { 2258 char *p; 2259 isc_mem_t *mctx; 2260 isc_taskmgr_t *manager; 2261 isc_task_t *tasks[T14_NTASKS]; 2262 unsigned int workers; 2263 isc_result_t isc_result; 2264 int i; 2265 2266 manager = NULL; 2267 mctx = NULL; 2268 2269 for (i = 0; i < T14_NTASKS; i++) 2270 tasks[i] = NULL; 2271 2272 workers = 4; 2273 p = t_getenv("ISC_TASK_WORKERS"); 2274 if (p != NULL) 2275 workers = atoi(p); 2276 if (workers < 1) { 2277 t_info("Bad config value for ISC_TASK_WORKERS, %d\n", workers); 2278 return(T_UNRESOLVED); 2279 } 2280 2281 isc_result = isc_mem_create(0, 0, &mctx); 2282 if (isc_result != ISC_R_SUCCESS) { 2283 t_info("isc_mem_create failed %d\n", isc_result); 2284 return(T_UNRESOLVED); 2285 } 2286 2287 isc_result = isc_taskmgr_create(mctx, workers, 0, &manager); 2288 if (isc_result != ISC_R_SUCCESS) { 2289 t_info("isc_taskmgr_create failed %d\n", isc_result); 2290 return(T_FAIL); 2291 } 2292 2293 for (i = 0; i < T14_NTASKS; i++) { 2294 isc_event_t *event; 2295 int *v; 2296 2297 isc_result = isc_task_create(manager, 0, &tasks[i]); 2298 if (isc_result != ISC_R_SUCCESS) { 2299 t_info("isc_task_create failed %d\n", isc_result); 2300 return(T_FAIL); 2301 } 2302 2303 v = isc_mem_get(mctx, sizeof *v); 2304 if (v == NULL) { 2305 isc_task_detach(&tasks[i]); 2306 t_info("isc_mem_get failed\n"); 2307 return(T_FAIL); 2308 } 2309 *v = i; 2310 2311 event = isc_event_allocate(mctx, NULL, 1, t14_callback, 2312 v, sizeof(*event)); 2313 if (event == NULL) { 2314 isc_mem_put(mctx, v, sizeof *v); 2315 t_info("isc_event_allocate failed\n"); 2316 return(T_UNRESOLVED); 2317 } 2318 isc_task_send(tasks[i], &event); 2319 } 2320 2321 for (i = 0; i < T14_NTASKS; i++) { 2322 isc_task_detach(&tasks[i]); 2323 } 2324 2325 isc_taskmgr_destroy(&manager); 2326 2327 if (t14_exclusiveerror != ISC_R_SUCCESS || t14_error) { 2328 if (t14_exclusiveerror != ISC_R_SUCCESS) 2329 t_info("isc_task_beginexclusive() failed\n"); 2330 if (t14_error) 2331 t_info("mutual access occurred\n"); 2332 return(T_FAIL); 2333 } 2334 2335 isc_mem_destroy(&mctx); 2336 return(T_PASS); 2337} 2338 2339static void 2340t14(void) { 2341 int result; 2342 2343 t_assert("tasks", 14, T_REQUIRED, "%s", 2344 "isc_task_beginexclusive() gets exclusive access"); 2345 result = t_tasks14(); 2346 t_result(result); 2347} 2348 2349testspec_t T_testlist[] = { 2350 { t1, "basic task subsystem" }, 2351 { t2, "maxtasks" }, 2352 { t3, "isc_task_shutdown" }, 2353 { t4, "isc_task_shutdown" }, 2354 { t7, "isc_task_create" }, 2355 { t10, "isc_task_purge" }, 2356 { t11, "isc_task_purgeevent" }, 2357 { t12, "isc_task_purgeevent" }, 2358 { t13, "isc_task_purgerange" }, 2359 { t14, "isc_task_beginexclusive" }, 2360 { NULL, NULL } 2361}; 2362