Skip to content

Instantly share code, notes, and snippets.

@rocallahan
Created December 15, 2023 04:52
Show Gist options
  • Save rocallahan/a046f28800383fbe2e2904aa8507fcfa to your computer and use it in GitHub Desktop.
Save rocallahan/a046f28800383fbe2e2904aa8507fcfa to your computer and use it in GitHub Desktop.
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <linux/perf_event.h>
#include <sys/syscall.h>
#include <poll.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <signal.h>
static void do_child() {
for (int i = 0; i < 20; ++i) {
sleep(1);
}
exit(0);
}
static void handle_signal(__attribute__((unused)) int sig) {
write(STDERR_FILENO, "SIGIO\n", 6);
}
/* Undefined this to use poll instead, which works */
#define USE_SIGNALS 1
int main() {
pid_t child = fork();
if (!child) {
do_child();
}
signal(SIGIO, handle_signal);
struct perf_event_attr attr;
memset(&attr, 0, sizeof(attr));
attr.size = sizeof(attr);
attr.type = PERF_TYPE_SOFTWARE;
attr.config = PERF_COUNT_SW_DUMMY;
attr.sample_period = 1;
attr.disabled = 1;
attr.watermark = 1;
attr.context_switch = 1;
attr.wakeup_watermark = 100;
int fd = syscall(SYS_perf_event_open, &attr, child, -1, -1, 0);
fcntl(fd, F_SETFL, FASYNC);
fcntl(fd, F_SETOWN, getpid());
fcntl(fd, F_SETSIG, SIGIO);
struct perf_event_mmap_page* p = (struct perf_event_mmap_page*)
mmap(NULL, 8192, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
ioctl(fd, PERF_EVENT_IOC_ENABLE, 0);
#ifdef USE_SIGNALS
sleep(1000);
#else
char buf[20][8192];
for (int i = 0; i < 20; ++i) {
struct pollfd pfd = { fd, POLLIN, 0 };
poll(&pfd, 1, 1000000000);
printf("Polled %d\n", i);
memcpy(buf[i], p, sizeof(buf[i]));
}
#endif
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment