sigtrap_threads.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Test for perf events with SIGTRAP across all threads.
  4. *
  5. * Copyright (C) 2021, Google LLC.
  6. */
  7. #define _GNU_SOURCE
  8. /* We need the latest siginfo from the kernel repo. */
  9. #include <sys/types.h>
  10. #include <asm/siginfo.h>
  11. #define __have_siginfo_t 1
  12. #define __have_sigval_t 1
  13. #define __have_sigevent_t 1
  14. #define __siginfo_t_defined
  15. #define __sigval_t_defined
  16. #define __sigevent_t_defined
  17. #define _BITS_SIGINFO_CONSTS_H 1
  18. #define _BITS_SIGEVENT_CONSTS_H 1
  19. #include <stdbool.h>
  20. #include <stddef.h>
  21. #include <stdint.h>
  22. #include <stdio.h>
  23. #include <linux/hw_breakpoint.h>
  24. #include <linux/perf_event.h>
  25. #include <pthread.h>
  26. #include <signal.h>
  27. #include <sys/ioctl.h>
  28. #include <sys/syscall.h>
  29. #include <unistd.h>
  30. #include "../kselftest_harness.h"
  31. #define NUM_THREADS 5
  32. /* Data shared between test body, threads, and signal handler. */
  33. static struct {
  34. int tids_want_signal; /* Which threads still want a signal. */
  35. int signal_count; /* Sanity check number of signals received. */
  36. volatile int iterate_on; /* Variable to set breakpoint on. */
  37. siginfo_t first_siginfo; /* First observed siginfo_t. */
  38. } ctx;
  39. /* Unique value to check si_perf_data is correctly set from perf_event_attr::sig_data. */
  40. #define TEST_SIG_DATA(addr, id) (~(unsigned long)(addr) + id)
  41. static struct perf_event_attr make_event_attr(bool enabled, volatile void *addr,
  42. unsigned long id)
  43. {
  44. struct perf_event_attr attr = {
  45. .type = PERF_TYPE_BREAKPOINT,
  46. .size = sizeof(attr),
  47. .sample_period = 1,
  48. .disabled = !enabled,
  49. .bp_addr = (unsigned long)addr,
  50. .bp_type = HW_BREAKPOINT_RW,
  51. .bp_len = HW_BREAKPOINT_LEN_1,
  52. .inherit = 1, /* Children inherit events ... */
  53. .inherit_thread = 1, /* ... but only cloned with CLONE_THREAD. */
  54. .remove_on_exec = 1, /* Required by sigtrap. */
  55. .sigtrap = 1, /* Request synchronous SIGTRAP on event. */
  56. .sig_data = TEST_SIG_DATA(addr, id),
  57. .exclude_kernel = 1, /* To allow */
  58. .exclude_hv = 1, /* running as !root */
  59. };
  60. return attr;
  61. }
  62. static void sigtrap_handler(int signum, siginfo_t *info, void *ucontext)
  63. {
  64. if (info->si_code != TRAP_PERF) {
  65. fprintf(stderr, "%s: unexpected si_code %d\n", __func__, info->si_code);
  66. return;
  67. }
  68. /*
  69. * The data in siginfo_t we're interested in should all be the same
  70. * across threads.
  71. */
  72. if (!__atomic_fetch_add(&ctx.signal_count, 1, __ATOMIC_RELAXED))
  73. ctx.first_siginfo = *info;
  74. __atomic_fetch_sub(&ctx.tids_want_signal, syscall(__NR_gettid), __ATOMIC_RELAXED);
  75. }
  76. static void *test_thread(void *arg)
  77. {
  78. pthread_barrier_t *barrier = (pthread_barrier_t *)arg;
  79. pid_t tid = syscall(__NR_gettid);
  80. int iter;
  81. int i;
  82. pthread_barrier_wait(barrier);
  83. __atomic_fetch_add(&ctx.tids_want_signal, tid, __ATOMIC_RELAXED);
  84. iter = ctx.iterate_on; /* read */
  85. if (iter >= 0) {
  86. for (i = 0; i < iter - 1; i++) {
  87. __atomic_fetch_add(&ctx.tids_want_signal, tid, __ATOMIC_RELAXED);
  88. ctx.iterate_on = iter; /* idempotent write */
  89. }
  90. } else {
  91. while (ctx.iterate_on);
  92. }
  93. return NULL;
  94. }
  95. FIXTURE(sigtrap_threads)
  96. {
  97. struct sigaction oldact;
  98. pthread_t threads[NUM_THREADS];
  99. pthread_barrier_t barrier;
  100. int fd;
  101. };
  102. FIXTURE_SETUP(sigtrap_threads)
  103. {
  104. struct perf_event_attr attr = make_event_attr(false, &ctx.iterate_on, 0);
  105. struct sigaction action = {};
  106. int i;
  107. memset(&ctx, 0, sizeof(ctx));
  108. /* Initialize sigtrap handler. */
  109. action.sa_flags = SA_SIGINFO | SA_NODEFER;
  110. action.sa_sigaction = sigtrap_handler;
  111. sigemptyset(&action.sa_mask);
  112. ASSERT_EQ(sigaction(SIGTRAP, &action, &self->oldact), 0);
  113. /* Initialize perf event. */
  114. self->fd = syscall(__NR_perf_event_open, &attr, 0, -1, -1, PERF_FLAG_FD_CLOEXEC);
  115. ASSERT_NE(self->fd, -1);
  116. /* Spawn threads inheriting perf event. */
  117. pthread_barrier_init(&self->barrier, NULL, NUM_THREADS + 1);
  118. for (i = 0; i < NUM_THREADS; i++)
  119. ASSERT_EQ(pthread_create(&self->threads[i], NULL, test_thread, &self->barrier), 0);
  120. }
  121. FIXTURE_TEARDOWN(sigtrap_threads)
  122. {
  123. pthread_barrier_destroy(&self->barrier);
  124. close(self->fd);
  125. sigaction(SIGTRAP, &self->oldact, NULL);
  126. }
  127. static void run_test_threads(struct __test_metadata *_metadata,
  128. FIXTURE_DATA(sigtrap_threads) *self)
  129. {
  130. int i;
  131. pthread_barrier_wait(&self->barrier);
  132. for (i = 0; i < NUM_THREADS; i++)
  133. ASSERT_EQ(pthread_join(self->threads[i], NULL), 0);
  134. }
  135. TEST_F(sigtrap_threads, remain_disabled)
  136. {
  137. run_test_threads(_metadata, self);
  138. EXPECT_EQ(ctx.signal_count, 0);
  139. EXPECT_NE(ctx.tids_want_signal, 0);
  140. }
  141. TEST_F(sigtrap_threads, enable_event)
  142. {
  143. EXPECT_EQ(ioctl(self->fd, PERF_EVENT_IOC_ENABLE, 0), 0);
  144. run_test_threads(_metadata, self);
  145. EXPECT_EQ(ctx.signal_count, NUM_THREADS);
  146. EXPECT_EQ(ctx.tids_want_signal, 0);
  147. EXPECT_EQ(ctx.first_siginfo.si_addr, &ctx.iterate_on);
  148. EXPECT_EQ(ctx.first_siginfo.si_perf_type, PERF_TYPE_BREAKPOINT);
  149. EXPECT_EQ(ctx.first_siginfo.si_perf_data, TEST_SIG_DATA(&ctx.iterate_on, 0));
  150. /* Check enabled for parent. */
  151. ctx.iterate_on = 0;
  152. EXPECT_EQ(ctx.signal_count, NUM_THREADS + 1);
  153. }
  154. /* Test that modification propagates to all inherited events. */
  155. TEST_F(sigtrap_threads, modify_and_enable_event)
  156. {
  157. struct perf_event_attr new_attr = make_event_attr(true, &ctx.iterate_on, 42);
  158. EXPECT_EQ(ioctl(self->fd, PERF_EVENT_IOC_MODIFY_ATTRIBUTES, &new_attr), 0);
  159. run_test_threads(_metadata, self);
  160. EXPECT_EQ(ctx.signal_count, NUM_THREADS);
  161. EXPECT_EQ(ctx.tids_want_signal, 0);
  162. EXPECT_EQ(ctx.first_siginfo.si_addr, &ctx.iterate_on);
  163. EXPECT_EQ(ctx.first_siginfo.si_perf_type, PERF_TYPE_BREAKPOINT);
  164. EXPECT_EQ(ctx.first_siginfo.si_perf_data, TEST_SIG_DATA(&ctx.iterate_on, 42));
  165. /* Check enabled for parent. */
  166. ctx.iterate_on = 0;
  167. EXPECT_EQ(ctx.signal_count, NUM_THREADS + 1);
  168. }
  169. /* Stress test event + signal handling. */
  170. TEST_F(sigtrap_threads, signal_stress)
  171. {
  172. ctx.iterate_on = 3000;
  173. EXPECT_EQ(ioctl(self->fd, PERF_EVENT_IOC_ENABLE, 0), 0);
  174. run_test_threads(_metadata, self);
  175. EXPECT_EQ(ioctl(self->fd, PERF_EVENT_IOC_DISABLE, 0), 0);
  176. EXPECT_EQ(ctx.signal_count, NUM_THREADS * ctx.iterate_on);
  177. EXPECT_EQ(ctx.tids_want_signal, 0);
  178. EXPECT_EQ(ctx.first_siginfo.si_addr, &ctx.iterate_on);
  179. EXPECT_EQ(ctx.first_siginfo.si_perf_type, PERF_TYPE_BREAKPOINT);
  180. EXPECT_EQ(ctx.first_siginfo.si_perf_data, TEST_SIG_DATA(&ctx.iterate_on, 0));
  181. }
  182. TEST_F(sigtrap_threads, signal_stress_with_disable)
  183. {
  184. const int target_count = NUM_THREADS * 3000;
  185. int i;
  186. ctx.iterate_on = -1;
  187. EXPECT_EQ(ioctl(self->fd, PERF_EVENT_IOC_ENABLE, 0), 0);
  188. pthread_barrier_wait(&self->barrier);
  189. while (__atomic_load_n(&ctx.signal_count, __ATOMIC_RELAXED) < target_count) {
  190. EXPECT_EQ(ioctl(self->fd, PERF_EVENT_IOC_DISABLE, 0), 0);
  191. EXPECT_EQ(ioctl(self->fd, PERF_EVENT_IOC_ENABLE, 0), 0);
  192. }
  193. ctx.iterate_on = 0;
  194. for (i = 0; i < NUM_THREADS; i++)
  195. ASSERT_EQ(pthread_join(self->threads[i], NULL), 0);
  196. EXPECT_EQ(ioctl(self->fd, PERF_EVENT_IOC_DISABLE, 0), 0);
  197. EXPECT_EQ(ctx.first_siginfo.si_addr, &ctx.iterate_on);
  198. EXPECT_EQ(ctx.first_siginfo.si_perf_type, PERF_TYPE_BREAKPOINT);
  199. EXPECT_EQ(ctx.first_siginfo.si_perf_data, TEST_SIG_DATA(&ctx.iterate_on, 0));
  200. }
  201. TEST_HARNESS_MAIN