~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/bpf/prog_tests/send_signal.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 #include <test_progs.h>
  3 #include <sys/time.h>
  4 #include <sys/resource.h>
  5 #include "test_send_signal_kern.skel.h"
  6 
  7 static int sigusr1_received;
  8 
  9 static void sigusr1_handler(int signum)
 10 {
 11         sigusr1_received = 1;
 12 }
 13 
 14 static void test_send_signal_common(struct perf_event_attr *attr,
 15                                     bool signal_thread)
 16 {
 17         struct test_send_signal_kern *skel;
 18         int pipe_c2p[2], pipe_p2c[2];
 19         int err = -1, pmu_fd = -1;
 20         char buf[256];
 21         pid_t pid;
 22 
 23         if (!ASSERT_OK(pipe(pipe_c2p), "pipe_c2p"))
 24                 return;
 25 
 26         if (!ASSERT_OK(pipe(pipe_p2c), "pipe_p2c")) {
 27                 close(pipe_c2p[0]);
 28                 close(pipe_c2p[1]);
 29                 return;
 30         }
 31 
 32         pid = fork();
 33         if (!ASSERT_GE(pid, 0, "fork")) {
 34                 close(pipe_c2p[0]);
 35                 close(pipe_c2p[1]);
 36                 close(pipe_p2c[0]);
 37                 close(pipe_p2c[1]);
 38                 return;
 39         }
 40 
 41         if (pid == 0) {
 42                 int old_prio;
 43                 volatile int j = 0;
 44 
 45                 /* install signal handler and notify parent */
 46                 ASSERT_NEQ(signal(SIGUSR1, sigusr1_handler), SIG_ERR, "signal");
 47 
 48                 close(pipe_c2p[0]); /* close read */
 49                 close(pipe_p2c[1]); /* close write */
 50 
 51                 /* boost with a high priority so we got a higher chance
 52                  * that if an interrupt happens, the underlying task
 53                  * is this process.
 54                  */
 55                 errno = 0;
 56                 old_prio = getpriority(PRIO_PROCESS, 0);
 57                 ASSERT_OK(errno, "getpriority");
 58                 ASSERT_OK(setpriority(PRIO_PROCESS, 0, -20), "setpriority");
 59 
 60                 /* notify parent signal handler is installed */
 61                 ASSERT_EQ(write(pipe_c2p[1], buf, 1), 1, "pipe_write");
 62 
 63                 /* make sure parent enabled bpf program to send_signal */
 64                 ASSERT_EQ(read(pipe_p2c[0], buf, 1), 1, "pipe_read");
 65 
 66                 /* wait a little for signal handler */
 67                 for (int i = 0; i < 1000000000 && !sigusr1_received; i++) {
 68                         j /= i + j + 1;
 69                         if (!attr)
 70                                 /* trigger the nanosleep tracepoint program. */
 71                                 usleep(1);
 72                 }
 73 
 74                 buf[0] = sigusr1_received ? '2' : '';
 75                 ASSERT_EQ(sigusr1_received, 1, "sigusr1_received");
 76                 ASSERT_EQ(write(pipe_c2p[1], buf, 1), 1, "pipe_write");
 77 
 78                 /* wait for parent notification and exit */
 79                 ASSERT_EQ(read(pipe_p2c[0], buf, 1), 1, "pipe_read");
 80 
 81                 /* restore the old priority */
 82                 ASSERT_OK(setpriority(PRIO_PROCESS, 0, old_prio), "setpriority");
 83 
 84                 close(pipe_c2p[1]);
 85                 close(pipe_p2c[0]);
 86                 exit(0);
 87         }
 88 
 89         close(pipe_c2p[1]); /* close write */
 90         close(pipe_p2c[0]); /* close read */
 91 
 92         skel = test_send_signal_kern__open_and_load();
 93         if (!ASSERT_OK_PTR(skel, "skel_open_and_load"))
 94                 goto skel_open_load_failure;
 95 
 96         if (!attr) {
 97                 err = test_send_signal_kern__attach(skel);
 98                 if (!ASSERT_OK(err, "skel_attach")) {
 99                         err = -1;
100                         goto destroy_skel;
101                 }
102         } else {
103                 pmu_fd = syscall(__NR_perf_event_open, attr, pid, -1 /* cpu */,
104                                  -1 /* group id */, 0 /* flags */);
105                 if (!ASSERT_GE(pmu_fd, 0, "perf_event_open")) {
106                         err = -1;
107                         goto destroy_skel;
108                 }
109 
110                 skel->links.send_signal_perf =
111                         bpf_program__attach_perf_event(skel->progs.send_signal_perf, pmu_fd);
112                 if (!ASSERT_OK_PTR(skel->links.send_signal_perf, "attach_perf_event"))
113                         goto disable_pmu;
114         }
115 
116         /* wait until child signal handler installed */
117         ASSERT_EQ(read(pipe_c2p[0], buf, 1), 1, "pipe_read");
118 
119         /* trigger the bpf send_signal */
120         skel->bss->signal_thread = signal_thread;
121         skel->bss->sig = SIGUSR1;
122         skel->bss->pid = pid;
123 
124         /* notify child that bpf program can send_signal now */
125         ASSERT_EQ(write(pipe_p2c[1], buf, 1), 1, "pipe_write");
126 
127         /* wait for result */
128         err = read(pipe_c2p[0], buf, 1);
129         if (!ASSERT_GE(err, 0, "reading pipe"))
130                 goto disable_pmu;
131         if (!ASSERT_GT(err, 0, "reading pipe error: size 0")) {
132                 err = -1;
133                 goto disable_pmu;
134         }
135 
136         ASSERT_EQ(buf[0], '2', "incorrect result");
137 
138         /* notify child safe to exit */
139         ASSERT_EQ(write(pipe_p2c[1], buf, 1), 1, "pipe_write");
140 
141 disable_pmu:
142         close(pmu_fd);
143 destroy_skel:
144         test_send_signal_kern__destroy(skel);
145 skel_open_load_failure:
146         close(pipe_c2p[0]);
147         close(pipe_p2c[1]);
148         wait(NULL);
149 }
150 
151 static void test_send_signal_tracepoint(bool signal_thread)
152 {
153         test_send_signal_common(NULL, signal_thread);
154 }
155 
156 static void test_send_signal_perf(bool signal_thread)
157 {
158         struct perf_event_attr attr = {
159                 .freq = 1,
160                 .sample_freq = 1000,
161                 .type = PERF_TYPE_SOFTWARE,
162                 .config = PERF_COUNT_SW_CPU_CLOCK,
163         };
164 
165         test_send_signal_common(&attr, signal_thread);
166 }
167 
168 static void test_send_signal_nmi(bool signal_thread)
169 {
170         struct perf_event_attr attr = {
171                 .sample_period = 1,
172                 .type = PERF_TYPE_HARDWARE,
173                 .config = PERF_COUNT_HW_CPU_CYCLES,
174         };
175         int pmu_fd;
176 
177         /* Some setups (e.g. virtual machines) might run with hardware
178          * perf events disabled. If this is the case, skip this test.
179          */
180         pmu_fd = syscall(__NR_perf_event_open, &attr, 0 /* pid */,
181                          -1 /* cpu */, -1 /* group_fd */, 0 /* flags */);
182         if (pmu_fd == -1) {
183                 if (errno == ENOENT || errno == EOPNOTSUPP) {
184                         printf("%s:SKIP:no PERF_COUNT_HW_CPU_CYCLES\n",
185                                __func__);
186                         test__skip();
187                         return;
188                 }
189                 /* Let the test fail with a more informative message */
190         } else {
191                 close(pmu_fd);
192         }
193 
194         test_send_signal_common(&attr, signal_thread);
195 }
196 
197 void test_send_signal(void)
198 {
199         if (test__start_subtest("send_signal_tracepoint"))
200                 test_send_signal_tracepoint(false);
201         if (test__start_subtest("send_signal_perf"))
202                 test_send_signal_perf(false);
203         if (test__start_subtest("send_signal_nmi"))
204                 test_send_signal_nmi(false);
205         if (test__start_subtest("send_signal_tracepoint_thread"))
206                 test_send_signal_tracepoint(true);
207         if (test__start_subtest("send_signal_perf_thread"))
208                 test_send_signal_perf(true);
209         if (test__start_subtest("send_signal_nmi_thread"))
210                 test_send_signal_nmi(true);
211 }
212 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php