event.c (3223B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright 2013, Michael Ellerman, IBM Corp. 4 */ 5 6#define _GNU_SOURCE 7#include <unistd.h> 8#include <sys/syscall.h> 9#include <string.h> 10#include <stdio.h> 11#include <stdbool.h> 12#include <sys/ioctl.h> 13 14#include "event.h" 15 16 17int perf_event_open(struct perf_event_attr *attr, pid_t pid, int cpu, 18 int group_fd, unsigned long flags) 19{ 20 return syscall(__NR_perf_event_open, attr, pid, cpu, 21 group_fd, flags); 22} 23 24static void __event_init_opts(struct event *e, u64 config, 25 int type, char *name, bool sampling) 26{ 27 memset(e, 0, sizeof(*e)); 28 29 e->name = name; 30 31 e->attr.type = type; 32 e->attr.config = config; 33 e->attr.size = sizeof(e->attr); 34 /* This has to match the structure layout in the header */ 35 e->attr.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | \ 36 PERF_FORMAT_TOTAL_TIME_RUNNING; 37 if (sampling) { 38 e->attr.sample_period = 1000; 39 e->attr.sample_type = PERF_SAMPLE_REGS_INTR; 40 e->attr.disabled = 1; 41 } 42} 43 44void event_init_opts(struct event *e, u64 config, int type, char *name) 45{ 46 __event_init_opts(e, config, type, name, false); 47} 48 49void event_init_named(struct event *e, u64 config, char *name) 50{ 51 event_init_opts(e, config, PERF_TYPE_RAW, name); 52} 53 54void event_init(struct event *e, u64 config) 55{ 56 event_init_opts(e, config, PERF_TYPE_RAW, "event"); 57} 58 59void event_init_sampling(struct event *e, u64 config) 60{ 61 __event_init_opts(e, config, PERF_TYPE_RAW, "event", true); 62} 63 64#define PERF_CURRENT_PID 0 65#define PERF_NO_PID -1 66#define PERF_NO_CPU -1 67#define PERF_NO_GROUP -1 68 69int event_open_with_options(struct event *e, pid_t pid, int cpu, int group_fd) 70{ 71 e->fd = perf_event_open(&e->attr, pid, cpu, group_fd, 0); 72 if (e->fd == -1) { 73 perror("perf_event_open"); 74 return -1; 75 } 76 77 return 0; 78} 79 80int event_open_with_group(struct event *e, int group_fd) 81{ 82 return event_open_with_options(e, PERF_CURRENT_PID, PERF_NO_CPU, group_fd); 83} 84 85int event_open_with_pid(struct event *e, pid_t pid) 86{ 87 return event_open_with_options(e, pid, PERF_NO_CPU, PERF_NO_GROUP); 88} 89 90int event_open_with_cpu(struct event *e, int cpu) 91{ 92 return event_open_with_options(e, PERF_NO_PID, cpu, PERF_NO_GROUP); 93} 94 95int event_open(struct event *e) 96{ 97 return event_open_with_options(e, PERF_CURRENT_PID, PERF_NO_CPU, PERF_NO_GROUP); 98} 99 100void event_close(struct event *e) 101{ 102 close(e->fd); 103} 104 105int event_enable(struct event *e) 106{ 107 return ioctl(e->fd, PERF_EVENT_IOC_ENABLE); 108} 109 110int event_disable(struct event *e) 111{ 112 return ioctl(e->fd, PERF_EVENT_IOC_DISABLE); 113} 114 115int event_reset(struct event *e) 116{ 117 return ioctl(e->fd, PERF_EVENT_IOC_RESET); 118} 119 120int event_read(struct event *e) 121{ 122 int rc; 123 124 rc = read(e->fd, &e->result, sizeof(e->result)); 125 if (rc != sizeof(e->result)) { 126 fprintf(stderr, "read error on event %p!\n", e); 127 return -1; 128 } 129 130 return 0; 131} 132 133void event_report_justified(struct event *e, int name_width, int result_width) 134{ 135 printf("%*s: result %*llu ", name_width, e->name, result_width, 136 e->result.value); 137 138 if (e->result.running == e->result.enabled) 139 printf("running/enabled %llu\n", e->result.running); 140 else 141 printf("running %llu enabled %llu\n", e->result.running, 142 e->result.enabled); 143} 144 145void event_report(struct event *e) 146{ 147 event_report_justified(e, 0, 0); 148}