git: 359f5cf29ff1 - stable/13 - Basic signal tests: Can we deliver a signal?

From: Warner Losh <imp_at_FreeBSD.org>
Date: Mon, 06 Dec 2021 15:56:32 UTC
The branch stable/13 has been updated by imp:

URL: https://cgit.FreeBSD.org/src/commit/?id=359f5cf29ff125a9f32d1ec70b73ecbdc49c956c

commit 359f5cf29ff125a9f32d1ec70b73ecbdc49c956c
Author:     Warner Losh <imp@FreeBSD.org>
AuthorDate: 2021-11-23 20:37:14 +0000
Commit:     Warner Losh <imp@FreeBSD.org>
CommitDate: 2021-12-06 15:55:57 +0000

    Basic signal tests: Can we deliver a signal?
    
    Basic signal tests that tests can we deliver a signal via raise() and
    can we deliver one via SIGALARM asynchronously.
    
    In addition, tests whether or not on ARM T32 (Thumb) code can interrupt
    A32 (normal) and vice versa.
    
    While this test is aimed at ensuring basic qemu signals are working,
    it's good to have in the base.
    
    Sponsored by:           Netflix
    Discussed with:         kevans, cognet
    Differential Revision:  https://reviews.freebsd.org/D33078
    
    (cherry picked from commit afc5ab870d8661a7dacdbd65554c2f3533aecb8d)
---
 tests/sys/kern/Makefile       |   1 +
 tests/sys/kern/basic_signal.c | 159 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 160 insertions(+)

diff --git a/tests/sys/kern/Makefile b/tests/sys/kern/Makefile
index b0f83b97db41..b8fee0944c06 100644
--- a/tests/sys/kern/Makefile
+++ b/tests/sys/kern/Makefile
@@ -9,6 +9,7 @@ TESTSRC=	${SRCTOP}/contrib/netbsd-tests/kernel
 
 TESTSDIR=	${TESTSBASE}/sys/kern
 
+ATF_TESTS_C+=	basic_signal
 #ATF_TESTS_C+=	kcov
 ATF_TESTS_C+=	kern_copyin
 ATF_TESTS_C+=	kern_descrip_test
diff --git a/tests/sys/kern/basic_signal.c b/tests/sys/kern/basic_signal.c
new file mode 100644
index 000000000000..0b3200e2b8ab
--- /dev/null
+++ b/tests/sys/kern/basic_signal.c
@@ -0,0 +1,159 @@
+/*-
+ * Copyright (c) 2021 Warner Losh <imp@bsdimp.com>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <atf-c.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+static volatile sig_atomic_t signal_fired = 0;
+
+static void
+sig_handler(int signo, siginfo_t *info __unused, void *ucp __unused)
+{
+	signal_fired++;
+}
+
+ATF_TC(signal_test);
+
+ATF_TC_HEAD(signal_test, tc)
+{
+
+	atf_tc_set_md_var(tc, "descr", "Testing delivery of a signal");
+}
+
+ATF_TC_BODY(signal_test, tc)
+{
+	/*
+	 * Setup the signal handlers
+	 */
+	struct sigaction sa = {
+		.sa_sigaction = sig_handler,
+		.sa_flags = SA_SIGINFO,
+	};
+	ATF_REQUIRE(sigemptyset(&sa.sa_mask) == 0);
+	ATF_REQUIRE(sigaction(SIGUSR1, &sa, NULL) == 0);
+	ATF_REQUIRE(sigaction(SIGUSR2, &sa, NULL) == 0);
+	ATF_REQUIRE(sigaction(SIGALRM, &sa, NULL) == 0);
+
+	/*
+	 * Fire SIGUSR1
+	 */
+	ATF_CHECK(signal_fired == 0);
+	ATF_REQUIRE(raise(SIGUSR1) == 0);
+	ATF_CHECK(signal_fired == 1);
+
+	/*
+	 * Fire SIGUSR2
+	 */
+	ATF_REQUIRE(raise(SIGUSR2) == 0);
+	ATF_CHECK(signal_fired == 2);
+
+	/*
+	 * Fire SIGALRM after a timeout
+	 */
+	ATF_REQUIRE(alarm(1) == 0);
+	ATF_REQUIRE(pause() == -1);
+	ATF_REQUIRE(errno == EINTR);
+	ATF_CHECK(signal_fired == 3);
+}
+
+/*
+ * Special tests for 32-bit arm. We can call thumb code (really just t32) from
+ * normal (a32) mode and vice versa. Likewise, signals can interrupt a T32
+ * context with A32 code and vice versa. Make sure these all work with a simple
+ * test that raises the signal and ensures that it executed. No other platform
+ * has these requirements. Also note: we only support thumb2, so there's no T16
+ * vs T32 issues we have to test for.
+ */
+#ifdef __arm__
+
+#define a32_isa __attribute__((target("arm")))
+#define t32_isa __attribute__((target("thumb")))
+
+static volatile sig_atomic_t t32_fired = 0;
+static volatile sig_atomic_t a32_fired = 0;
+
+a32_isa static void
+sig_a32(int signo, siginfo_t *info __unused, void *ucp __unused)
+{
+	a32_fired++;
+}
+
+t32_isa static void
+sig_t32(int signo, siginfo_t *info __unused, void *ucp __unused)
+{
+	t32_fired++;
+}
+
+
+ATF_TC(signal_test_T32_to_A32);
+
+ATF_TC_HEAD(signal_test_T32_to_A32, tc)
+{
+
+	atf_tc_set_md_var(tc, "descr", "Testing delivery of a signal from T32 to A32");
+}
+
+t32_isa ATF_TC_BODY(signal_test_T32_to_A32, tc)
+{
+	/*
+	 * Setup the signal handlers
+	 */
+	struct sigaction sa = {
+		.sa_sigaction = sig_a32,
+		.sa_flags = SA_SIGINFO,
+	};
+	ATF_REQUIRE(sigemptyset(&sa.sa_mask) == 0);
+	ATF_REQUIRE(sigaction(SIGUSR1, &sa, NULL) == 0);
+
+	ATF_REQUIRE((((uintptr_t)sig_a32) & 1) == 0); /* Make sure compiled as not thumb */
+
+	ATF_CHECK(a32_fired == 0);
+	ATF_REQUIRE(raise(SIGUSR1) == 0);
+	ATF_CHECK(a32_fired == 1);
+}
+
+ATF_TC(signal_test_A32_to_T32);
+
+ATF_TC_HEAD(signal_test_A32_to_T32, tc)
+{
+
+	atf_tc_set_md_var(tc, "descr", "Testing delivery of a signal from A32 to T32");
+}
+
+a32_isa ATF_TC_BODY(signal_test_A32_to_T32, tc)
+{
+	/*
+	 * Setup the signal handlers
+	 */
+	struct sigaction sa = {
+		.sa_sigaction = sig_t32,
+		.sa_flags = SA_SIGINFO,
+	};
+	ATF_REQUIRE(sigemptyset(&sa.sa_mask) == 0);
+	ATF_REQUIRE(sigaction(SIGUSR1, &sa, NULL) == 0);
+
+	ATF_REQUIRE((((uintptr_t)sig_t32) & 1) == 1);	/* Make sure compiled as thumb */
+
+	ATF_CHECK(t32_fired == 0);
+	ATF_REQUIRE(raise(SIGUSR1) == 0);
+	ATF_CHECK(t32_fired == 1);
+}
+#endif
+
+ATF_TP_ADD_TCS(tp)
+{
+
+	ATF_TP_ADD_TC(tp, signal_test);
+#ifdef __arm__
+	ATF_TP_ADD_TC(tp, signal_test_T32_to_A32);
+	ATF_TP_ADD_TC(tp, signal_test_A32_to_T32);
+#endif
+
+	return (atf_no_error());
+}