File Index
Files and directories
Sign in
FILE

watermark_signal.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/perf_events/watermark_signal.c 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.