1312123Sngie/*	$NetBSD: t_threads.c,v 1.9 2017/01/13 05:18:22 christos Exp $	*/
2312123Sngie
3312123Sngie/*-
4312123Sngie * Copyright (c) 2016 The NetBSD Foundation, Inc.
5312123Sngie * All rights reserved.
6312123Sngie *
7312123Sngie * Redistribution and use in source and binary forms, with or without
8312123Sngie * modification, are permitted provided that the following conditions
9312123Sngie * are met:
10312123Sngie * 1. Redistributions of source code must retain the above copyright
11312123Sngie *    notice, this list of conditions and the following disclaimer.
12312123Sngie * 2. Redistributions in binary form must reproduce the above copyright
13312123Sngie *    notice, this list of conditions and the following disclaimer in the
14312123Sngie *    documentation and/or other materials provided with the distribution.
15312123Sngie *
16312123Sngie * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17312123Sngie * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18312123Sngie * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19312123Sngie * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20312123Sngie * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21312123Sngie * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22312123Sngie * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23312123Sngie * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24312123Sngie * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25312123Sngie * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26312123Sngie * POSSIBILITY OF SUCH DAMAGE.
27312123Sngie */
28312123Sngie
29312123Sngie
30312123Sngie#include <sys/cdefs.h>
31312123Sngie__RCSID("$NetBSD: t_threads.c,v 1.9 2017/01/13 05:18:22 christos Exp $");
32312123Sngie
33312123Sngie#include <dlfcn.h>
34312123Sngie#include <pthread.h>
35312123Sngie#include <pthread_dbg.h>
36312123Sngie#include <stdio.h>
37312123Sngie#include <string.h>
38312123Sngie#include <unistd.h>
39312123Sngie
40312123Sngie#include <atf-c.h>
41312123Sngie
42312123Sngie#include "h_common.h"
43312123Sngie
44312123Sngie#define MAX_THREADS (size_t)10
45312123Sngie
46312123SngieATF_TC(threads1);
47312123SngieATF_TC_HEAD(threads1, tc)
48312123Sngie{
49312123Sngie
50312123Sngie	atf_tc_set_md_var(tc, "descr",
51312123Sngie	    "Asserts that td_thr_iter() call without extra logic works");
52312123Sngie}
53312123Sngie
54312123Sngiestatic volatile int exiting1;
55312123Sngie
56312123Sngiestatic void *
57312123SngiebusyFunction1(void *arg)
58312123Sngie{
59312123Sngie
60312123Sngie	while (exiting1 == 0)
61312123Sngie		usleep(50000);
62312123Sngie
63312123Sngie	return NULL;
64312123Sngie}
65312123Sngie
66312123Sngiestatic int
67312123SngieiterateThreads1(td_thread_t *thread, void *arg)
68312123Sngie{
69312123Sngie
70312123Sngie	return TD_ERR_OK;
71312123Sngie}
72312123Sngie
73312123SngieATF_TC_BODY(threads1, tc)
74312123Sngie{
75312123Sngie	struct td_proc_callbacks_t dummy_callbacks;
76312123Sngie	td_proc_t *main_ta;
77312123Sngie	size_t i;
78312123Sngie	pthread_t threads[MAX_THREADS];
79312123Sngie
80312123Sngie	dummy_callbacks.proc_read	= basic_proc_read;
81312123Sngie	dummy_callbacks.proc_write	= basic_proc_write;
82312123Sngie	dummy_callbacks.proc_lookup	= basic_proc_lookup;
83312123Sngie	dummy_callbacks.proc_regsize	= dummy_proc_regsize;
84312123Sngie	dummy_callbacks.proc_getregs	= dummy_proc_getregs;
85312123Sngie	dummy_callbacks.proc_setregs	= dummy_proc_setregs;
86312123Sngie
87312123Sngie	for (i = 0; i < MAX_THREADS; i++) {
88312123Sngie		printf("Creating thread %zu\n", i);
89312123Sngie		PTHREAD_REQUIRE
90312123Sngie		    (pthread_create(&threads[i], NULL, busyFunction1, NULL));
91312123Sngie	}
92312123Sngie
93312123Sngie	printf("Calling td_open(3)\n");
94312123Sngie	ATF_REQUIRE(td_open(&dummy_callbacks, NULL, &main_ta) == TD_ERR_OK);
95312123Sngie
96312123Sngie	ATF_REQUIRE(td_thr_iter(main_ta, iterateThreads1, NULL) == TD_ERR_OK);
97312123Sngie
98312123Sngie	exiting1 = 1;
99312123Sngie
100312123Sngie	printf("Calling td_close(3)\n");
101312123Sngie	ATF_REQUIRE(td_close(main_ta) == TD_ERR_OK);
102312123Sngie}
103312123Sngie
104312123SngieATF_TC(threads2);
105312123SngieATF_TC_HEAD(threads2, tc)
106312123Sngie{
107312123Sngie
108312123Sngie	atf_tc_set_md_var(tc, "descr",
109312123Sngie	    "Asserts that td_thr_iter() call is executed for each thread once");
110312123Sngie}
111312123Sngie
112312123Sngiestatic volatile int exiting2;
113312123Sngie
114312123Sngiestatic void *
115312123SngiebusyFunction2(void *arg)
116312123Sngie{
117312123Sngie
118312123Sngie	while (exiting2 == 0)
119312123Sngie		usleep(50000);
120312123Sngie
121312123Sngie	return NULL;
122312123Sngie}
123312123Sngie
124312123Sngiestatic int
125312123SngieiterateThreads2(td_thread_t *thread, void *arg)
126312123Sngie{
127312123Sngie	int *counter = (int *)arg;
128312123Sngie
129312123Sngie	++(*counter);
130312123Sngie
131312123Sngie	return TD_ERR_OK;
132312123Sngie}
133312123Sngie
134312123SngieATF_TC_BODY(threads2, tc)
135312123Sngie{
136312123Sngie	struct td_proc_callbacks_t dummy_callbacks;
137312123Sngie	td_proc_t *main_ta;
138312123Sngie	size_t i;
139312123Sngie	pthread_t threads[MAX_THREADS];
140312123Sngie	int count = 0;
141312123Sngie
142312123Sngie	dummy_callbacks.proc_read	= basic_proc_read;
143312123Sngie	dummy_callbacks.proc_write	= basic_proc_write;
144312123Sngie	dummy_callbacks.proc_lookup	= basic_proc_lookup;
145312123Sngie	dummy_callbacks.proc_regsize	= dummy_proc_regsize;
146312123Sngie	dummy_callbacks.proc_getregs	= dummy_proc_getregs;
147312123Sngie	dummy_callbacks.proc_setregs	= dummy_proc_setregs;
148312123Sngie
149312123Sngie
150312123Sngie	for (i = 0; i < MAX_THREADS; i++) {
151312123Sngie		printf("Creating thread %zu\n", i);
152312123Sngie		PTHREAD_REQUIRE
153312123Sngie		    (pthread_create(&threads[i], NULL, busyFunction2, NULL));
154312123Sngie	}
155312123Sngie
156312123Sngie	printf("Calling td_open(3)\n");
157312123Sngie	ATF_REQUIRE(td_open(&dummy_callbacks, NULL, &main_ta) == TD_ERR_OK);
158312123Sngie
159312123Sngie	ATF_REQUIRE(td_thr_iter(main_ta, iterateThreads2, &count) == TD_ERR_OK);
160312123Sngie
161312123Sngie	exiting2 = 1;
162312123Sngie
163312123Sngie	printf("Calling td_close(3)\n");
164312123Sngie	ATF_REQUIRE(td_close(main_ta) == TD_ERR_OK);
165312123Sngie
166312123Sngie	ATF_REQUIRE_EQ_MSG(count, MAX_THREADS + 1,
167312123Sngie	    "counted threads (%d) != expected threads (%zu)",
168312123Sngie	    count, MAX_THREADS + 1);
169312123Sngie}
170312123Sngie
171312123SngieATF_TC(threads3);
172312123SngieATF_TC_HEAD(threads3, tc)
173312123Sngie{
174312123Sngie
175312123Sngie	atf_tc_set_md_var(tc, "descr",
176312123Sngie	    "Asserts that for each td_thr_iter() call td_thr_info() is valid");
177312123Sngie}
178312123Sngie
179312123Sngiestatic volatile int exiting3;
180312123Sngie
181312123Sngiestatic void *
182312123SngiebusyFunction3(void *arg)
183312123Sngie{
184312123Sngie
185312123Sngie	while (exiting3 == 0)
186312123Sngie		usleep(50000);
187312123Sngie
188312123Sngie	return NULL;
189312123Sngie}
190312123Sngie
191312123Sngiestatic int
192312123SngieiterateThreads3(td_thread_t *thread, void *arg)
193312123Sngie{
194312123Sngie	int *counter = (int *)arg;
195312123Sngie	td_thread_info_t info;
196312123Sngie
197312123Sngie	ATF_REQUIRE(td_thr_info(thread, &info) == TD_ERR_OK);
198312123Sngie
199312123Sngie	++(*counter);
200312123Sngie
201312123Sngie	return TD_ERR_OK;
202312123Sngie}
203312123Sngie
204312123SngieATF_TC_BODY(threads3, tc)
205312123Sngie{
206312123Sngie	struct td_proc_callbacks_t dummy_callbacks;
207312123Sngie	td_proc_t *main_ta;
208312123Sngie	size_t i;
209312123Sngie	pthread_t threads[MAX_THREADS];
210312123Sngie	int count = 0;
211312123Sngie
212312123Sngie	dummy_callbacks.proc_read	= basic_proc_read;
213312123Sngie	dummy_callbacks.proc_write	= basic_proc_write;
214312123Sngie	dummy_callbacks.proc_lookup	= basic_proc_lookup;
215312123Sngie	dummy_callbacks.proc_regsize	= dummy_proc_regsize;
216312123Sngie	dummy_callbacks.proc_getregs	= dummy_proc_getregs;
217312123Sngie	dummy_callbacks.proc_setregs	= dummy_proc_setregs;
218312123Sngie
219312123Sngie
220312123Sngie	for (i = 0; i < MAX_THREADS; i++) {
221312123Sngie		printf("Creating thread %zu\n", i);
222312123Sngie		PTHREAD_REQUIRE
223312123Sngie		    (pthread_create(&threads[i], NULL, busyFunction3, NULL));
224312123Sngie	}
225312123Sngie
226312123Sngie	printf("Calling td_open(3)\n");
227312123Sngie	ATF_REQUIRE(td_open(&dummy_callbacks, NULL, &main_ta) == TD_ERR_OK);
228312123Sngie
229312123Sngie	ATF_REQUIRE(td_thr_iter(main_ta, iterateThreads3, &count) == TD_ERR_OK);
230312123Sngie
231312123Sngie	exiting3 = 1;
232312123Sngie
233312123Sngie	printf("Calling td_close(3)\n");
234312123Sngie	ATF_REQUIRE(td_close(main_ta) == TD_ERR_OK);
235312123Sngie
236312123Sngie	ATF_REQUIRE_EQ_MSG(count, MAX_THREADS + 1,
237312123Sngie	    "counted threads (%d) != expected threads (%zu)",
238312123Sngie	    count, MAX_THREADS + 1);
239312123Sngie}
240312123Sngie
241312123SngieATF_TC(threads4);
242312123SngieATF_TC_HEAD(threads4, tc)
243312123Sngie{
244312123Sngie
245312123Sngie	atf_tc_set_md_var(tc, "descr",
246312123Sngie	    "Asserts that for each td_thr_iter() call td_thr_getname() is "
247312123Sngie	    "valid");
248312123Sngie}
249312123Sngie
250312123Sngiestatic volatile int exiting4;
251312123Sngie
252312123Sngiestatic void *
253312123SngiebusyFunction4(void *arg)
254312123Sngie{
255312123Sngie
256312123Sngie	while (exiting4 == 0)
257312123Sngie		usleep(50000);
258312123Sngie
259312123Sngie	return NULL;
260312123Sngie}
261312123Sngie
262312123Sngiestatic int
263312123SngieiterateThreads4(td_thread_t *thread, void *arg)
264312123Sngie{
265312123Sngie	int *counter = (int *)arg;
266312123Sngie	char name[PTHREAD_MAX_NAMELEN_NP];
267312123Sngie
268312123Sngie	ATF_REQUIRE(td_thr_getname(thread, name, sizeof(name)) == TD_ERR_OK);
269312123Sngie
270312123Sngie	printf("Thread name: %s\n", name);
271312123Sngie
272312123Sngie	++(*counter);
273312123Sngie
274312123Sngie	return TD_ERR_OK;
275312123Sngie}
276312123Sngie
277312123SngieATF_TC_BODY(threads4, tc)
278312123Sngie{
279312123Sngie	struct td_proc_callbacks_t dummy_callbacks;
280312123Sngie	td_proc_t *main_ta;
281312123Sngie	size_t i;
282312123Sngie	pthread_t threads[MAX_THREADS];
283312123Sngie	int count = 0;
284312123Sngie
285312123Sngie	dummy_callbacks.proc_read	= basic_proc_read;
286312123Sngie	dummy_callbacks.proc_write	= basic_proc_write;
287312123Sngie	dummy_callbacks.proc_lookup	= basic_proc_lookup;
288312123Sngie	dummy_callbacks.proc_regsize	= dummy_proc_regsize;
289312123Sngie	dummy_callbacks.proc_getregs	= dummy_proc_getregs;
290312123Sngie	dummy_callbacks.proc_setregs	= dummy_proc_setregs;
291312123Sngie
292312123Sngie	for (i = 0; i < MAX_THREADS; i++) {
293312123Sngie		printf("Creating thread %zu\n", i);
294312123Sngie		PTHREAD_REQUIRE
295312123Sngie		    (pthread_create(&threads[i], NULL, busyFunction4, NULL));
296312123Sngie	}
297312123Sngie
298312123Sngie	for (i = 0; i < MAX_THREADS; i++) {
299312123Sngie		PTHREAD_REQUIRE
300312123Sngie		    (pthread_setname_np(threads[i], "test_%d", (void*)i));
301312123Sngie	}
302312123Sngie
303312123Sngie	printf("Calling td_open(3)\n");
304312123Sngie	ATF_REQUIRE(td_open(&dummy_callbacks, NULL, &main_ta) == TD_ERR_OK);
305312123Sngie
306312123Sngie	ATF_REQUIRE(td_thr_iter(main_ta, iterateThreads4, &count) == TD_ERR_OK);
307312123Sngie
308312123Sngie	exiting4 = 1;
309312123Sngie
310312123Sngie	printf("Calling td_close(3)\n");
311312123Sngie	ATF_REQUIRE(td_close(main_ta) == TD_ERR_OK);
312312123Sngie
313312123Sngie	ATF_REQUIRE_EQ_MSG(count, MAX_THREADS + 1,
314312123Sngie	    "counted threads (%d) != expected threads (%zu)",
315312123Sngie	    count, MAX_THREADS + 1);
316312123Sngie}
317312123Sngie
318312123SngieATF_TC(threads5);
319312123SngieATF_TC_HEAD(threads5, tc)
320312123Sngie{
321312123Sngie
322312123Sngie	atf_tc_set_md_var(tc, "descr",
323312123Sngie	    "Asserts that td_thr_getname() handles shorter buffer parameter "
324312123Sngie	    "and the result is properly truncated");
325312123Sngie}
326312123Sngie
327312123Sngiestatic volatile int exiting5;
328312123Sngie
329312123Sngiestatic void *
330312123SngiebusyFunction5(void *arg)
331312123Sngie{
332312123Sngie
333312123Sngie	while (exiting5 == 0)
334312123Sngie		usleep(50000);
335312123Sngie
336312123Sngie	return NULL;
337312123Sngie}
338312123Sngie
339312123Sngiestatic int
340312123SngieiterateThreads5(td_thread_t *thread, void *arg)
341312123Sngie{
342312123Sngie	int *counter = (int *)arg;
343312123Sngie	/* Arbitrarily short string buffer */
344312123Sngie	char name[3];
345312123Sngie
346312123Sngie	ATF_REQUIRE(td_thr_getname(thread, name, sizeof(name)) == TD_ERR_OK);
347312123Sngie
348312123Sngie	printf("Thread name: %s\n", name);
349312123Sngie
350312123Sngie	/* strlen(3) does not count including a '\0' character */
351312123Sngie	ATF_REQUIRE(strlen(name) < sizeof(name));
352312123Sngie
353312123Sngie	++(*counter);
354312123Sngie
355312123Sngie	return TD_ERR_OK;
356312123Sngie}
357312123Sngie
358312123SngieATF_TC_BODY(threads5, tc)
359312123Sngie{
360312123Sngie	struct td_proc_callbacks_t dummy_callbacks;
361312123Sngie	td_proc_t *main_ta;
362312123Sngie	size_t i;
363312123Sngie	pthread_t threads[MAX_THREADS];
364312123Sngie	int count = 0;
365312123Sngie
366312123Sngie	dummy_callbacks.proc_read	= basic_proc_read;
367312123Sngie	dummy_callbacks.proc_write	= basic_proc_write;
368312123Sngie	dummy_callbacks.proc_lookup	= basic_proc_lookup;
369312123Sngie	dummy_callbacks.proc_regsize	= dummy_proc_regsize;
370312123Sngie	dummy_callbacks.proc_getregs	= dummy_proc_getregs;
371312123Sngie	dummy_callbacks.proc_setregs	= dummy_proc_setregs;
372312123Sngie
373312123Sngie	for (i = 0; i < MAX_THREADS; i++) {
374312123Sngie		printf("Creating thread %zu\n", i);
375312123Sngie		PTHREAD_REQUIRE
376312123Sngie		    (pthread_create(&threads[i], NULL, busyFunction5, NULL));
377312123Sngie	}
378312123Sngie
379312123Sngie	for (i = 0; i < MAX_THREADS; i++) {
380312123Sngie		PTHREAD_REQUIRE
381312123Sngie		    (pthread_setname_np(threads[i], "test_%d", (void*)i));
382312123Sngie	}
383312123Sngie
384312123Sngie	printf("Calling td_open(3)\n");
385312123Sngie	ATF_REQUIRE(td_open(&dummy_callbacks, NULL, &main_ta) == TD_ERR_OK);
386312123Sngie
387312123Sngie	ATF_REQUIRE(td_thr_iter(main_ta, iterateThreads5, &count) == TD_ERR_OK);
388312123Sngie
389312123Sngie	exiting5 = 1;
390312123Sngie
391312123Sngie	printf("Calling td_close(3)\n");
392312123Sngie	ATF_REQUIRE(td_close(main_ta) == TD_ERR_OK);
393312123Sngie
394312123Sngie	ATF_REQUIRE_EQ_MSG(count, MAX_THREADS + 1,
395312123Sngie	    "counted threads (%d) != expected threads (%zu)",
396312123Sngie	    count, MAX_THREADS + 1);
397312123Sngie}
398312123Sngie
399312123SngieATF_TC(threads6);
400312123SngieATF_TC_HEAD(threads6, tc)
401312123Sngie{
402312123Sngie
403312123Sngie	atf_tc_set_md_var(tc, "descr",
404312123Sngie	    "Asserts that pthread_t can be translated with td_map_pth2thr() "
405312123Sngie	    "to td_thread_t -- and assert earlier that td_thr_iter() call is "
406312123Sngie	    "valid");
407312123Sngie}
408312123Sngie
409312123Sngiestatic volatile int exiting6;
410312123Sngie
411312123Sngiestatic void *
412312123SngiebusyFunction6(void *arg)
413312123Sngie{
414312123Sngie
415312123Sngie	while (exiting6 == 0)
416312123Sngie		usleep(50000);
417312123Sngie
418312123Sngie	return NULL;
419312123Sngie}
420312123Sngie
421312123Sngiestatic int
422312123SngieiterateThreads6(td_thread_t *thread, void *arg)
423312123Sngie{
424312123Sngie	int *counter = (int *)arg;
425312123Sngie
426312123Sngie	++(*counter);
427312123Sngie
428312123Sngie	return TD_ERR_OK;
429312123Sngie}
430312123Sngie
431312123SngieATF_TC_BODY(threads6, tc)
432312123Sngie{
433312123Sngie	struct td_proc_callbacks_t dummy_callbacks;
434312123Sngie	td_proc_t *main_ta;
435312123Sngie	size_t i;
436312123Sngie	pthread_t threads[MAX_THREADS];
437312123Sngie	int count = 0;
438312123Sngie
439312123Sngie	dummy_callbacks.proc_read	= basic_proc_read;
440312123Sngie	dummy_callbacks.proc_write	= basic_proc_write;
441312123Sngie	dummy_callbacks.proc_lookup	= basic_proc_lookup;
442312123Sngie	dummy_callbacks.proc_regsize	= dummy_proc_regsize;
443312123Sngie	dummy_callbacks.proc_getregs	= dummy_proc_getregs;
444312123Sngie	dummy_callbacks.proc_setregs	= dummy_proc_setregs;
445312123Sngie
446312123Sngie	for (i = 0; i < MAX_THREADS; i++) {
447312123Sngie		printf("Creating thread %zu\n", i);
448312123Sngie		PTHREAD_REQUIRE
449312123Sngie		    (pthread_create(&threads[i], NULL, busyFunction6, NULL));
450312123Sngie	}
451312123Sngie
452312123Sngie	printf("Calling td_open(3)\n");
453312123Sngie	ATF_REQUIRE(td_open(&dummy_callbacks, NULL, &main_ta) == TD_ERR_OK);
454312123Sngie
455312123Sngie	ATF_REQUIRE(td_thr_iter(main_ta, iterateThreads6, &count) == TD_ERR_OK);
456312123Sngie
457312123Sngie	for (i = 0; i < MAX_THREADS; i++) {
458312123Sngie		td_thread_t *td_thread;
459312123Sngie		ATF_REQUIRE(td_map_pth2thr(main_ta, threads[i], &td_thread)
460312123Sngie		    == TD_ERR_OK);
461312123Sngie	}
462312123Sngie
463312123Sngie	exiting6 = 1;
464312123Sngie
465312123Sngie	printf("Calling td_close(3)\n");
466312123Sngie	ATF_REQUIRE(td_close(main_ta) == TD_ERR_OK);
467312123Sngie
468312123Sngie	ATF_REQUIRE_EQ_MSG(count, MAX_THREADS + 1,
469312123Sngie	    "counted threads (%d) != expected threads (%zu)",
470312123Sngie	    count, MAX_THREADS + 1);
471312123Sngie}
472312123Sngie
473312123SngieATF_TC(threads7);
474312123SngieATF_TC_HEAD(threads7, tc)
475312123Sngie{
476312123Sngie
477312123Sngie	atf_tc_set_md_var(tc, "descr",
478312123Sngie	    "Asserts that pthread_t can be translated with td_map_pth2thr() "
479312123Sngie	    "to td_thread_t -- and assert later that td_thr_iter() call is "
480312123Sngie	    "valid");
481312123Sngie}
482312123Sngie
483312123Sngiestatic volatile int exiting7;
484312123Sngie
485312123Sngiestatic void *
486312123SngiebusyFunction7(void *arg)
487312123Sngie{
488312123Sngie
489312123Sngie	while (exiting7 == 0)
490312123Sngie		usleep(50000);
491312123Sngie
492312123Sngie	return NULL;
493312123Sngie}
494312123Sngie
495312123Sngiestatic int
496312123SngieiterateThreads7(td_thread_t *thread, void *arg)
497312123Sngie{
498312123Sngie	int *counter = (int *)arg;
499312123Sngie
500312123Sngie	++(*counter);
501312123Sngie
502312123Sngie	return TD_ERR_OK;
503312123Sngie}
504312123Sngie
505312123SngieATF_TC_BODY(threads7, tc)
506312123Sngie{
507312123Sngie	struct td_proc_callbacks_t dummy_callbacks;
508312123Sngie	td_proc_t *main_ta;
509312123Sngie	size_t i;
510312123Sngie	pthread_t threads[MAX_THREADS];
511312123Sngie	int count = 0;
512312123Sngie
513312123Sngie	dummy_callbacks.proc_read	= basic_proc_read;
514312123Sngie	dummy_callbacks.proc_write	= basic_proc_write;
515312123Sngie	dummy_callbacks.proc_lookup	= basic_proc_lookup;
516312123Sngie	dummy_callbacks.proc_regsize	= dummy_proc_regsize;
517312123Sngie	dummy_callbacks.proc_getregs	= dummy_proc_getregs;
518312123Sngie	dummy_callbacks.proc_setregs	= dummy_proc_setregs;
519312123Sngie
520312123Sngie	for (i = 0; i < MAX_THREADS; i++) {
521312123Sngie		printf("Creating thread %zu\n", i);
522312123Sngie		PTHREAD_REQUIRE
523312123Sngie		    (pthread_create(&threads[i], NULL, busyFunction7, NULL));
524312123Sngie	}
525312123Sngie
526312123Sngie	printf("Calling td_open(3)\n");
527312123Sngie	ATF_REQUIRE(td_open(&dummy_callbacks, NULL, &main_ta) == TD_ERR_OK);
528312123Sngie
529312123Sngie	for (i = 0; i < MAX_THREADS; i++) {
530312123Sngie		td_thread_t *td_thread;
531312123Sngie		ATF_REQUIRE(td_map_pth2thr(main_ta, threads[i], &td_thread)
532312123Sngie		    == TD_ERR_OK);
533312123Sngie	}
534312123Sngie
535312123Sngie	ATF_REQUIRE(td_thr_iter(main_ta, iterateThreads7, &count) == TD_ERR_OK);
536312123Sngie
537312123Sngie	exiting7 = 1;
538312123Sngie
539312123Sngie	printf("Calling td_close(3)\n");
540312123Sngie	ATF_REQUIRE(td_close(main_ta) == TD_ERR_OK);
541312123Sngie
542312123Sngie	ATF_REQUIRE_EQ_MSG(count, MAX_THREADS + 1,
543312123Sngie	    "counted threads (%d) != expected threads (%zu)",
544312123Sngie	    count, MAX_THREADS + 1);
545312123Sngie}
546312123Sngie
547312123SngieATF_TC(threads8);
548312123SngieATF_TC_HEAD(threads8, tc)
549312123Sngie{
550312123Sngie
551312123Sngie	atf_tc_set_md_var(tc, "descr",
552312123Sngie	    "Asserts that pthread_t can be translated with td_map_pth2thr() "
553312123Sngie	    "to td_thread_t -- compare thread's name of pthread_t and "
554312123Sngie	    "td_thread_t");
555312123Sngie}
556312123Sngie
557312123Sngiestatic volatile int exiting8;
558312123Sngie
559312123Sngiestatic void *
560312123SngiebusyFunction8(void *arg)
561312123Sngie{
562312123Sngie
563312123Sngie	while (exiting8 == 0)
564312123Sngie		usleep(50000);
565312123Sngie
566312123Sngie	return NULL;
567312123Sngie}
568312123Sngie
569312123Sngiestatic int
570312123SngieiterateThreads8(td_thread_t *thread, void *arg)
571312123Sngie{
572312123Sngie	int *counter = (int *)arg;
573312123Sngie
574312123Sngie	++(*counter);
575312123Sngie
576312123Sngie	return TD_ERR_OK;
577312123Sngie}
578312123Sngie
579312123SngieATF_TC_BODY(threads8, tc)
580312123Sngie{
581312123Sngie	struct td_proc_callbacks_t dummy_callbacks;
582312123Sngie	td_proc_t *main_ta;
583312123Sngie	size_t i;
584312123Sngie	pthread_t threads[MAX_THREADS];
585312123Sngie	int count = 0;
586312123Sngie
587312123Sngie	dummy_callbacks.proc_read	= basic_proc_read;
588312123Sngie	dummy_callbacks.proc_write	= basic_proc_write;
589312123Sngie	dummy_callbacks.proc_lookup	= basic_proc_lookup;
590312123Sngie	dummy_callbacks.proc_regsize	= dummy_proc_regsize;
591312123Sngie	dummy_callbacks.proc_getregs	= dummy_proc_getregs;
592312123Sngie	dummy_callbacks.proc_setregs	= dummy_proc_setregs;
593312123Sngie
594312123Sngie	for (i = 0; i < MAX_THREADS; i++) {
595312123Sngie		printf("Creating thread %zu\n", i);
596312123Sngie		PTHREAD_REQUIRE
597312123Sngie		    (pthread_create(&threads[i], NULL, busyFunction8, NULL));
598312123Sngie	}
599312123Sngie
600312123Sngie	printf("Calling td_open(3)\n");
601312123Sngie	ATF_REQUIRE(td_open(&dummy_callbacks, NULL, &main_ta) == TD_ERR_OK);
602312123Sngie
603312123Sngie	ATF_REQUIRE(td_thr_iter(main_ta, iterateThreads8, &count) == TD_ERR_OK);
604312123Sngie
605312123Sngie	for (i = 0; i < MAX_THREADS; i++) {
606312123Sngie		td_thread_t *td_thread;
607312123Sngie		char td_threadname[PTHREAD_MAX_NAMELEN_NP];
608312123Sngie		char pth_threadname[PTHREAD_MAX_NAMELEN_NP];
609312123Sngie		ATF_REQUIRE(td_map_pth2thr(main_ta, threads[i], &td_thread)
610312123Sngie		    == TD_ERR_OK);
611312123Sngie		ATF_REQUIRE(td_thr_getname(td_thread, td_threadname,
612312123Sngie		    sizeof(td_threadname)) == TD_ERR_OK);
613312123Sngie		PTHREAD_REQUIRE(pthread_getname_np(threads[i], pth_threadname,
614312123Sngie		    sizeof(pth_threadname)));
615312123Sngie		ATF_REQUIRE(strcmp(td_threadname, pth_threadname) == 0);
616312123Sngie	}
617312123Sngie
618312123Sngie	exiting8 = 1;
619312123Sngie
620312123Sngie	printf("Calling td_close(3)\n");
621312123Sngie	ATF_REQUIRE(td_close(main_ta) == TD_ERR_OK);
622312123Sngie
623312123Sngie	ATF_REQUIRE_EQ_MSG(count, MAX_THREADS + 1,
624312123Sngie	    "counted threads (%d) != expected threads (%zu)",
625312123Sngie	    count, MAX_THREADS + 1);
626312123Sngie}
627312123Sngie
628312123SngieATF_TC(threads9);
629312123SngieATF_TC_HEAD(threads9, tc)
630312123Sngie{
631312123Sngie
632312123Sngie	atf_tc_set_md_var(tc, "descr",
633312123Sngie	    "Asserts that pthread_t can be translated with td_map_pth2thr() "
634312123Sngie	    "to td_thread_t -- assert that thread is in the TD_STATE_RUNNING "
635312123Sngie            "state");
636312123Sngie}
637312123Sngie
638312123Sngiestatic volatile int exiting9;
639312123Sngie
640312123Sngiestatic void *
641312123SngiebusyFunction9(void *arg)
642312123Sngie{
643312123Sngie
644312123Sngie	while (exiting9 == 0)
645312123Sngie		usleep(50000);
646312123Sngie
647312123Sngie	return NULL;
648312123Sngie}
649312123Sngie
650312123Sngiestatic int
651312123SngieiterateThreads9(td_thread_t *thread, void *arg)
652312123Sngie{
653312123Sngie	int *counter = (int *)arg;
654312123Sngie
655312123Sngie	++(*counter);
656312123Sngie
657312123Sngie	return TD_ERR_OK;
658312123Sngie}
659312123Sngie
660312123SngieATF_TC_BODY(threads9, tc)
661312123Sngie{
662312123Sngie	struct td_proc_callbacks_t dummy_callbacks;
663312123Sngie	td_proc_t *main_ta;
664312123Sngie	size_t i;
665312123Sngie	pthread_t threads[MAX_THREADS];
666312123Sngie	int count = 0;
667312123Sngie
668312123Sngie	dummy_callbacks.proc_read	= basic_proc_read;
669312123Sngie	dummy_callbacks.proc_write	= basic_proc_write;
670312123Sngie	dummy_callbacks.proc_lookup	= basic_proc_lookup;
671312123Sngie	dummy_callbacks.proc_regsize	= dummy_proc_regsize;
672312123Sngie	dummy_callbacks.proc_getregs	= dummy_proc_getregs;
673312123Sngie	dummy_callbacks.proc_setregs	= dummy_proc_setregs;
674312123Sngie
675312123Sngie	for (i = 0; i < MAX_THREADS; i++) {
676312123Sngie		printf("Creating thread %zu\n", i);
677312123Sngie		PTHREAD_REQUIRE
678312123Sngie		    (pthread_create(&threads[i], NULL, busyFunction9, NULL));
679312123Sngie	}
680312123Sngie
681312123Sngie	printf("Calling td_open(3)\n");
682312123Sngie	ATF_REQUIRE(td_open(&dummy_callbacks, NULL, &main_ta) == TD_ERR_OK);
683312123Sngie
684312123Sngie	for (i = 0; i < MAX_THREADS; i++) {
685312123Sngie		td_thread_t *td_thread;
686312123Sngie		td_thread_info_t info;
687312123Sngie		ATF_REQUIRE(td_map_pth2thr(main_ta, threads[i], &td_thread)
688312123Sngie		    == TD_ERR_OK);
689312123Sngie		ATF_REQUIRE(td_thr_info(td_thread, &info) == TD_ERR_OK);
690312123Sngie		ATF_REQUIRE_EQ(info.thread_state, TD_STATE_RUNNING);
691312123Sngie	}
692312123Sngie
693312123Sngie	ATF_REQUIRE(td_thr_iter(main_ta, iterateThreads9, &count) == TD_ERR_OK);
694312123Sngie
695312123Sngie	exiting9 = 1;
696312123Sngie
697312123Sngie	printf("Calling td_close(3)\n");
698312123Sngie	ATF_REQUIRE(td_close(main_ta) == TD_ERR_OK);
699312123Sngie
700312123Sngie	ATF_REQUIRE_EQ_MSG(count, MAX_THREADS + 1,
701312123Sngie	    "counted threads (%d) != expected threads (%zu)",
702312123Sngie	    count, MAX_THREADS + 1);
703312123Sngie}
704312123Sngie
705312123SngieATF_TP_ADD_TCS(tp)
706312123Sngie{
707312123Sngie
708312123Sngie	ATF_TP_ADD_TC(tp, threads1);
709312123Sngie	ATF_TP_ADD_TC(tp, threads2);
710312123Sngie	ATF_TP_ADD_TC(tp, threads3);
711312123Sngie	ATF_TP_ADD_TC(tp, threads4);
712312123Sngie	ATF_TP_ADD_TC(tp, threads5);
713312123Sngie	ATF_TP_ADD_TC(tp, threads6);
714312123Sngie	ATF_TP_ADD_TC(tp, threads7);
715312123Sngie	ATF_TP_ADD_TC(tp, threads8);
716312123Sngie	ATF_TP_ADD_TC(tp, threads9);
717312123Sngie
718312123Sngie	return atf_no_error();
719312123Sngie}
720