1 /*- 2 * Copyright (c) 2021 M. Warner Losh <imp@FreeBSD.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7 #include <atf-c.h> 8 #include <errno.h> 9 #include <signal.h> 10 #include <stdbool.h> 11 #include <stdlib.h> 12 13 static volatile sig_atomic_t signal_fired = 0; 14 15 static void 16 sig_handler(int signo, siginfo_t *info __unused, void *ucp __unused) 17 { 18 signal_fired++; 19 } 20 21 ATF_TC(signal_test); 22 23 ATF_TC_HEAD(signal_test, tc) 24 { 25 26 atf_tc_set_md_var(tc, "descr", "Testing delivery of a signal"); 27 } 28 29 ATF_TC_BODY(signal_test, tc) 30 { 31 /* 32 * Setup the signal handlers 33 */ 34 struct sigaction sa = { 35 .sa_sigaction = sig_handler, 36 .sa_flags = SA_SIGINFO, 37 }; 38 ATF_REQUIRE(sigemptyset(&sa.sa_mask) == 0); 39 ATF_REQUIRE(sigaction(SIGUSR1, &sa, NULL) == 0); 40 ATF_REQUIRE(sigaction(SIGUSR2, &sa, NULL) == 0); 41 ATF_REQUIRE(sigaction(SIGALRM, &sa, NULL) == 0); 42 43 /* 44 * Fire SIGUSR1 45 */ 46 ATF_CHECK(signal_fired == 0); 47 ATF_REQUIRE(raise(SIGUSR1) == 0); 48 ATF_CHECK(signal_fired == 1); 49 50 /* 51 * Fire SIGUSR2 52 */ 53 ATF_REQUIRE(raise(SIGUSR2) == 0); 54 ATF_CHECK(signal_fired == 2); 55 56 /* 57 * Fire SIGALRM after a timeout 58 */ 59 ATF_REQUIRE(alarm(1) == 0); 60 ATF_REQUIRE(pause() == -1); 61 ATF_REQUIRE(errno == EINTR); 62 ATF_CHECK(signal_fired == 3); 63 } 64 65 /* 66 * Special tests for 32-bit arm. We can call thumb code (really just t32) from 67 * normal (a32) mode and vice versa. Likewise, signals can interrupt a T32 68 * context with A32 code and vice versa. Make sure these all work with a simple 69 * test that raises the signal and ensures that it executed. No other platform 70 * has these requirements. Also note: we only support thumb2, so there's no T16 71 * vs T32 issues we have to test for. 72 */ 73 #ifdef __arm__ 74 75 #define a32_isa __attribute__((target("arm"))) 76 #define t32_isa __attribute__((target("thumb"))) 77 78 static volatile sig_atomic_t t32_fired = 0; 79 static volatile sig_atomic_t a32_fired = 0; 80 81 a32_isa static void 82 sig_a32(int signo, siginfo_t *info __unused, void *ucp __unused) 83 { 84 a32_fired++; 85 } 86 87 t32_isa static void 88 sig_t32(int signo, siginfo_t *info __unused, void *ucp __unused) 89 { 90 t32_fired++; 91 } 92 93 94 ATF_TC(signal_test_T32_to_A32); 95 96 ATF_TC_HEAD(signal_test_T32_to_A32, tc) 97 { 98 99 atf_tc_set_md_var(tc, "descr", "Testing delivery of a signal from T32 to A32"); 100 } 101 102 t32_isa ATF_TC_BODY(signal_test_T32_to_A32, tc) 103 { 104 /* 105 * Setup the signal handlers 106 */ 107 struct sigaction sa = { 108 .sa_sigaction = sig_a32, 109 .sa_flags = SA_SIGINFO, 110 }; 111 ATF_REQUIRE(sigemptyset(&sa.sa_mask) == 0); 112 ATF_REQUIRE(sigaction(SIGUSR1, &sa, NULL) == 0); 113 114 ATF_REQUIRE((((uintptr_t)sig_a32) & 1) == 0); /* Make sure compiled as not thumb */ 115 116 ATF_CHECK(a32_fired == 0); 117 ATF_REQUIRE(raise(SIGUSR1) == 0); 118 ATF_CHECK(a32_fired == 1); 119 } 120 121 ATF_TC(signal_test_A32_to_T32); 122 123 ATF_TC_HEAD(signal_test_A32_to_T32, tc) 124 { 125 126 atf_tc_set_md_var(tc, "descr", "Testing delivery of a signal from A32 to T32"); 127 } 128 129 a32_isa ATF_TC_BODY(signal_test_A32_to_T32, tc) 130 { 131 /* 132 * Setup the signal handlers 133 */ 134 struct sigaction sa = { 135 .sa_sigaction = sig_t32, 136 .sa_flags = SA_SIGINFO, 137 }; 138 ATF_REQUIRE(sigemptyset(&sa.sa_mask) == 0); 139 ATF_REQUIRE(sigaction(SIGUSR1, &sa, NULL) == 0); 140 141 ATF_REQUIRE((((uintptr_t)sig_t32) & 1) == 1); /* Make sure compiled as thumb */ 142 143 ATF_CHECK(t32_fired == 0); 144 ATF_REQUIRE(raise(SIGUSR1) == 0); 145 ATF_CHECK(t32_fired == 1); 146 } 147 #endif 148 149 ATF_TP_ADD_TCS(tp) 150 { 151 152 ATF_TP_ADD_TC(tp, signal_test); 153 #ifdef __arm__ 154 ATF_TP_ADD_TC(tp, signal_test_T32_to_A32); 155 ATF_TP_ADD_TC(tp, signal_test_A32_to_T32); 156 #endif 157 158 return (atf_no_error()); 159 } 160