FILE
watermark_signal.c
File preview with syntax highlighting.
linux-6.19.14/tools/testing/selftests/perf_events/watermark_signal.c
1// SPDX-License-Identifier: GPL-2.0 2#define _GNU_SOURCE 3 4#include <errno.h> 5#include <fcntl.h> 6#include <linux/perf_event.h> 7#include <stddef.h> 8#include <sched.h> 9#include <signal.h> 10#include <stdlib.h> 11#include <string.h> 12#include <sys/ioctl.h> 13#include <sys/mman.h> 14#include <sys/syscall.h> 15#include <sys/wait.h> 16#include <unistd.h> 17 18#include "kselftest_harness.h" 19 20static int sigio_count; 21 22static void handle_sigio(int signum __maybe_unused, 23 siginfo_t *oh __maybe_unused, 24 void *uc __maybe_unused) 25{ 26 ++sigio_count; 27} 28 29static void do_child(void) 30{ 31 raise(SIGSTOP); 32 33 for (int i = 0; i < 20; ++i) 34 sleep(1); 35 36 raise(SIGSTOP); 37 38 exit(0); 39} 40 41TEST(watermark_signal) 42{ 43 struct perf_event_attr attr; 44 struct perf_event_mmap_page *p = NULL; 45 struct sigaction previous_sigio, sigio = { 0 }; 46 pid_t child = -1; 47 int child_status; 48 int fd = -1; 49 long page_size = sysconf(_SC_PAGE_SIZE); 50 51 sigio.sa_sigaction = handle_sigio; 52 EXPECT_EQ(sigaction(SIGIO, &sigio, &previous_sigio), 0); 53 54 memset(&attr, 0, sizeof(attr)); 55 attr.size = sizeof(attr); 56 attr.type = PERF_TYPE_SOFTWARE; 57 attr.config = PERF_COUNT_SW_DUMMY; 58 attr.sample_period = 1; 59 attr.disabled = 1; 60 attr.watermark = 1; 61 attr.context_switch = 1; 62 attr.wakeup_watermark = 1; 63 64 child = fork(); 65 EXPECT_GE(child, 0); 66 if (child == 0) 67 do_child(); 68 else if (child < 0) { 69 perror("fork()"); 70 goto cleanup; 71 } 72 73 if (waitpid(child, &child_status, WSTOPPED) != child || 74 !(WIFSTOPPED(child_status) && WSTOPSIG(child_status) == SIGSTOP)) { 75 fprintf(stderr, 76 "failed to synchronize with child errno=%d status=%x\n", 77 errno, 78 child_status); 79 goto cleanup; 80 } 81 82 fd = syscall(__NR_perf_event_open, &attr, child, -1, -1, 83 PERF_FLAG_FD_CLOEXEC); 84 if (fd < 0) { 85 fprintf(stderr, "failed opening event %llx\n", attr.config); 86 goto cleanup; 87 } 88 89 if (fcntl(fd, F_SETFL, FASYNC)) { 90 perror("F_SETFL FASYNC"); 91 goto cleanup; 92 } 93 94 if (fcntl(fd, F_SETOWN, getpid())) { 95 perror("F_SETOWN getpid()"); 96 goto cleanup; 97 } 98 99 if (fcntl(fd, F_SETSIG, SIGIO)) { 100 perror("F_SETSIG SIGIO"); 101 goto cleanup; 102 } 103 104 p = mmap(NULL, 2 * page_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 105 if (p == NULL) { 106 perror("mmap"); 107 goto cleanup; 108 } 109 110 if (ioctl(fd, PERF_EVENT_IOC_ENABLE, 0)) { 111 perror("PERF_EVENT_IOC_ENABLE"); 112 goto cleanup; 113 } 114 115 if (kill(child, SIGCONT) < 0) { 116 perror("SIGCONT"); 117 goto cleanup; 118 } 119 120 if (waitpid(child, &child_status, WSTOPPED) != -1 || errno != EINTR) 121 fprintf(stderr, 122 "expected SIGIO to terminate wait errno=%d status=%x\n%d", 123 errno, 124 child_status, 125 sigio_count); 126 127 EXPECT_GE(sigio_count, 1); 128 129cleanup: 130 if (p != NULL) 131 munmap(p, 2 * page_size); 132 133 if (fd >= 0) 134 close(fd); 135 136 if (child > 0) { 137 kill(child, SIGKILL); 138 waitpid(child, NULL, 0); 139 } 140 141 sigaction(SIGIO, &previous_sigio, NULL); 142} 143 144TEST_HARNESS_MAIN
~/
Read-only file preview.