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
46 ATF_TC(threads1);
ATF_TC_HEAD(threads1,tc)47 ATF_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
54 static volatile int exiting1;
55
56 static void *
busyFunction1(void * arg)57 busyFunction1(void *arg)
58 {
59
60 while (exiting1 == 0)
61 usleep(50000);
62
63 return NULL;
64 }
65
66 static int
iterateThreads1(td_thread_t * thread,void * arg)67 iterateThreads1(td_thread_t *thread, void *arg)
68 {
69
70 return TD_ERR_OK;
71 }
72
ATF_TC_BODY(threads1,tc)73 ATF_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
104 ATF_TC(threads2);
ATF_TC_HEAD(threads2,tc)105 ATF_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
112 static volatile int exiting2;
113
114 static void *
busyFunction2(void * arg)115 busyFunction2(void *arg)
116 {
117
118 while (exiting2 == 0)
119 usleep(50000);
120
121 return NULL;
122 }
123
124 static int
iterateThreads2(td_thread_t * thread,void * arg)125 iterateThreads2(td_thread_t *thread, void *arg)
126 {
127 int *counter = (int *)arg;
128
129 ++(*counter);
130
131 return TD_ERR_OK;
132 }
133
ATF_TC_BODY(threads2,tc)134 ATF_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
171 ATF_TC(threads3);
ATF_TC_HEAD(threads3,tc)172 ATF_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
179 static volatile int exiting3;
180
181 static void *
busyFunction3(void * arg)182 busyFunction3(void *arg)
183 {
184
185 while (exiting3 == 0)
186 usleep(50000);
187
188 return NULL;
189 }
190
191 static int
iterateThreads3(td_thread_t * thread,void * arg)192 iterateThreads3(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
ATF_TC_BODY(threads3,tc)204 ATF_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
241 ATF_TC(threads4);
ATF_TC_HEAD(threads4,tc)242 ATF_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
250 static volatile int exiting4;
251
252 static void *
busyFunction4(void * arg)253 busyFunction4(void *arg)
254 {
255
256 while (exiting4 == 0)
257 usleep(50000);
258
259 return NULL;
260 }
261
262 static int
iterateThreads4(td_thread_t * thread,void * arg)263 iterateThreads4(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
ATF_TC_BODY(threads4,tc)277 ATF_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
318 ATF_TC(threads5);
ATF_TC_HEAD(threads5,tc)319 ATF_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
327 static volatile int exiting5;
328
329 static void *
busyFunction5(void * arg)330 busyFunction5(void *arg)
331 {
332
333 while (exiting5 == 0)
334 usleep(50000);
335
336 return NULL;
337 }
338
339 static int
iterateThreads5(td_thread_t * thread,void * arg)340 iterateThreads5(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
ATF_TC_BODY(threads5,tc)358 ATF_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
399 ATF_TC(threads6);
ATF_TC_HEAD(threads6,tc)400 ATF_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
409 static volatile int exiting6;
410
411 static void *
busyFunction6(void * arg)412 busyFunction6(void *arg)
413 {
414
415 while (exiting6 == 0)
416 usleep(50000);
417
418 return NULL;
419 }
420
421 static int
iterateThreads6(td_thread_t * thread,void * arg)422 iterateThreads6(td_thread_t *thread, void *arg)
423 {
424 int *counter = (int *)arg;
425
426 ++(*counter);
427
428 return TD_ERR_OK;
429 }
430
ATF_TC_BODY(threads6,tc)431 ATF_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
473 ATF_TC(threads7);
ATF_TC_HEAD(threads7,tc)474 ATF_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
483 static volatile int exiting7;
484
485 static void *
busyFunction7(void * arg)486 busyFunction7(void *arg)
487 {
488
489 while (exiting7 == 0)
490 usleep(50000);
491
492 return NULL;
493 }
494
495 static int
iterateThreads7(td_thread_t * thread,void * arg)496 iterateThreads7(td_thread_t *thread, void *arg)
497 {
498 int *counter = (int *)arg;
499
500 ++(*counter);
501
502 return TD_ERR_OK;
503 }
504
ATF_TC_BODY(threads7,tc)505 ATF_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
547 ATF_TC(threads8);
ATF_TC_HEAD(threads8,tc)548 ATF_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
557 static volatile int exiting8;
558
559 static void *
busyFunction8(void * arg)560 busyFunction8(void *arg)
561 {
562
563 while (exiting8 == 0)
564 usleep(50000);
565
566 return NULL;
567 }
568
569 static int
iterateThreads8(td_thread_t * thread,void * arg)570 iterateThreads8(td_thread_t *thread, void *arg)
571 {
572 int *counter = (int *)arg;
573
574 ++(*counter);
575
576 return TD_ERR_OK;
577 }
578
ATF_TC_BODY(threads8,tc)579 ATF_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
628 ATF_TC(threads9);
ATF_TC_HEAD(threads9,tc)629 ATF_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
638 static volatile int exiting9;
639
640 static void *
busyFunction9(void * arg)641 busyFunction9(void *arg)
642 {
643
644 while (exiting9 == 0)
645 usleep(50000);
646
647 return NULL;
648 }
649
650 static int
iterateThreads9(td_thread_t * thread,void * arg)651 iterateThreads9(td_thread_t *thread, void *arg)
652 {
653 int *counter = (int *)arg;
654
655 ++(*counter);
656
657 return TD_ERR_OK;
658 }
659
ATF_TC_BODY(threads9,tc)660 ATF_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
ATF_TP_ADD_TCS(tp)705 ATF_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