xref: /netbsd-src/tests/lib/libc/sys/t_ptrace_threads_wait.h (revision 373d242e6e77e3fdd9c7b58a53cd1af9a6395b39)
1 /*	$NetBSD: t_ptrace_threads_wait.h,v 1.1 2020/05/05 00:50:39 kamil Exp $	*/
2 
3 /*-
4  * Copyright (c) 2016, 2017, 2018, 2019, 2020 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 #define TRACE_THREADS_NUM 100
31 
32 static volatile int done;
33 pthread_mutex_t trace_threads_mtx = PTHREAD_MUTEX_INITIALIZER;
34 
35 static void *
trace_threads_cb(void * arg __unused)36 trace_threads_cb(void *arg __unused)
37 {
38 
39 	pthread_mutex_lock(&trace_threads_mtx);
40 	done++;
41 	pthread_mutex_unlock(&trace_threads_mtx);
42 
43 	while (done < TRACE_THREADS_NUM)
44 		sched_yield();
45 
46 	return NULL;
47 }
48 
49 static void
trace_threads(bool trace_create,bool trace_exit,bool masked)50 trace_threads(bool trace_create, bool trace_exit, bool masked)
51 {
52 	const int sigval = SIGSTOP;
53 	pid_t child, wpid;
54 #if defined(TWAIT_HAVE_STATUS)
55 	int status;
56 #endif
57 	ptrace_state_t state;
58 	const int slen = sizeof(state);
59 	ptrace_event_t event;
60 	const int elen = sizeof(event);
61 	struct ptrace_siginfo info;
62 
63 	sigset_t intmask;
64 
65 	pthread_t t[TRACE_THREADS_NUM];
66 	int rv;
67 	size_t n;
68 	lwpid_t lid;
69 
70 	/* Track created and exited threads */
71 	struct lwp_event_count traced_lwps[__arraycount(t)] = {{0, 0}};
72 
73 	DPRINTF("Before forking process PID=%d\n", getpid());
74 	SYSCALL_REQUIRE((child = fork()) != -1);
75 	if (child == 0) {
76 		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
77 		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
78 
79 		if (masked) {
80 			sigemptyset(&intmask);
81 			sigaddset(&intmask, SIGTRAP);
82 			sigprocmask(SIG_BLOCK, &intmask, NULL);
83 		}
84 
85 		DPRINTF("Before raising %s from child\n", strsignal(sigval));
86 		FORKEE_ASSERT(raise(sigval) == 0);
87 
88 		for (n = 0; n < __arraycount(t); n++) {
89 			rv = pthread_create(&t[n], NULL, trace_threads_cb,
90 			    NULL);
91 			FORKEE_ASSERT(rv == 0);
92 		}
93 
94 		for (n = 0; n < __arraycount(t); n++) {
95 			rv = pthread_join(t[n], NULL);
96 			FORKEE_ASSERT(rv == 0);
97 		}
98 
99 		/*
100 		 * There is race between _exit() and pthread_join() detaching
101 		 * a thread. For simplicity kill the process after detecting
102 		 * LWP events.
103 		 */
104 		while (true)
105 			continue;
106 
107 		FORKEE_ASSERT(0 && "Not reached");
108 	}
109 	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
110 
111 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
112 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
113 
114 	validate_status_stopped(status, sigval);
115 
116 	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
117 	SYSCALL_REQUIRE(
118 	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
119 
120 	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
121 	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
122 	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
123 	    info.psi_siginfo.si_errno);
124 
125 	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
126 	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
127 
128 	DPRINTF("Set LWP event mask for the child %d\n", child);
129 	memset(&event, 0, sizeof(event));
130 	if (trace_create)
131 		event.pe_set_event |= PTRACE_LWP_CREATE;
132 	if (trace_exit)
133 		event.pe_set_event |= PTRACE_LWP_EXIT;
134 	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
135 
136 	DPRINTF("Before resuming the child process where it left off and "
137 	    "without signal to be sent\n");
138 	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
139 
140 	for (n = 0; n < (trace_create ? __arraycount(t) : 0); n++) {
141 		DPRINTF("Before calling %s() for the child - expected stopped "
142 		    "SIGTRAP\n", TWAIT_FNAME);
143 		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
144 		    child);
145 
146 		validate_status_stopped(status, SIGTRAP);
147 
148 		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
149 		    "child\n");
150 		SYSCALL_REQUIRE(
151 		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
152 
153 		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
154 		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
155 		    "si_errno=%#x\n",
156 		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
157 		    info.psi_siginfo.si_errno);
158 
159 		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
160 		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP);
161 
162 		SYSCALL_REQUIRE(
163 		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
164 
165 		ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE,
166 		    "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE);
167 
168 		lid = state.pe_lwp;
169 		DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
170 
171 		*FIND_EVENT_COUNT(traced_lwps, lid) += 1;
172 
173 		DPRINTF("Before resuming the child process where it left off "
174 		    "and without signal to be sent\n");
175 		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
176 	}
177 
178 	for (n = 0; n < (trace_exit ? __arraycount(t) : 0); n++) {
179 		DPRINTF("Before calling %s() for the child - expected stopped "
180 		    "SIGTRAP\n", TWAIT_FNAME);
181 		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
182 		    child);
183 
184 		validate_status_stopped(status, SIGTRAP);
185 
186 		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
187 		    "child\n");
188 		SYSCALL_REQUIRE(
189 		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
190 
191 		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
192 		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
193 		    "si_errno=%#x\n",
194 		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
195 		    info.psi_siginfo.si_errno);
196 
197 		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
198 		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP);
199 
200 		SYSCALL_REQUIRE(
201 		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
202 
203 		ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT,
204 		    "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT);
205 
206 		lid = state.pe_lwp;
207 		DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
208 
209 		if (trace_create) {
210 			int *count = FIND_EVENT_COUNT(traced_lwps, lid);
211 			ATF_REQUIRE_EQ(*count, 1);
212 			*count = 0;
213 		}
214 
215 		DPRINTF("Before resuming the child process where it left off "
216 		    "and without signal to be sent\n");
217 		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
218 	}
219 
220 	kill(child, SIGKILL);
221 
222 	DPRINTF("Before calling %s() for the child - expected exited\n",
223 	    TWAIT_FNAME);
224 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
225 
226 	validate_status_signaled(status, SIGKILL, 0);
227 
228 	DPRINTF("Before calling %s() for the child - expected no process\n",
229 	    TWAIT_FNAME);
230 	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
231 }
232 
233 #define TRACE_THREADS(test, trace_create, trace_exit, mask)		\
234 ATF_TC(test);								\
235 ATF_TC_HEAD(test, tc)							\
236 {									\
237         atf_tc_set_md_var(tc, "descr",					\
238             "Verify spawning threads with%s tracing LWP create and"	\
239 	    "with%s tracing LWP exit", trace_create ? "" : "out",	\
240 	    trace_exit ? "" : "out");					\
241 }									\
242 									\
243 ATF_TC_BODY(test, tc)							\
244 {									\
245 									\
246         trace_threads(trace_create, trace_exit, mask);			\
247 }
248 
TRACE_THREADS(trace_thread_nolwpevents,false,false,false)249 TRACE_THREADS(trace_thread_nolwpevents, false, false, false)
250 TRACE_THREADS(trace_thread_lwpexit, false, true, false)
251 TRACE_THREADS(trace_thread_lwpcreate, true, false, false)
252 TRACE_THREADS(trace_thread_lwpcreate_and_exit, true, true, false)
253 
254 TRACE_THREADS(trace_thread_lwpexit_masked_sigtrap, false, true, true)
255 TRACE_THREADS(trace_thread_lwpcreate_masked_sigtrap, true, false, true)
256 TRACE_THREADS(trace_thread_lwpcreate_and_exit_masked_sigtrap, true, true, true)
257 
258 /// ----------------------------------------------------------------------------
259 
260 static void *
261 thread_and_exec_thread_cb(void *arg __unused)
262 {
263 
264 	execlp("/bin/echo", "/bin/echo", NULL);
265 
266 	abort();
267 }
268 
269 static void
threads_and_exec(void)270 threads_and_exec(void)
271 {
272 	const int sigval = SIGSTOP;
273 	pid_t child, wpid;
274 #if defined(TWAIT_HAVE_STATUS)
275 	int status;
276 #endif
277 	ptrace_state_t state;
278 	const int slen = sizeof(state);
279 	ptrace_event_t event;
280 	const int elen = sizeof(event);
281 	struct ptrace_siginfo info;
282 
283 	pthread_t t;
284 	lwpid_t lid;
285 
286 	DPRINTF("Before forking process PID=%d\n", getpid());
287 	SYSCALL_REQUIRE((child = fork()) != -1);
288 	if (child == 0) {
289 		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
290 		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
291 
292 		DPRINTF("Before raising %s from child\n", strsignal(sigval));
293 		FORKEE_ASSERT(raise(sigval) == 0);
294 
295 		FORKEE_ASSERT(pthread_create(&t, NULL,
296 		    thread_and_exec_thread_cb, NULL) == 0);
297 
298 		for (;;)
299 			continue;
300 
301 		FORKEE_ASSERT(0 && "Not reached");
302 	}
303 	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
304 
305 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
306 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
307 
308 	validate_status_stopped(status, sigval);
309 
310 	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
311 	SYSCALL_REQUIRE(
312 	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
313 
314 	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
315 	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
316 	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
317 	    info.psi_siginfo.si_errno);
318 
319 	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
320 	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
321 
322 	DPRINTF("Set LWP event mask for the child %d\n", child);
323 	memset(&event, 0, sizeof(event));
324 	event.pe_set_event |= PTRACE_LWP_CREATE | PTRACE_LWP_EXIT;
325 	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
326 
327 	DPRINTF("Before resuming the child process where it left off and "
328 	    "without signal to be sent\n");
329 	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
330 
331 	DPRINTF("Before calling %s() for the child - expected stopped "
332 	    "SIGTRAP\n", TWAIT_FNAME);
333 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
334 	    child);
335 
336 	validate_status_stopped(status, SIGTRAP);
337 
338 	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
339 	    "child\n");
340 	SYSCALL_REQUIRE(
341 	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
342 
343 	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
344 	DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
345 	    "si_errno=%#x\n",
346 	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
347 	    info.psi_siginfo.si_errno);
348 
349 	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
350 	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP);
351 
352 	SYSCALL_REQUIRE(
353 	    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
354 
355 	ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE,
356 	    "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE);
357 
358 	lid = state.pe_lwp;
359 	DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
360 
361 	DPRINTF("Before resuming the child process where it left off "
362 	    "and without signal to be sent\n");
363 	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
364 
365 	DPRINTF("Before calling %s() for the child - expected stopped "
366 	    "SIGTRAP\n", TWAIT_FNAME);
367 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
368 	    child);
369 
370 	validate_status_stopped(status, SIGTRAP);
371 
372 	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
373 	    "child\n");
374 	SYSCALL_REQUIRE(
375 	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
376 
377 	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
378 	DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
379 	    "si_errno=%#x\n",
380 	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
381 	    info.psi_siginfo.si_errno);
382 
383 	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
384 	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP);
385 
386 	SYSCALL_REQUIRE(
387 	    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
388 
389 	ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT,
390 	    "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT);
391 
392 	lid = state.pe_lwp;
393 	DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
394 
395 	DPRINTF("Before resuming the child process where it left off "
396 	    "and without signal to be sent\n");
397 	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
398 
399 	DPRINTF("Before calling %s() for the child - expected stopped "
400 	    "SIGTRAP\n", TWAIT_FNAME);
401 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
402 	    child);
403 
404 	validate_status_stopped(status, SIGTRAP);
405 
406 	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
407 	    "child\n");
408 	SYSCALL_REQUIRE(
409 	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
410 
411 	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
412 	DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
413 	    "si_errno=%#x\n",
414 	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
415 	    info.psi_siginfo.si_errno);
416 
417 	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
418 	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
419 
420 	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
421 
422 	DPRINTF("Before calling %s() for the child - expected exited\n",
423 	    TWAIT_FNAME);
424 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
425 
426 	validate_status_signaled(status, SIGKILL, 0);
427 
428 	DPRINTF("Before calling %s() for the child - expected no process\n",
429 	    TWAIT_FNAME);
430 	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
431 }
432 
433 ATF_TC(threads_and_exec);
ATF_TC_HEAD(threads_and_exec,tc)434 ATF_TC_HEAD(threads_and_exec, tc)
435 {
436         atf_tc_set_md_var(tc, "descr",
437             "Verify that multithreaded application on exec() will report "
438 	    "LWP_EXIT events");
439 }
440 
ATF_TC_BODY(threads_and_exec,tc)441 ATF_TC_BODY(threads_and_exec, tc)
442 {
443 
444         threads_and_exec();
445 }
446 
447 /// ----------------------------------------------------------------------------
448 
449 ATF_TC(suspend_no_deadlock);
ATF_TC_HEAD(suspend_no_deadlock,tc)450 ATF_TC_HEAD(suspend_no_deadlock, tc)
451 {
452 	atf_tc_set_md_var(tc, "descr",
453 	    "Verify that the while the only thread within a process is "
454 	    "suspended, the whole process cannot be unstopped");
455 }
456 
ATF_TC_BODY(suspend_no_deadlock,tc)457 ATF_TC_BODY(suspend_no_deadlock, tc)
458 {
459 	const int exitval = 5;
460 	const int sigval = SIGSTOP;
461 	pid_t child, wpid;
462 #if defined(TWAIT_HAVE_STATUS)
463 	int status;
464 #endif
465 	struct ptrace_siginfo psi;
466 
467 	DPRINTF("Before forking process PID=%d\n", getpid());
468 	SYSCALL_REQUIRE((child = fork()) != -1);
469 	if (child == 0) {
470 		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
471 		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
472 
473 		DPRINTF("Before raising %s from child\n", strsignal(sigval));
474 		FORKEE_ASSERT(raise(sigval) == 0);
475 
476 		DPRINTF("Before exiting of the child process\n");
477 		_exit(exitval);
478 	}
479 	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
480 
481 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
482 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
483 
484 	validate_status_stopped(status, sigval);
485 
486 	DPRINTF("Before reading siginfo and lwpid_t\n");
487 	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
488 
489 	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
490 	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
491 
492 	DPRINTF("Before resuming the child process where it left off and "
493 	    "without signal to be sent\n");
494 	ATF_REQUIRE_ERRNO(EDEADLK,
495 	    ptrace(PT_CONTINUE, child, (void *)1, 0) == -1);
496 
497 	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
498 	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
499 
500 	DPRINTF("Before resuming the child process where it left off and "
501 	    "without signal to be sent\n");
502 	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
503 
504 	DPRINTF("Before calling %s() for the child - expected exited\n",
505 	    TWAIT_FNAME);
506 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
507 
508 	validate_status_exited(status, exitval);
509 
510 	DPRINTF("Before calling %s() for the child - expected no process\n",
511 	    TWAIT_FNAME);
512 	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
513 }
514 
515 /// ----------------------------------------------------------------------------
516 
517 static pthread_barrier_t barrier1_resume;
518 static pthread_barrier_t barrier2_resume;
519 
520 static void *
resume_thread(void * arg)521 resume_thread(void *arg)
522 {
523 
524 	raise(SIGUSR1);
525 
526 	pthread_barrier_wait(&barrier1_resume);
527 
528 	/* Debugger will suspend the process here */
529 
530 	pthread_barrier_wait(&barrier2_resume);
531 
532 	raise(SIGUSR2);
533 
534 	return infinite_thread(arg);
535 }
536 
537 ATF_TC(resume);
ATF_TC_HEAD(resume,tc)538 ATF_TC_HEAD(resume, tc)
539 {
540 	atf_tc_set_md_var(tc, "descr",
541 	    "Verify that a thread can be suspended by a debugger and later "
542 	    "resumed by the debugger");
543 }
544 
ATF_TC_BODY(resume,tc)545 ATF_TC_BODY(resume, tc)
546 {
547 	const int sigval = SIGSTOP;
548 	pid_t child, wpid;
549 #if defined(TWAIT_HAVE_STATUS)
550 	int status;
551 #endif
552 	lwpid_t lid;
553 	struct ptrace_siginfo psi;
554 	pthread_t t;
555 
556 	DPRINTF("Before forking process PID=%d\n", getpid());
557 	SYSCALL_REQUIRE((child = fork()) != -1);
558 	if (child == 0) {
559 		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
560 		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
561 
562 		pthread_barrier_init(&barrier1_resume, NULL, 2);
563 		pthread_barrier_init(&barrier2_resume, NULL, 2);
564 
565 		DPRINTF("Before raising %s from child\n", strsignal(sigval));
566 		FORKEE_ASSERT(raise(sigval) == 0);
567 
568 		DPRINTF("Before creating new thread in child\n");
569 		FORKEE_ASSERT(pthread_create(&t, NULL, resume_thread, NULL) == 0);
570 
571 		pthread_barrier_wait(&barrier1_resume);
572 
573 		pthread_barrier_wait(&barrier2_resume);
574 
575 		infinite_thread(NULL);
576 	}
577 	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
578 
579 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
580 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
581 
582 	validate_status_stopped(status, sigval);
583 
584 	DPRINTF("Before resuming the child process where it left off and "
585 	    "without signal to be sent\n");
586 	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
587 
588 	DPRINTF("Before calling %s() for the child - expected stopped "
589 	    "SIGUSR1\n", TWAIT_FNAME);
590 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
591 
592 	validate_status_stopped(status, SIGUSR1);
593 
594 	DPRINTF("Before reading siginfo and lwpid_t\n");
595 	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
596 
597 	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
598 	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
599 
600 	lid = psi.psi_lwpid;
601 
602 	DPRINTF("Before resuming the child process where it left off and "
603 	    "without signal to be sent\n");
604 	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
605 
606 	DPRINTF("Before suspending the parent for 1 second, we expect no signals\n");
607 	SYSCALL_REQUIRE(sleep(1) == 0);
608 
609 #if defined(TWAIT_HAVE_OPTIONS)
610 	DPRINTF("Before calling %s() for the child - expected no status\n",
611 	    TWAIT_FNAME);
612 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, WNOHANG), 0);
613 #endif
614 
615 	DPRINTF("Before resuming the child process where it left off and "
616 	    "without signal to be sent\n");
617 	SYSCALL_REQUIRE(ptrace(PT_STOP, child, NULL, 0) != -1);
618 
619 	DPRINTF("Before calling %s() for the child - expected stopped "
620 	    "SIGSTOP\n", TWAIT_FNAME);
621 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
622 
623 	validate_status_stopped(status, SIGSTOP);
624 
625 	DPRINTF("Before resuming LWP %d\n", lid);
626 	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, lid) != -1);
627 
628 	DPRINTF("Before resuming the child process where it left off and "
629 	    "without signal to be sent\n");
630 	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
631 
632 	DPRINTF("Before calling %s() for the child - expected stopped "
633 	    "SIGUSR2\n", TWAIT_FNAME);
634 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
635 
636 	validate_status_stopped(status, SIGUSR2);
637 
638 	DPRINTF("Before resuming the child process where it left off and "
639 	    "without signal to be sent\n");
640 	SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1);
641 
642 	DPRINTF("Before calling %s() for the child - expected exited\n",
643 	    TWAIT_FNAME);
644 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
645 
646 	validate_status_signaled(status, SIGKILL, 0);
647 
648 	DPRINTF("Before calling %s() for the child - expected no process\n",
649 	    TWAIT_FNAME);
650 	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
651 }
652 
653 /// ----------------------------------------------------------------------------
654 
655 #if defined(TWAIT_HAVE_STATUS)
656 
657 #define THREAD_CONCURRENT_BREAKPOINT_NUM 50
658 #define THREAD_CONCURRENT_SIGNALS_NUM 50
659 #define THREAD_CONCURRENT_WATCHPOINT_NUM 50
660 
661 /* List of signals to use for the test */
662 const int thread_concurrent_signals_list[] = {
663 	SIGIO,
664 	SIGXCPU,
665 	SIGXFSZ,
666 	SIGVTALRM,
667 	SIGPROF,
668 	SIGWINCH,
669 	SIGINFO,
670 	SIGUSR1,
671 	SIGUSR2
672 };
673 
674 enum thread_concurrent_signal_handling {
675 	/* the signal is discarded by debugger */
676 	TCSH_DISCARD,
677 	/* the handler is set to SIG_IGN */
678 	TCSH_SIG_IGN,
679 	/* an actual handler is used */
680 	TCSH_HANDLER
681 };
682 
683 static pthread_barrier_t thread_concurrent_barrier;
684 static pthread_key_t thread_concurrent_key;
685 static uint32_t thread_concurrent_watchpoint_var = 0;
686 
687 static void *
thread_concurrent_breakpoint_thread(void * arg)688 thread_concurrent_breakpoint_thread(void *arg)
689 {
690 	static volatile int watchme = 1;
691 	pthread_barrier_wait(&thread_concurrent_barrier);
692 	DPRINTF("Before entering breakpoint func from LWP %d\n", _lwp_self());
693 	check_happy(watchme);
694 	return NULL;
695 }
696 
697 static void
thread_concurrent_sig_handler(int sig)698 thread_concurrent_sig_handler(int sig)
699 {
700 	void *tls_val = pthread_getspecific(thread_concurrent_key);
701 	DPRINTF("Before increment, LWP %d tls_val=%p\n", _lwp_self(), tls_val);
702 	FORKEE_ASSERT(pthread_setspecific(thread_concurrent_key,
703 	    (void*)((uintptr_t)tls_val + 1)) == 0);
704 }
705 
706 static void *
thread_concurrent_signals_thread(void * arg)707 thread_concurrent_signals_thread(void *arg)
708 {
709 	int sigval = thread_concurrent_signals_list[
710 	    _lwp_self() % __arraycount(thread_concurrent_signals_list)];
711 	enum thread_concurrent_signal_handling *signal_handle = arg;
712 	void *tls_val;
713 
714 	pthread_barrier_wait(&thread_concurrent_barrier);
715 	DPRINTF("Before raising %s from LWP %d\n", strsignal(sigval),
716 		_lwp_self());
717 	pthread_kill(pthread_self(), sigval);
718 	if (*signal_handle == TCSH_HANDLER) {
719 	    tls_val = pthread_getspecific(thread_concurrent_key);
720 	    DPRINTF("After raising, LWP %d tls_val=%p\n", _lwp_self(), tls_val);
721 	    FORKEE_ASSERT(tls_val == (void*)1);
722 	}
723 	return NULL;
724 }
725 
726 static void *
thread_concurrent_watchpoint_thread(void * arg)727 thread_concurrent_watchpoint_thread(void *arg)
728 {
729 	pthread_barrier_wait(&thread_concurrent_barrier);
730 	DPRINTF("Before modifying var from LWP %d\n", _lwp_self());
731 	thread_concurrent_watchpoint_var = 1;
732 	return NULL;
733 }
734 
735 #if defined(__i386__) || defined(__x86_64__)
736 enum thread_concurrent_sigtrap_event {
737 	TCSE_UNKNOWN,
738 	TCSE_BREAKPOINT,
739 	TCSE_WATCHPOINT
740 };
741 
742 static void
743 thread_concurrent_lwp_setup(pid_t child, lwpid_t lwpid);
744 static enum thread_concurrent_sigtrap_event
745 thread_concurrent_handle_sigtrap(pid_t child, ptrace_siginfo_t *info);
746 #endif
747 
748 static void
thread_concurrent_test(enum thread_concurrent_signal_handling signal_handle,int breakpoint_threads,int signal_threads,int watchpoint_threads)749 thread_concurrent_test(enum thread_concurrent_signal_handling signal_handle,
750     int breakpoint_threads, int signal_threads, int watchpoint_threads)
751 {
752 	const int exitval = 5;
753 	const int sigval = SIGSTOP;
754 	pid_t child, wpid;
755 	int status;
756 	struct lwp_event_count signal_counts[THREAD_CONCURRENT_SIGNALS_NUM]
757 	    = {{0, 0}};
758 	struct lwp_event_count bp_counts[THREAD_CONCURRENT_BREAKPOINT_NUM]
759 	    = {{0, 0}};
760 	struct lwp_event_count wp_counts[THREAD_CONCURRENT_BREAKPOINT_NUM]
761 	    = {{0, 0}};
762 	ptrace_event_t event;
763 	int i;
764 
765 #if defined(HAVE_DBREGS)
766 	if (!can_we_set_dbregs()) {
767 		atf_tc_skip("Either run this test as root or set sysctl(3) "
768 		            "security.models.extensions.user_set_dbregs to 1");
769         }
770 #endif
771 
772 	atf_tc_skip("PR kern/54960");
773 
774 	/* Protect against out-of-bounds array access. */
775 	ATF_REQUIRE(breakpoint_threads <= THREAD_CONCURRENT_BREAKPOINT_NUM);
776 	ATF_REQUIRE(signal_threads <= THREAD_CONCURRENT_SIGNALS_NUM);
777 	ATF_REQUIRE(watchpoint_threads <= THREAD_CONCURRENT_WATCHPOINT_NUM);
778 
779 	DPRINTF("Before forking process PID=%d\n", getpid());
780 	SYSCALL_REQUIRE((child = fork()) != -1);
781 	if (child == 0) {
782 		pthread_t bp_threads[THREAD_CONCURRENT_BREAKPOINT_NUM];
783 		pthread_t sig_threads[THREAD_CONCURRENT_SIGNALS_NUM];
784 		pthread_t wp_threads[THREAD_CONCURRENT_WATCHPOINT_NUM];
785 
786 		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
787 		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
788 
789 		DPRINTF("Before raising %s from child\n", strsignal(sigval));
790 		FORKEE_ASSERT(raise(sigval) == 0);
791 
792 		if (signal_handle != TCSH_DISCARD) {
793 			struct sigaction sa;
794 			unsigned int j;
795 
796 			memset(&sa, 0, sizeof(sa));
797 			if (signal_handle == TCSH_SIG_IGN)
798 				sa.sa_handler = SIG_IGN;
799 			else
800 				sa.sa_handler = thread_concurrent_sig_handler;
801 			sigemptyset(&sa.sa_mask);
802 
803 			for (j = 0;
804 			    j < __arraycount(thread_concurrent_signals_list);
805 			    j++)
806 				FORKEE_ASSERT(sigaction(
807 				    thread_concurrent_signals_list[j], &sa, NULL)
808 				    != -1);
809 		}
810 
811 		DPRINTF("Before starting threads from the child\n");
812 		FORKEE_ASSERT(pthread_barrier_init(
813 		    &thread_concurrent_barrier, NULL,
814 		    breakpoint_threads + signal_threads + watchpoint_threads)
815 		    == 0);
816 		FORKEE_ASSERT(pthread_key_create(&thread_concurrent_key, NULL)
817 		    == 0);
818 
819 		for (i = 0; i < signal_threads; i++) {
820 			FORKEE_ASSERT(pthread_create(&sig_threads[i], NULL,
821 			    thread_concurrent_signals_thread,
822 			    &signal_handle) == 0);
823 		}
824 		for (i = 0; i < breakpoint_threads; i++) {
825 			FORKEE_ASSERT(pthread_create(&bp_threads[i], NULL,
826 			    thread_concurrent_breakpoint_thread, NULL) == 0);
827 		}
828 		for (i = 0; i < watchpoint_threads; i++) {
829 			FORKEE_ASSERT(pthread_create(&wp_threads[i], NULL,
830 			    thread_concurrent_watchpoint_thread, NULL) == 0);
831 		}
832 
833 		DPRINTF("Before joining threads from the child\n");
834 		for (i = 0; i < watchpoint_threads; i++) {
835 			FORKEE_ASSERT(pthread_join(wp_threads[i], NULL) == 0);
836 		}
837 		for (i = 0; i < breakpoint_threads; i++) {
838 			FORKEE_ASSERT(pthread_join(bp_threads[i], NULL) == 0);
839 		}
840 		for (i = 0; i < signal_threads; i++) {
841 			FORKEE_ASSERT(pthread_join(sig_threads[i], NULL) == 0);
842 		}
843 
844 		FORKEE_ASSERT(pthread_key_delete(thread_concurrent_key) == 0);
845 		FORKEE_ASSERT(pthread_barrier_destroy(
846 		    &thread_concurrent_barrier) == 0);
847 
848 		DPRINTF("Before exiting of the child process\n");
849 		_exit(exitval);
850 	}
851 	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
852 
853 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
854 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
855 
856 	validate_status_stopped(status, sigval);
857 
858 	DPRINTF("Set LWP event mask for the child process\n");
859 	memset(&event, 0, sizeof(event));
860 	event.pe_set_event |= PTRACE_LWP_CREATE;
861 	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, sizeof(event))
862 	    != -1);
863 
864 	DPRINTF("Before resuming the child process where it left off\n");
865 	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
866 
867 	DPRINTF("Before entering signal collection loop\n");
868 	while (1) {
869 		ptrace_siginfo_t info;
870 
871 		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
872 		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
873 		    child);
874 		if (WIFEXITED(status))
875 			break;
876 		/* Note: we use validate_status_stopped() to get nice error
877 		 * message.  Signal is irrelevant since it won't be reached.
878 		 */
879 		else if (!WIFSTOPPED(status))
880 			validate_status_stopped(status, 0);
881 
882 		DPRINTF("Before calling PT_GET_SIGINFO\n");
883 		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
884 		    sizeof(info)) != -1);
885 
886 		DPRINTF("Received signal %d from LWP %d (wait: %d)\n",
887 		    info.psi_siginfo.si_signo, info.psi_lwpid,
888 		    WSTOPSIG(status));
889 
890 		ATF_CHECK_EQ_MSG(info.psi_siginfo.si_signo, WSTOPSIG(status),
891 		    "lwp=%d, WSTOPSIG=%d, psi_siginfo=%d", info.psi_lwpid,
892 		    WSTOPSIG(status), info.psi_siginfo.si_signo);
893 
894 		if (WSTOPSIG(status) != SIGTRAP) {
895 			int expected_sig =
896 			    thread_concurrent_signals_list[info.psi_lwpid %
897 			    __arraycount(thread_concurrent_signals_list)];
898 			ATF_CHECK_EQ_MSG(WSTOPSIG(status), expected_sig,
899 				"lwp=%d, expected %d, got %d", info.psi_lwpid,
900 				expected_sig, WSTOPSIG(status));
901 
902 			*FIND_EVENT_COUNT(signal_counts, info.psi_lwpid) += 1;
903 		} else if (info.psi_siginfo.si_code == TRAP_LWP) {
904 #if defined(__i386__) || defined(__x86_64__)
905 			thread_concurrent_lwp_setup(child, info.psi_lwpid);
906 #endif
907 		} else {
908 #if defined(__i386__) || defined(__x86_64__)
909 			switch (thread_concurrent_handle_sigtrap(child, &info)) {
910 				case TCSE_UNKNOWN:
911 					/* already reported inside the function */
912 					break;
913 				case TCSE_BREAKPOINT:
914 					*FIND_EVENT_COUNT(bp_counts,
915 					    info.psi_lwpid) += 1;
916 					break;
917 				case TCSE_WATCHPOINT:
918 					*FIND_EVENT_COUNT(wp_counts,
919 					    info.psi_lwpid) += 1;
920 					break;
921 			}
922 #else
923 			ATF_CHECK_MSG(0, "Unexpected SIGTRAP, si_code=%d\n",
924 			    info.psi_siginfo.si_code);
925 #endif
926 		}
927 
928 		DPRINTF("Before resuming the child process\n");
929 		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1,
930 		     signal_handle != TCSH_DISCARD && WSTOPSIG(status) != SIGTRAP
931 		     ? WSTOPSIG(status) : 0) != -1);
932 	}
933 
934 	for (i = 0; i < signal_threads; i++)
935 		ATF_CHECK_EQ_MSG(signal_counts[i].lec_count, 1,
936 		    "signal_counts[%d].lec_count=%d; lec_lwp=%d",
937 		    i, signal_counts[i].lec_count, signal_counts[i].lec_lwp);
938 	for (i = signal_threads; i < THREAD_CONCURRENT_SIGNALS_NUM; i++)
939 		ATF_CHECK_EQ_MSG(signal_counts[i].lec_count, 0,
940 		    "extraneous signal_counts[%d].lec_count=%d; lec_lwp=%d",
941 		    i, signal_counts[i].lec_count, signal_counts[i].lec_lwp);
942 
943 	for (i = 0; i < breakpoint_threads; i++)
944 		ATF_CHECK_EQ_MSG(bp_counts[i].lec_count, 1,
945 		    "bp_counts[%d].lec_count=%d; lec_lwp=%d",
946 		    i, bp_counts[i].lec_count, bp_counts[i].lec_lwp);
947 	for (i = breakpoint_threads; i < THREAD_CONCURRENT_BREAKPOINT_NUM; i++)
948 		ATF_CHECK_EQ_MSG(bp_counts[i].lec_count, 0,
949 		    "extraneous bp_counts[%d].lec_count=%d; lec_lwp=%d",
950 		    i, bp_counts[i].lec_count, bp_counts[i].lec_lwp);
951 
952 	for (i = 0; i < watchpoint_threads; i++)
953 		ATF_CHECK_EQ_MSG(wp_counts[i].lec_count, 1,
954 		    "wp_counts[%d].lec_count=%d; lec_lwp=%d",
955 		    i, wp_counts[i].lec_count, wp_counts[i].lec_lwp);
956 	for (i = watchpoint_threads; i < THREAD_CONCURRENT_WATCHPOINT_NUM; i++)
957 		ATF_CHECK_EQ_MSG(wp_counts[i].lec_count, 0,
958 		    "extraneous wp_counts[%d].lec_count=%d; lec_lwp=%d",
959 		    i, wp_counts[i].lec_count, wp_counts[i].lec_lwp);
960 
961 	validate_status_exited(status, exitval);
962 }
963 
964 #define THREAD_CONCURRENT_TEST(test, sig_hdl, bps, sigs, wps, descr)	\
965 ATF_TC(test);								\
966 ATF_TC_HEAD(test, tc)							\
967 {									\
968 	atf_tc_set_md_var(tc, "descr", descr);				\
969 }									\
970 									\
971 ATF_TC_BODY(test, tc)							\
972 {									\
973 	thread_concurrent_test(sig_hdl, bps, sigs, wps);		\
974 }
975 
976 THREAD_CONCURRENT_TEST(thread_concurrent_signals, TCSH_DISCARD,
977     0, THREAD_CONCURRENT_SIGNALS_NUM, 0,
978     "Verify that concurrent signals issued to a single thread are reported "
979     "correctly");
980 THREAD_CONCURRENT_TEST(thread_concurrent_signals_sig_ign, TCSH_SIG_IGN,
981     0, THREAD_CONCURRENT_SIGNALS_NUM, 0,
982     "Verify that concurrent signals issued to a single thread are reported "
983     "correctly and passed back to SIG_IGN handler");
984 THREAD_CONCURRENT_TEST(thread_concurrent_signals_handler, TCSH_HANDLER,
985     0, THREAD_CONCURRENT_SIGNALS_NUM, 0,
986     "Verify that concurrent signals issued to a single thread are reported "
987     "correctly and passed back to a handler function");
988 
989 #if defined(__i386__) || defined(__x86_64__)
990 THREAD_CONCURRENT_TEST(thread_concurrent_breakpoints, TCSH_DISCARD,
991     THREAD_CONCURRENT_BREAKPOINT_NUM, 0, 0,
992     "Verify that concurrent breakpoints are reported correctly");
993 THREAD_CONCURRENT_TEST(thread_concurrent_watchpoints, TCSH_DISCARD,
994     0, 0, THREAD_CONCURRENT_WATCHPOINT_NUM,
995     "Verify that concurrent breakpoints are reported correctly");
996 THREAD_CONCURRENT_TEST(thread_concurrent_bp_wp, TCSH_DISCARD,
997     THREAD_CONCURRENT_BREAKPOINT_NUM, 0, THREAD_CONCURRENT_WATCHPOINT_NUM,
998     "Verify that concurrent breakpoints and watchpoints are reported "
999     "correctly");
1000 
1001 THREAD_CONCURRENT_TEST(thread_concurrent_bp_sig, TCSH_DISCARD,
1002     THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM, 0,
1003     "Verify that concurrent breakpoints and signals are reported correctly");
1004 THREAD_CONCURRENT_TEST(thread_concurrent_bp_sig_sig_ign, TCSH_SIG_IGN,
1005     THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM, 0,
1006     "Verify that concurrent breakpoints and signals are reported correctly "
1007     "and passed back to SIG_IGN handler");
1008 THREAD_CONCURRENT_TEST(thread_concurrent_bp_sig_handler, TCSH_HANDLER,
1009     THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM, 0,
1010     "Verify that concurrent breakpoints and signals are reported correctly "
1011     "and passed back to a handler function");
1012 
1013 THREAD_CONCURRENT_TEST(thread_concurrent_wp_sig, TCSH_DISCARD,
1014     0, THREAD_CONCURRENT_SIGNALS_NUM, THREAD_CONCURRENT_WATCHPOINT_NUM,
1015     "Verify that concurrent watchpoints and signals are reported correctly");
1016 THREAD_CONCURRENT_TEST(thread_concurrent_wp_sig_sig_ign, TCSH_SIG_IGN,
1017     0, THREAD_CONCURRENT_SIGNALS_NUM, THREAD_CONCURRENT_WATCHPOINT_NUM,
1018     "Verify that concurrent watchpoints and signals are reported correctly "
1019     "and passed back to SIG_IGN handler");
1020 THREAD_CONCURRENT_TEST(thread_concurrent_wp_sig_handler, TCSH_HANDLER,
1021     0, THREAD_CONCURRENT_SIGNALS_NUM, THREAD_CONCURRENT_WATCHPOINT_NUM,
1022     "Verify that concurrent watchpoints and signals are reported correctly "
1023     "and passed back to a handler function");
1024 
1025 THREAD_CONCURRENT_TEST(thread_concurrent_bp_wp_sig, TCSH_DISCARD,
1026     THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM,
1027     THREAD_CONCURRENT_WATCHPOINT_NUM,
1028     "Verify that concurrent breakpoints, watchpoints and signals are reported "
1029     "correctly");
1030 THREAD_CONCURRENT_TEST(thread_concurrent_bp_wp_sig_sig_ign, TCSH_SIG_IGN,
1031     THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM,
1032     THREAD_CONCURRENT_WATCHPOINT_NUM,
1033     "Verify that concurrent breakpoints, watchpoints and signals are reported "
1034     "correctly and passed back to SIG_IGN handler");
1035 THREAD_CONCURRENT_TEST(thread_concurrent_bp_wp_sig_handler, TCSH_HANDLER,
1036     THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM,
1037     THREAD_CONCURRENT_WATCHPOINT_NUM,
1038     "Verify that concurrent breakpoints, watchpoints and signals are reported "
1039     "correctly and passed back to a handler function");
1040 #endif
1041 
1042 #endif /*defined(TWAIT_HAVE_STATUS)*/
1043 
1044 #define ATF_TP_ADD_TCS_PTRACE_WAIT_THREADS() \
1045 	ATF_TP_ADD_TC(tp, trace_thread_nolwpevents); \
1046 	ATF_TP_ADD_TC(tp, trace_thread_lwpexit); \
1047 	ATF_TP_ADD_TC(tp, trace_thread_lwpcreate); \
1048 	ATF_TP_ADD_TC(tp, trace_thread_lwpcreate_and_exit); \
1049 	ATF_TP_ADD_TC(tp, trace_thread_lwpexit_masked_sigtrap); \
1050 	ATF_TP_ADD_TC(tp, trace_thread_lwpcreate_masked_sigtrap); \
1051 	ATF_TP_ADD_TC(tp, trace_thread_lwpcreate_and_exit_masked_sigtrap); \
1052 	ATF_TP_ADD_TC(tp, threads_and_exec); \
1053 	ATF_TP_ADD_TC(tp, suspend_no_deadlock); \
1054 	ATF_TP_ADD_TC(tp, resume); \
1055 	ATF_TP_ADD_TC_HAVE_STATUS(tp, thread_concurrent_signals); \
1056 	ATF_TP_ADD_TC_HAVE_STATUS(tp, thread_concurrent_signals_sig_ign); \
1057 	ATF_TP_ADD_TC_HAVE_STATUS(tp, thread_concurrent_signals_handler); \
1058 	ATF_TP_ADD_TC_HAVE_STATUS_X86(tp, thread_concurrent_breakpoints); \
1059 	ATF_TP_ADD_TC_HAVE_STATUS_X86(tp, thread_concurrent_watchpoints); \
1060 	ATF_TP_ADD_TC_HAVE_STATUS_X86(tp, thread_concurrent_bp_wp); \
1061 	ATF_TP_ADD_TC_HAVE_STATUS_X86(tp, thread_concurrent_bp_sig); \
1062 	ATF_TP_ADD_TC_HAVE_STATUS_X86(tp, thread_concurrent_bp_sig_sig_ign); \
1063 	ATF_TP_ADD_TC_HAVE_STATUS_X86(tp, thread_concurrent_bp_sig_handler); \
1064 	ATF_TP_ADD_TC_HAVE_STATUS_X86(tp, thread_concurrent_wp_sig); \
1065 	ATF_TP_ADD_TC_HAVE_STATUS_X86(tp, thread_concurrent_wp_sig_sig_ign); \
1066 	ATF_TP_ADD_TC_HAVE_STATUS_X86(tp, thread_concurrent_wp_sig_handler); \
1067 	ATF_TP_ADD_TC_HAVE_STATUS_X86(tp, thread_concurrent_bp_wp_sig); \
1068 	ATF_TP_ADD_TC_HAVE_STATUS_X86(tp, thread_concurrent_bp_wp_sig_sig_ign); \
1069 	ATF_TP_ADD_TC_HAVE_STATUS_X86(tp, thread_concurrent_bp_wp_sig_handler);
1070