Created
December 19, 2019 07:13
-
-
Save o-/6d4c05546431dbd3d9c0f9b23a98ee4c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define _GNU_SOURCE 1 | |
#include <asm/unistd.h> | |
#include <fcntl.h> | |
#include <linux/perf_event.h> | |
#include <signal.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
long perf_event_open(struct perf_event_attr* event_attr, pid_t pid, int cpu, int group_fd, unsigned long flags) | |
{ | |
return syscall(__NR_perf_event_open, event_attr, pid, cpu, group_fd, flags); | |
} | |
volatile int fd; | |
volatile char gotPerfEvent = 0; | |
static void perf_event_handler(int signum, siginfo_t* info, void* ucontext) { | |
if(info->si_code != POLL_HUP) { | |
// Only POLL_HUP should happen. | |
exit(EXIT_FAILURE); | |
} | |
gotPerfEvent = 1; | |
ioctl(info->si_fd, PERF_EVENT_IOC_REFRESH, 1); | |
} | |
int main(int argc, char** argv) | |
{ | |
int signo = SIGRTMIN + 1; | |
// Configure signal handler | |
struct sigaction sa; | |
memset(&sa, 0, sizeof(struct sigaction)); | |
sa.sa_sigaction = perf_event_handler; | |
sa.sa_flags = SA_SIGINFO; | |
// Setup signal handler | |
if (sigaction(signo, &sa, NULL) < 0) { | |
fprintf(stderr,"Error setting up signal handler\n"); | |
perror("sigaction"); | |
exit(EXIT_FAILURE); | |
} | |
struct perf_event_attr pe; | |
memset(&pe, 0, sizeof(struct perf_event_attr)); | |
pe.type = PERF_TYPE_HARDWARE; | |
pe.size = sizeof(struct perf_event_attr); | |
pe.config = PERF_COUNT_SW_TASK_CLOCK; | |
pe.disabled = 1; | |
pe.sample_period = 1000; | |
pe.exclude_kernel = 1; | |
pe.exclude_hv = 1; | |
pe.exclude_idle = 1; | |
pid_t pid = 0; // measure the current process/thread | |
int cpu = -1; // measure on any cpu | |
int group_fd = -1; | |
unsigned long flags = 0; | |
fd = perf_event_open(&pe, pid, cpu, group_fd, flags); | |
if (fd == -1) { | |
fprintf(stderr, "Error opening leader %llx\n", pe.config); | |
perror("perf_event_open"); | |
exit(EXIT_FAILURE); | |
} | |
// Setup event handler for overflow signals | |
fcntl(fd, F_SETFL, O_NONBLOCK|O_ASYNC); | |
fcntl(fd, F_SETSIG, signo); | |
fcntl(fd, F_SETOWN, getpid()); | |
ioctl(fd, PERF_EVENT_IOC_RESET, 0); // Reset event counter to 0 | |
ioctl(fd, PERF_EVENT_IOC_REFRESH, 1); | |
// Start monitoring | |
for(int i = 0; i < 1000; i++) { | |
putchar('.'); | |
if (gotPerfEvent) { | |
long long counter; | |
read(fd, &counter, sizeof(long long)); // Read event counter value | |
printf("\nUsed %lld instructions\n", counter); | |
gotPerfEvent = 0; | |
} | |
} | |
// End monitoring | |
ioctl(fd, PERF_EVENT_IOC_DISABLE, 0); // Disable event | |
close(fd); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment