brintos

brintos / linux-shallow public Read only

0
0
Text · 2.8 KiB · 49dc1e8 Raw
147 lines · c
1// SPDX-License-Identifier: GPL-2.02#define _GNU_SOURCE3 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 20#define __maybe_unused __attribute__((__unused__))21 22static int sigio_count;23 24static void handle_sigio(int signum __maybe_unused,25			 siginfo_t *oh __maybe_unused,26			 void *uc __maybe_unused)27{28	++sigio_count;29}30 31static void do_child(void)32{33	raise(SIGSTOP);34 35	for (int i = 0; i < 20; ++i)36		sleep(1);37 38	raise(SIGSTOP);39 40	exit(0);41}42 43TEST(watermark_signal)44{45	struct perf_event_attr attr;46	struct perf_event_mmap_page *p = NULL;47	struct sigaction previous_sigio, sigio = { 0 };48	pid_t child = -1;49	int child_status;50	int fd = -1;51	long page_size = sysconf(_SC_PAGE_SIZE);52 53	sigio.sa_sigaction = handle_sigio;54	EXPECT_EQ(sigaction(SIGIO, &sigio, &previous_sigio), 0);55 56	memset(&attr, 0, sizeof(attr));57	attr.size = sizeof(attr);58	attr.type = PERF_TYPE_SOFTWARE;59	attr.config = PERF_COUNT_SW_DUMMY;60	attr.sample_period = 1;61	attr.disabled = 1;62	attr.watermark = 1;63	attr.context_switch = 1;64	attr.wakeup_watermark = 1;65 66	child = fork();67	EXPECT_GE(child, 0);68	if (child == 0)69		do_child();70	else if (child < 0) {71		perror("fork()");72		goto cleanup;73	}74 75	if (waitpid(child, &child_status, WSTOPPED) != child ||76	    !(WIFSTOPPED(child_status) && WSTOPSIG(child_status) == SIGSTOP)) {77		fprintf(stderr,78			"failed to sycnhronize with child errno=%d status=%x\n",79			errno,80			child_status);81		goto cleanup;82	}83 84	fd = syscall(__NR_perf_event_open, &attr, child, -1, -1,85		     PERF_FLAG_FD_CLOEXEC);86	if (fd < 0) {87		fprintf(stderr, "failed opening event %llx\n", attr.config);88		goto cleanup;89	}90 91	if (fcntl(fd, F_SETFL, FASYNC)) {92		perror("F_SETFL FASYNC");93		goto cleanup;94	}95 96	if (fcntl(fd, F_SETOWN, getpid())) {97		perror("F_SETOWN getpid()");98		goto cleanup;99	}100 101	if (fcntl(fd, F_SETSIG, SIGIO)) {102		perror("F_SETSIG SIGIO");103		goto cleanup;104	}105 106	p = mmap(NULL, 2 * page_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);107	if (p == NULL) {108		perror("mmap");109		goto cleanup;110	}111 112	if (ioctl(fd, PERF_EVENT_IOC_ENABLE, 0)) {113		perror("PERF_EVENT_IOC_ENABLE");114		goto cleanup;115	}116 117	if (kill(child, SIGCONT) < 0) {118		perror("SIGCONT");119		goto cleanup;120	}121 122	if (waitpid(child, &child_status, WSTOPPED) != -1 || errno != EINTR)123		fprintf(stderr,124			"expected SIGIO to terminate wait errno=%d status=%x\n%d",125			errno,126			child_status,127			sigio_count);128 129	EXPECT_GE(sigio_count, 1);130 131cleanup:132	if (p != NULL)133		munmap(p, 2 * page_size);134 135	if (fd >= 0)136		close(fd);137 138	if (child > 0) {139		kill(child, SIGKILL);140		waitpid(child, NULL, 0);141	}142 143	sigaction(SIGIO, &previous_sigio, NULL);144}145 146TEST_HARNESS_MAIN147