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