Generalize thread_concurrent_signals to a generic factory

Build thread_concurrent_signals on a generic parametrized
thread_concurrent_test() function.  At first, this permits adjusting
the number of running signal threads but in the followup commits
support for different concurrent events (breakpoints, watchpoints)
and different signal handling will be added.
This commit is contained in:
mgorny 2020-02-13 15:25:29 +00:00
parent 35bacae748
commit 767bd35aa5
1 changed files with 41 additions and 24 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: t_ptrace_wait.c,v 1.155 2020/02/11 00:41:37 kamil Exp $ */
/* $NetBSD: t_ptrace_wait.c,v 1.156 2020/02/13 15:25:29 mgorny Exp $ */
/*-
* Copyright (c) 2016, 2017, 2018, 2019 The NetBSD Foundation, Inc.
@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: t_ptrace_wait.c,v 1.155 2020/02/11 00:41:37 kamil Exp $");
__RCSID("$NetBSD: t_ptrace_wait.c,v 1.156 2020/02/13 15:25:29 mgorny Exp $");
#define __LEGACY_PT_LWPINFO
@ -8620,13 +8620,7 @@ ATF_TC_BODY(core_dump_procinfo, tc)
#if defined(TWAIT_HAVE_STATUS)
ATF_TC(thread_concurrent_signals);
ATF_TC_HEAD(thread_concurrent_signals, tc)
{
atf_tc_set_md_var(tc, "descr",
"Verify that concurrent signals issued to a single thread "
"are reported correctly");
}
#define THREAD_CONCURRENT_SIGNALS_NUM 50
/* List of signals to use for the test */
const int thread_concurrent_signals_list[] = {
@ -8641,23 +8635,22 @@ const int thread_concurrent_signals_list[] = {
SIGUSR2
};
pthread_barrier_t thread_concurrent_signals_barrier;
static pthread_barrier_t thread_concurrent_barrier;
static void *
thread_concurrent_signals_thread(void *arg)
{
int sigval = thread_concurrent_signals_list[
_lwp_self() % __arraycount(thread_concurrent_signals_list)];
pthread_barrier_wait(&thread_concurrent_signals_barrier);
pthread_barrier_wait(&thread_concurrent_barrier);
DPRINTF("Before raising %s from LWP %d\n", strsignal(sigval),
_lwp_self());
pthread_kill(pthread_self(), sigval);
return NULL;
}
#define THREAD_CONCURRENT_SIGNALS_NUM 50
ATF_TC_BODY(thread_concurrent_signals, tc)
static void
thread_concurrent_test(int signal_threads)
{
const int exitval = 5;
const int sigval = SIGSTOP;
@ -8665,12 +8658,15 @@ ATF_TC_BODY(thread_concurrent_signals, tc)
int status;
struct lwp_event_count signal_counts[THREAD_CONCURRENT_SIGNALS_NUM]
= {{0, 0}};
unsigned int i;
int i;
/* Protect against out-of-bounds array access. */
ATF_REQUIRE(signal_threads <= THREAD_CONCURRENT_SIGNALS_NUM);
DPRINTF("Before forking process PID=%d\n", getpid());
SYSCALL_REQUIRE((child = fork()) != -1);
if (child == 0) {
pthread_t threads[THREAD_CONCURRENT_SIGNALS_NUM];
pthread_t sig_threads[THREAD_CONCURRENT_SIGNALS_NUM];
DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
@ -8680,21 +8676,21 @@ ATF_TC_BODY(thread_concurrent_signals, tc)
DPRINTF("Before starting threads from the child\n");
FORKEE_ASSERT(pthread_barrier_init(
&thread_concurrent_signals_barrier, NULL,
__arraycount(threads)) == 0);
&thread_concurrent_barrier, NULL,
signal_threads) == 0);
for (i = 0; i < __arraycount(threads); i++) {
FORKEE_ASSERT(pthread_create(&threads[i], NULL,
for (i = 0; i < signal_threads; i++) {
FORKEE_ASSERT(pthread_create(&sig_threads[i], NULL,
thread_concurrent_signals_thread, NULL) == 0);
}
DPRINTF("Before joining threads from the child\n");
for (i = 0; i < __arraycount(threads); i++) {
FORKEE_ASSERT(pthread_join(threads[i], NULL) == 0);
for (i = 0; i < signal_threads; i++) {
FORKEE_ASSERT(pthread_join(sig_threads[i], NULL) == 0);
}
FORKEE_ASSERT(pthread_barrier_destroy(
&thread_concurrent_signals_barrier) == 0);
&thread_concurrent_barrier) == 0);
DPRINTF("Before exiting of the child process\n");
_exit(exitval);
@ -8748,14 +8744,35 @@ ATF_TC_BODY(thread_concurrent_signals, tc)
SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
}
for (i = 0; i < __arraycount(signal_counts); i++)
for (i = 0; i < signal_threads; i++)
ATF_CHECK_EQ_MSG(signal_counts[i].lec_count, 1,
"signal_counts[%d].lec_count=%d; lec_lwp=%d",
i, signal_counts[i].lec_count, signal_counts[i].lec_lwp);
for (i = signal_threads; i < THREAD_CONCURRENT_SIGNALS_NUM; i++)
ATF_CHECK_EQ_MSG(signal_counts[i].lec_count, 0,
"extraneous signal_counts[%d].lec_count=%d; lec_lwp=%d",
i, signal_counts[i].lec_count, signal_counts[i].lec_lwp);
validate_status_exited(status, exitval);
}
#define THREAD_CONCURRENT_TEST(test, sigs, descr) \
ATF_TC(test); \
ATF_TC_HEAD(test, tc) \
{ \
atf_tc_set_md_var(tc, "descr", descr); \
} \
\
ATF_TC_BODY(test, tc) \
{ \
thread_concurrent_test(sigs); \
}
THREAD_CONCURRENT_TEST(thread_concurrent_signals,
THREAD_CONCURRENT_SIGNALS_NUM,
"Verify that concurrent signals issued to a single thread are reported "
"correctly");
#endif /*defined(TWAIT_HAVE_STATUS)*/
/// ----------------------------------------------------------------------------