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