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