0001
0002
0003
0004
0005
0006
0007
0008 #define _GNU_SOURCE
0009
0010
0011 #include <sys/types.h>
0012 #include <asm/siginfo.h>
0013 #define __have_siginfo_t 1
0014 #define __have_sigval_t 1
0015 #define __have_sigevent_t 1
0016 #define __siginfo_t_defined
0017 #define __sigval_t_defined
0018 #define __sigevent_t_defined
0019 #define _BITS_SIGINFO_CONSTS_H 1
0020 #define _BITS_SIGEVENT_CONSTS_H 1
0021
0022 #include <stdbool.h>
0023 #include <stddef.h>
0024 #include <stdint.h>
0025 #include <stdio.h>
0026 #include <linux/hw_breakpoint.h>
0027 #include <linux/perf_event.h>
0028 #include <pthread.h>
0029 #include <signal.h>
0030 #include <sys/ioctl.h>
0031 #include <sys/syscall.h>
0032 #include <unistd.h>
0033
0034 #include "../kselftest_harness.h"
0035
0036 #define NUM_THREADS 5
0037
0038
0039 static struct {
0040 int tids_want_signal;
0041 int signal_count;
0042 volatile int iterate_on;
0043 siginfo_t first_siginfo;
0044 } ctx;
0045
0046
0047 #define TEST_SIG_DATA(addr, id) (~(unsigned long)(addr) + id)
0048
0049 static struct perf_event_attr make_event_attr(bool enabled, volatile void *addr,
0050 unsigned long id)
0051 {
0052 struct perf_event_attr attr = {
0053 .type = PERF_TYPE_BREAKPOINT,
0054 .size = sizeof(attr),
0055 .sample_period = 1,
0056 .disabled = !enabled,
0057 .bp_addr = (unsigned long)addr,
0058 .bp_type = HW_BREAKPOINT_RW,
0059 .bp_len = HW_BREAKPOINT_LEN_1,
0060 .inherit = 1,
0061 .inherit_thread = 1,
0062 .remove_on_exec = 1,
0063 .sigtrap = 1,
0064 .sig_data = TEST_SIG_DATA(addr, id),
0065 };
0066 return attr;
0067 }
0068
0069 static void sigtrap_handler(int signum, siginfo_t *info, void *ucontext)
0070 {
0071 if (info->si_code != TRAP_PERF) {
0072 fprintf(stderr, "%s: unexpected si_code %d\n", __func__, info->si_code);
0073 return;
0074 }
0075
0076
0077
0078
0079
0080 if (!__atomic_fetch_add(&ctx.signal_count, 1, __ATOMIC_RELAXED))
0081 ctx.first_siginfo = *info;
0082 __atomic_fetch_sub(&ctx.tids_want_signal, syscall(__NR_gettid), __ATOMIC_RELAXED);
0083 }
0084
0085 static void *test_thread(void *arg)
0086 {
0087 pthread_barrier_t *barrier = (pthread_barrier_t *)arg;
0088 pid_t tid = syscall(__NR_gettid);
0089 int iter;
0090 int i;
0091
0092 pthread_barrier_wait(barrier);
0093
0094 __atomic_fetch_add(&ctx.tids_want_signal, tid, __ATOMIC_RELAXED);
0095 iter = ctx.iterate_on;
0096 for (i = 0; i < iter - 1; i++) {
0097 __atomic_fetch_add(&ctx.tids_want_signal, tid, __ATOMIC_RELAXED);
0098 ctx.iterate_on = iter;
0099 }
0100
0101 return NULL;
0102 }
0103
0104 FIXTURE(sigtrap_threads)
0105 {
0106 struct sigaction oldact;
0107 pthread_t threads[NUM_THREADS];
0108 pthread_barrier_t barrier;
0109 int fd;
0110 };
0111
0112 FIXTURE_SETUP(sigtrap_threads)
0113 {
0114 struct perf_event_attr attr = make_event_attr(false, &ctx.iterate_on, 0);
0115 struct sigaction action = {};
0116 int i;
0117
0118 memset(&ctx, 0, sizeof(ctx));
0119
0120
0121 action.sa_flags = SA_SIGINFO | SA_NODEFER;
0122 action.sa_sigaction = sigtrap_handler;
0123 sigemptyset(&action.sa_mask);
0124 ASSERT_EQ(sigaction(SIGTRAP, &action, &self->oldact), 0);
0125
0126
0127 self->fd = syscall(__NR_perf_event_open, &attr, 0, -1, -1, PERF_FLAG_FD_CLOEXEC);
0128 ASSERT_NE(self->fd, -1);
0129
0130
0131 pthread_barrier_init(&self->barrier, NULL, NUM_THREADS + 1);
0132 for (i = 0; i < NUM_THREADS; i++)
0133 ASSERT_EQ(pthread_create(&self->threads[i], NULL, test_thread, &self->barrier), 0);
0134 }
0135
0136 FIXTURE_TEARDOWN(sigtrap_threads)
0137 {
0138 pthread_barrier_destroy(&self->barrier);
0139 close(self->fd);
0140 sigaction(SIGTRAP, &self->oldact, NULL);
0141 }
0142
0143 static void run_test_threads(struct __test_metadata *_metadata,
0144 FIXTURE_DATA(sigtrap_threads) *self)
0145 {
0146 int i;
0147
0148 pthread_barrier_wait(&self->barrier);
0149 for (i = 0; i < NUM_THREADS; i++)
0150 ASSERT_EQ(pthread_join(self->threads[i], NULL), 0);
0151 }
0152
0153 TEST_F(sigtrap_threads, remain_disabled)
0154 {
0155 run_test_threads(_metadata, self);
0156 EXPECT_EQ(ctx.signal_count, 0);
0157 EXPECT_NE(ctx.tids_want_signal, 0);
0158 }
0159
0160 TEST_F(sigtrap_threads, enable_event)
0161 {
0162 EXPECT_EQ(ioctl(self->fd, PERF_EVENT_IOC_ENABLE, 0), 0);
0163 run_test_threads(_metadata, self);
0164
0165 EXPECT_EQ(ctx.signal_count, NUM_THREADS);
0166 EXPECT_EQ(ctx.tids_want_signal, 0);
0167 EXPECT_EQ(ctx.first_siginfo.si_addr, &ctx.iterate_on);
0168 EXPECT_EQ(ctx.first_siginfo.si_perf_type, PERF_TYPE_BREAKPOINT);
0169 EXPECT_EQ(ctx.first_siginfo.si_perf_data, TEST_SIG_DATA(&ctx.iterate_on, 0));
0170
0171
0172 ctx.iterate_on = 0;
0173 EXPECT_EQ(ctx.signal_count, NUM_THREADS + 1);
0174 }
0175
0176
0177 TEST_F(sigtrap_threads, modify_and_enable_event)
0178 {
0179 struct perf_event_attr new_attr = make_event_attr(true, &ctx.iterate_on, 42);
0180
0181 EXPECT_EQ(ioctl(self->fd, PERF_EVENT_IOC_MODIFY_ATTRIBUTES, &new_attr), 0);
0182 run_test_threads(_metadata, self);
0183
0184 EXPECT_EQ(ctx.signal_count, NUM_THREADS);
0185 EXPECT_EQ(ctx.tids_want_signal, 0);
0186 EXPECT_EQ(ctx.first_siginfo.si_addr, &ctx.iterate_on);
0187 EXPECT_EQ(ctx.first_siginfo.si_perf_type, PERF_TYPE_BREAKPOINT);
0188 EXPECT_EQ(ctx.first_siginfo.si_perf_data, TEST_SIG_DATA(&ctx.iterate_on, 42));
0189
0190
0191 ctx.iterate_on = 0;
0192 EXPECT_EQ(ctx.signal_count, NUM_THREADS + 1);
0193 }
0194
0195
0196 TEST_F(sigtrap_threads, signal_stress)
0197 {
0198 ctx.iterate_on = 3000;
0199
0200 EXPECT_EQ(ioctl(self->fd, PERF_EVENT_IOC_ENABLE, 0), 0);
0201 run_test_threads(_metadata, self);
0202 EXPECT_EQ(ioctl(self->fd, PERF_EVENT_IOC_DISABLE, 0), 0);
0203
0204 EXPECT_EQ(ctx.signal_count, NUM_THREADS * ctx.iterate_on);
0205 EXPECT_EQ(ctx.tids_want_signal, 0);
0206 EXPECT_EQ(ctx.first_siginfo.si_addr, &ctx.iterate_on);
0207 EXPECT_EQ(ctx.first_siginfo.si_perf_type, PERF_TYPE_BREAKPOINT);
0208 EXPECT_EQ(ctx.first_siginfo.si_perf_data, TEST_SIG_DATA(&ctx.iterate_on, 0));
0209 }
0210
0211 TEST_HARNESS_MAIN