1/* $NetBSD: t_threads.c,v 1.9 2017/01/13 05:18:22 christos Exp $ */ 2 3/*- 4 * Copyright (c) 2016 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 30#include <sys/cdefs.h> 31__RCSID("$NetBSD: t_threads.c,v 1.9 2017/01/13 05:18:22 christos Exp $"); 32 33#include <dlfcn.h> 34#include <pthread.h> 35#include <pthread_dbg.h> 36#include <stdio.h> 37#include <string.h> 38#include <unistd.h> 39 40#include <atf-c.h> 41 42#include "h_common.h" 43 44#define MAX_THREADS (size_t)10 45 46ATF_TC(threads1); 47ATF_TC_HEAD(threads1, tc) 48{ 49 50 atf_tc_set_md_var(tc, "descr", 51 "Asserts that td_thr_iter() call without extra logic works"); 52} 53 54static volatile int exiting1; 55 56static void * 57busyFunction1(void *arg) 58{ 59 60 while (exiting1 == 0) 61 usleep(50000); 62 63 return NULL; 64} 65 66static int 67iterateThreads1(td_thread_t *thread, void *arg) 68{ 69 70 return TD_ERR_OK; 71} 72 73ATF_TC_BODY(threads1, tc) 74{ 75 struct td_proc_callbacks_t dummy_callbacks; 76 td_proc_t *main_ta; 77 size_t i; 78 pthread_t threads[MAX_THREADS]; 79 80 dummy_callbacks.proc_read = basic_proc_read; 81 dummy_callbacks.proc_write = basic_proc_write; 82 dummy_callbacks.proc_lookup = basic_proc_lookup; 83 dummy_callbacks.proc_regsize = dummy_proc_regsize; 84 dummy_callbacks.proc_getregs = dummy_proc_getregs; 85 dummy_callbacks.proc_setregs = dummy_proc_setregs; 86 87 for (i = 0; i < MAX_THREADS; i++) { 88 printf("Creating thread %zu\n", i); 89 PTHREAD_REQUIRE 90 (pthread_create(&threads[i], NULL, busyFunction1, NULL)); 91 } 92 93 printf("Calling td_open(3)\n"); 94 ATF_REQUIRE(td_open(&dummy_callbacks, NULL, &main_ta) == TD_ERR_OK); 95 96 ATF_REQUIRE(td_thr_iter(main_ta, iterateThreads1, NULL) == TD_ERR_OK); 97 98 exiting1 = 1; 99 100 printf("Calling td_close(3)\n"); 101 ATF_REQUIRE(td_close(main_ta) == TD_ERR_OK); 102} 103 104ATF_TC(threads2); 105ATF_TC_HEAD(threads2, tc) 106{ 107 108 atf_tc_set_md_var(tc, "descr", 109 "Asserts that td_thr_iter() call is executed for each thread once"); 110} 111 112static volatile int exiting2; 113 114static void * 115busyFunction2(void *arg) 116{ 117 118 while (exiting2 == 0) 119 usleep(50000); 120 121 return NULL; 122} 123 124static int 125iterateThreads2(td_thread_t *thread, void *arg) 126{ 127 int *counter = (int *)arg; 128 129 ++(*counter); 130 131 return TD_ERR_OK; 132} 133 134ATF_TC_BODY(threads2, tc) 135{ 136 struct td_proc_callbacks_t dummy_callbacks; 137 td_proc_t *main_ta; 138 size_t i; 139 pthread_t threads[MAX_THREADS]; 140 int count = 0; 141 142 dummy_callbacks.proc_read = basic_proc_read; 143 dummy_callbacks.proc_write = basic_proc_write; 144 dummy_callbacks.proc_lookup = basic_proc_lookup; 145 dummy_callbacks.proc_regsize = dummy_proc_regsize; 146 dummy_callbacks.proc_getregs = dummy_proc_getregs; 147 dummy_callbacks.proc_setregs = dummy_proc_setregs; 148 149 150 for (i = 0; i < MAX_THREADS; i++) { 151 printf("Creating thread %zu\n", i); 152 PTHREAD_REQUIRE 153 (pthread_create(&threads[i], NULL, busyFunction2, NULL)); 154 } 155 156 printf("Calling td_open(3)\n"); 157 ATF_REQUIRE(td_open(&dummy_callbacks, NULL, &main_ta) == TD_ERR_OK); 158 159 ATF_REQUIRE(td_thr_iter(main_ta, iterateThreads2, &count) == TD_ERR_OK); 160 161 exiting2 = 1; 162 163 printf("Calling td_close(3)\n"); 164 ATF_REQUIRE(td_close(main_ta) == TD_ERR_OK); 165 166 ATF_REQUIRE_EQ_MSG(count, MAX_THREADS + 1, 167 "counted threads (%d) != expected threads (%zu)", 168 count, MAX_THREADS + 1); 169} 170 171ATF_TC(threads3); 172ATF_TC_HEAD(threads3, tc) 173{ 174 175 atf_tc_set_md_var(tc, "descr", 176 "Asserts that for each td_thr_iter() call td_thr_info() is valid"); 177} 178 179static volatile int exiting3; 180 181static void * 182busyFunction3(void *arg) 183{ 184 185 while (exiting3 == 0) 186 usleep(50000); 187 188 return NULL; 189} 190 191static int 192iterateThreads3(td_thread_t *thread, void *arg) 193{ 194 int *counter = (int *)arg; 195 td_thread_info_t info; 196 197 ATF_REQUIRE(td_thr_info(thread, &info) == TD_ERR_OK); 198 199 ++(*counter); 200 201 return TD_ERR_OK; 202} 203 204ATF_TC_BODY(threads3, tc) 205{ 206 struct td_proc_callbacks_t dummy_callbacks; 207 td_proc_t *main_ta; 208 size_t i; 209 pthread_t threads[MAX_THREADS]; 210 int count = 0; 211 212 dummy_callbacks.proc_read = basic_proc_read; 213 dummy_callbacks.proc_write = basic_proc_write; 214 dummy_callbacks.proc_lookup = basic_proc_lookup; 215 dummy_callbacks.proc_regsize = dummy_proc_regsize; 216 dummy_callbacks.proc_getregs = dummy_proc_getregs; 217 dummy_callbacks.proc_setregs = dummy_proc_setregs; 218 219 220 for (i = 0; i < MAX_THREADS; i++) { 221 printf("Creating thread %zu\n", i); 222 PTHREAD_REQUIRE 223 (pthread_create(&threads[i], NULL, busyFunction3, NULL)); 224 } 225 226 printf("Calling td_open(3)\n"); 227 ATF_REQUIRE(td_open(&dummy_callbacks, NULL, &main_ta) == TD_ERR_OK); 228 229 ATF_REQUIRE(td_thr_iter(main_ta, iterateThreads3, &count) == TD_ERR_OK); 230 231 exiting3 = 1; 232 233 printf("Calling td_close(3)\n"); 234 ATF_REQUIRE(td_close(main_ta) == TD_ERR_OK); 235 236 ATF_REQUIRE_EQ_MSG(count, MAX_THREADS + 1, 237 "counted threads (%d) != expected threads (%zu)", 238 count, MAX_THREADS + 1); 239} 240 241ATF_TC(threads4); 242ATF_TC_HEAD(threads4, tc) 243{ 244 245 atf_tc_set_md_var(tc, "descr", 246 "Asserts that for each td_thr_iter() call td_thr_getname() is " 247 "valid"); 248} 249 250static volatile int exiting4; 251 252static void * 253busyFunction4(void *arg) 254{ 255 256 while (exiting4 == 0) 257 usleep(50000); 258 259 return NULL; 260} 261 262static int 263iterateThreads4(td_thread_t *thread, void *arg) 264{ 265 int *counter = (int *)arg; 266 char name[PTHREAD_MAX_NAMELEN_NP]; 267 268 ATF_REQUIRE(td_thr_getname(thread, name, sizeof(name)) == TD_ERR_OK); 269 270 printf("Thread name: %s\n", name); 271 272 ++(*counter); 273 274 return TD_ERR_OK; 275} 276 277ATF_TC_BODY(threads4, tc) 278{ 279 struct td_proc_callbacks_t dummy_callbacks; 280 td_proc_t *main_ta; 281 size_t i; 282 pthread_t threads[MAX_THREADS]; 283 int count = 0; 284 285 dummy_callbacks.proc_read = basic_proc_read; 286 dummy_callbacks.proc_write = basic_proc_write; 287 dummy_callbacks.proc_lookup = basic_proc_lookup; 288 dummy_callbacks.proc_regsize = dummy_proc_regsize; 289 dummy_callbacks.proc_getregs = dummy_proc_getregs; 290 dummy_callbacks.proc_setregs = dummy_proc_setregs; 291 292 for (i = 0; i < MAX_THREADS; i++) { 293 printf("Creating thread %zu\n", i); 294 PTHREAD_REQUIRE 295 (pthread_create(&threads[i], NULL, busyFunction4, NULL)); 296 } 297 298 for (i = 0; i < MAX_THREADS; i++) { 299 PTHREAD_REQUIRE 300 (pthread_setname_np(threads[i], "test_%d", (void*)i)); 301 } 302 303 printf("Calling td_open(3)\n"); 304 ATF_REQUIRE(td_open(&dummy_callbacks, NULL, &main_ta) == TD_ERR_OK); 305 306 ATF_REQUIRE(td_thr_iter(main_ta, iterateThreads4, &count) == TD_ERR_OK); 307 308 exiting4 = 1; 309 310 printf("Calling td_close(3)\n"); 311 ATF_REQUIRE(td_close(main_ta) == TD_ERR_OK); 312 313 ATF_REQUIRE_EQ_MSG(count, MAX_THREADS + 1, 314 "counted threads (%d) != expected threads (%zu)", 315 count, MAX_THREADS + 1); 316} 317 318ATF_TC(threads5); 319ATF_TC_HEAD(threads5, tc) 320{ 321 322 atf_tc_set_md_var(tc, "descr", 323 "Asserts that td_thr_getname() handles shorter buffer parameter " 324 "and the result is properly truncated"); 325} 326 327static volatile int exiting5; 328 329static void * 330busyFunction5(void *arg) 331{ 332 333 while (exiting5 == 0) 334 usleep(50000); 335 336 return NULL; 337} 338 339static int 340iterateThreads5(td_thread_t *thread, void *arg) 341{ 342 int *counter = (int *)arg; 343 /* Arbitrarily short string buffer */ 344 char name[3]; 345 346 ATF_REQUIRE(td_thr_getname(thread, name, sizeof(name)) == TD_ERR_OK); 347 348 printf("Thread name: %s\n", name); 349 350 /* strlen(3) does not count including a '\0' character */ 351 ATF_REQUIRE(strlen(name) < sizeof(name)); 352 353 ++(*counter); 354 355 return TD_ERR_OK; 356} 357 358ATF_TC_BODY(threads5, tc) 359{ 360 struct td_proc_callbacks_t dummy_callbacks; 361 td_proc_t *main_ta; 362 size_t i; 363 pthread_t threads[MAX_THREADS]; 364 int count = 0; 365 366 dummy_callbacks.proc_read = basic_proc_read; 367 dummy_callbacks.proc_write = basic_proc_write; 368 dummy_callbacks.proc_lookup = basic_proc_lookup; 369 dummy_callbacks.proc_regsize = dummy_proc_regsize; 370 dummy_callbacks.proc_getregs = dummy_proc_getregs; 371 dummy_callbacks.proc_setregs = dummy_proc_setregs; 372 373 for (i = 0; i < MAX_THREADS; i++) { 374 printf("Creating thread %zu\n", i); 375 PTHREAD_REQUIRE 376 (pthread_create(&threads[i], NULL, busyFunction5, NULL)); 377 } 378 379 for (i = 0; i < MAX_THREADS; i++) { 380 PTHREAD_REQUIRE 381 (pthread_setname_np(threads[i], "test_%d", (void*)i)); 382 } 383 384 printf("Calling td_open(3)\n"); 385 ATF_REQUIRE(td_open(&dummy_callbacks, NULL, &main_ta) == TD_ERR_OK); 386 387 ATF_REQUIRE(td_thr_iter(main_ta, iterateThreads5, &count) == TD_ERR_OK); 388 389 exiting5 = 1; 390 391 printf("Calling td_close(3)\n"); 392 ATF_REQUIRE(td_close(main_ta) == TD_ERR_OK); 393 394 ATF_REQUIRE_EQ_MSG(count, MAX_THREADS + 1, 395 "counted threads (%d) != expected threads (%zu)", 396 count, MAX_THREADS + 1); 397} 398 399ATF_TC(threads6); 400ATF_TC_HEAD(threads6, tc) 401{ 402 403 atf_tc_set_md_var(tc, "descr", 404 "Asserts that pthread_t can be translated with td_map_pth2thr() " 405 "to td_thread_t -- and assert earlier that td_thr_iter() call is " 406 "valid"); 407} 408 409static volatile int exiting6; 410 411static void * 412busyFunction6(void *arg) 413{ 414 415 while (exiting6 == 0) 416 usleep(50000); 417 418 return NULL; 419} 420 421static int 422iterateThreads6(td_thread_t *thread, void *arg) 423{ 424 int *counter = (int *)arg; 425 426 ++(*counter); 427 428 return TD_ERR_OK; 429} 430 431ATF_TC_BODY(threads6, tc) 432{ 433 struct td_proc_callbacks_t dummy_callbacks; 434 td_proc_t *main_ta; 435 size_t i; 436 pthread_t threads[MAX_THREADS]; 437 int count = 0; 438 439 dummy_callbacks.proc_read = basic_proc_read; 440 dummy_callbacks.proc_write = basic_proc_write; 441 dummy_callbacks.proc_lookup = basic_proc_lookup; 442 dummy_callbacks.proc_regsize = dummy_proc_regsize; 443 dummy_callbacks.proc_getregs = dummy_proc_getregs; 444 dummy_callbacks.proc_setregs = dummy_proc_setregs; 445 446 for (i = 0; i < MAX_THREADS; i++) { 447 printf("Creating thread %zu\n", i); 448 PTHREAD_REQUIRE 449 (pthread_create(&threads[i], NULL, busyFunction6, NULL)); 450 } 451 452 printf("Calling td_open(3)\n"); 453 ATF_REQUIRE(td_open(&dummy_callbacks, NULL, &main_ta) == TD_ERR_OK); 454 455 ATF_REQUIRE(td_thr_iter(main_ta, iterateThreads6, &count) == TD_ERR_OK); 456 457 for (i = 0; i < MAX_THREADS; i++) { 458 td_thread_t *td_thread; 459 ATF_REQUIRE(td_map_pth2thr(main_ta, threads[i], &td_thread) 460 == TD_ERR_OK); 461 } 462 463 exiting6 = 1; 464 465 printf("Calling td_close(3)\n"); 466 ATF_REQUIRE(td_close(main_ta) == TD_ERR_OK); 467 468 ATF_REQUIRE_EQ_MSG(count, MAX_THREADS + 1, 469 "counted threads (%d) != expected threads (%zu)", 470 count, MAX_THREADS + 1); 471} 472 473ATF_TC(threads7); 474ATF_TC_HEAD(threads7, tc) 475{ 476 477 atf_tc_set_md_var(tc, "descr", 478 "Asserts that pthread_t can be translated with td_map_pth2thr() " 479 "to td_thread_t -- and assert later that td_thr_iter() call is " 480 "valid"); 481} 482 483static volatile int exiting7; 484 485static void * 486busyFunction7(void *arg) 487{ 488 489 while (exiting7 == 0) 490 usleep(50000); 491 492 return NULL; 493} 494 495static int 496iterateThreads7(td_thread_t *thread, void *arg) 497{ 498 int *counter = (int *)arg; 499 500 ++(*counter); 501 502 return TD_ERR_OK; 503} 504 505ATF_TC_BODY(threads7, tc) 506{ 507 struct td_proc_callbacks_t dummy_callbacks; 508 td_proc_t *main_ta; 509 size_t i; 510 pthread_t threads[MAX_THREADS]; 511 int count = 0; 512 513 dummy_callbacks.proc_read = basic_proc_read; 514 dummy_callbacks.proc_write = basic_proc_write; 515 dummy_callbacks.proc_lookup = basic_proc_lookup; 516 dummy_callbacks.proc_regsize = dummy_proc_regsize; 517 dummy_callbacks.proc_getregs = dummy_proc_getregs; 518 dummy_callbacks.proc_setregs = dummy_proc_setregs; 519 520 for (i = 0; i < MAX_THREADS; i++) { 521 printf("Creating thread %zu\n", i); 522 PTHREAD_REQUIRE 523 (pthread_create(&threads[i], NULL, busyFunction7, NULL)); 524 } 525 526 printf("Calling td_open(3)\n"); 527 ATF_REQUIRE(td_open(&dummy_callbacks, NULL, &main_ta) == TD_ERR_OK); 528 529 for (i = 0; i < MAX_THREADS; i++) { 530 td_thread_t *td_thread; 531 ATF_REQUIRE(td_map_pth2thr(main_ta, threads[i], &td_thread) 532 == TD_ERR_OK); 533 } 534 535 ATF_REQUIRE(td_thr_iter(main_ta, iterateThreads7, &count) == TD_ERR_OK); 536 537 exiting7 = 1; 538 539 printf("Calling td_close(3)\n"); 540 ATF_REQUIRE(td_close(main_ta) == TD_ERR_OK); 541 542 ATF_REQUIRE_EQ_MSG(count, MAX_THREADS + 1, 543 "counted threads (%d) != expected threads (%zu)", 544 count, MAX_THREADS + 1); 545} 546 547ATF_TC(threads8); 548ATF_TC_HEAD(threads8, tc) 549{ 550 551 atf_tc_set_md_var(tc, "descr", 552 "Asserts that pthread_t can be translated with td_map_pth2thr() " 553 "to td_thread_t -- compare thread's name of pthread_t and " 554 "td_thread_t"); 555} 556 557static volatile int exiting8; 558 559static void * 560busyFunction8(void *arg) 561{ 562 563 while (exiting8 == 0) 564 usleep(50000); 565 566 return NULL; 567} 568 569static int 570iterateThreads8(td_thread_t *thread, void *arg) 571{ 572 int *counter = (int *)arg; 573 574 ++(*counter); 575 576 return TD_ERR_OK; 577} 578 579ATF_TC_BODY(threads8, tc) 580{ 581 struct td_proc_callbacks_t dummy_callbacks; 582 td_proc_t *main_ta; 583 size_t i; 584 pthread_t threads[MAX_THREADS]; 585 int count = 0; 586 587 dummy_callbacks.proc_read = basic_proc_read; 588 dummy_callbacks.proc_write = basic_proc_write; 589 dummy_callbacks.proc_lookup = basic_proc_lookup; 590 dummy_callbacks.proc_regsize = dummy_proc_regsize; 591 dummy_callbacks.proc_getregs = dummy_proc_getregs; 592 dummy_callbacks.proc_setregs = dummy_proc_setregs; 593 594 for (i = 0; i < MAX_THREADS; i++) { 595 printf("Creating thread %zu\n", i); 596 PTHREAD_REQUIRE 597 (pthread_create(&threads[i], NULL, busyFunction8, NULL)); 598 } 599 600 printf("Calling td_open(3)\n"); 601 ATF_REQUIRE(td_open(&dummy_callbacks, NULL, &main_ta) == TD_ERR_OK); 602 603 ATF_REQUIRE(td_thr_iter(main_ta, iterateThreads8, &count) == TD_ERR_OK); 604 605 for (i = 0; i < MAX_THREADS; i++) { 606 td_thread_t *td_thread; 607 char td_threadname[PTHREAD_MAX_NAMELEN_NP]; 608 char pth_threadname[PTHREAD_MAX_NAMELEN_NP]; 609 ATF_REQUIRE(td_map_pth2thr(main_ta, threads[i], &td_thread) 610 == TD_ERR_OK); 611 ATF_REQUIRE(td_thr_getname(td_thread, td_threadname, 612 sizeof(td_threadname)) == TD_ERR_OK); 613 PTHREAD_REQUIRE(pthread_getname_np(threads[i], pth_threadname, 614 sizeof(pth_threadname))); 615 ATF_REQUIRE(strcmp(td_threadname, pth_threadname) == 0); 616 } 617 618 exiting8 = 1; 619 620 printf("Calling td_close(3)\n"); 621 ATF_REQUIRE(td_close(main_ta) == TD_ERR_OK); 622 623 ATF_REQUIRE_EQ_MSG(count, MAX_THREADS + 1, 624 "counted threads (%d) != expected threads (%zu)", 625 count, MAX_THREADS + 1); 626} 627 628ATF_TC(threads9); 629ATF_TC_HEAD(threads9, tc) 630{ 631 632 atf_tc_set_md_var(tc, "descr", 633 "Asserts that pthread_t can be translated with td_map_pth2thr() " 634 "to td_thread_t -- assert that thread is in the TD_STATE_RUNNING " 635 "state"); 636} 637 638static volatile int exiting9; 639 640static void * 641busyFunction9(void *arg) 642{ 643 644 while (exiting9 == 0) 645 usleep(50000); 646 647 return NULL; 648} 649 650static int 651iterateThreads9(td_thread_t *thread, void *arg) 652{ 653 int *counter = (int *)arg; 654 655 ++(*counter); 656 657 return TD_ERR_OK; 658} 659 660ATF_TC_BODY(threads9, tc) 661{ 662 struct td_proc_callbacks_t dummy_callbacks; 663 td_proc_t *main_ta; 664 size_t i; 665 pthread_t threads[MAX_THREADS]; 666 int count = 0; 667 668 dummy_callbacks.proc_read = basic_proc_read; 669 dummy_callbacks.proc_write = basic_proc_write; 670 dummy_callbacks.proc_lookup = basic_proc_lookup; 671 dummy_callbacks.proc_regsize = dummy_proc_regsize; 672 dummy_callbacks.proc_getregs = dummy_proc_getregs; 673 dummy_callbacks.proc_setregs = dummy_proc_setregs; 674 675 for (i = 0; i < MAX_THREADS; i++) { 676 printf("Creating thread %zu\n", i); 677 PTHREAD_REQUIRE 678 (pthread_create(&threads[i], NULL, busyFunction9, NULL)); 679 } 680 681 printf("Calling td_open(3)\n"); 682 ATF_REQUIRE(td_open(&dummy_callbacks, NULL, &main_ta) == TD_ERR_OK); 683 684 for (i = 0; i < MAX_THREADS; i++) { 685 td_thread_t *td_thread; 686 td_thread_info_t info; 687 ATF_REQUIRE(td_map_pth2thr(main_ta, threads[i], &td_thread) 688 == TD_ERR_OK); 689 ATF_REQUIRE(td_thr_info(td_thread, &info) == TD_ERR_OK); 690 ATF_REQUIRE_EQ(info.thread_state, TD_STATE_RUNNING); 691 } 692 693 ATF_REQUIRE(td_thr_iter(main_ta, iterateThreads9, &count) == TD_ERR_OK); 694 695 exiting9 = 1; 696 697 printf("Calling td_close(3)\n"); 698 ATF_REQUIRE(td_close(main_ta) == TD_ERR_OK); 699 700 ATF_REQUIRE_EQ_MSG(count, MAX_THREADS + 1, 701 "counted threads (%d) != expected threads (%zu)", 702 count, MAX_THREADS + 1); 703} 704 705ATF_TP_ADD_TCS(tp) 706{ 707 708 ATF_TP_ADD_TC(tp, threads1); 709 ATF_TP_ADD_TC(tp, threads2); 710 ATF_TP_ADD_TC(tp, threads3); 711 ATF_TP_ADD_TC(tp, threads4); 712 ATF_TP_ADD_TC(tp, threads5); 713 ATF_TP_ADD_TC(tp, threads6); 714 ATF_TP_ADD_TC(tp, threads7); 715 ATF_TP_ADD_TC(tp, threads8); 716 ATF_TP_ADD_TC(tp, threads9); 717 718 return atf_no_error(); 719} 720