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 <sys/ioctl.h> 12 13 #include "event.h" 14 15 16 int perf_event_open(struct perf_event_attr *attr, pid_t pid, int cpu, 17 int group_fd, unsigned long flags) 18 { 19 return syscall(__NR_perf_event_open, attr, pid, cpu, 20 group_fd, flags); 21 } 22 23 void event_init_opts(struct event *e, u64 config, int type, char *name) 24 { 25 memset(e, 0, sizeof(*e)); 26 27 e->name = name; 28 29 e->attr.type = type; 30 e->attr.config = config; 31 e->attr.size = sizeof(e->attr); 32 /* This has to match the structure layout in the header */ 33 e->attr.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | \ 34 PERF_FORMAT_TOTAL_TIME_RUNNING; 35 } 36 37 void event_init_named(struct event *e, u64 config, char *name) 38 { 39 event_init_opts(e, config, PERF_TYPE_RAW, name); 40 } 41 42 void event_init(struct event *e, u64 config) 43 { 44 event_init_opts(e, config, PERF_TYPE_RAW, "event"); 45 } 46 47 #define PERF_CURRENT_PID 0 48 #define PERF_NO_PID -1 49 #define PERF_NO_CPU -1 50 #define PERF_NO_GROUP -1 51 52 int event_open_with_options(struct event *e, pid_t pid, int cpu, int group_fd) 53 { 54 e->fd = perf_event_open(&e->attr, pid, cpu, group_fd, 0); 55 if (e->fd == -1) { 56 perror("perf_event_open"); 57 return -1; 58 } 59 60 return 0; 61 } 62 63 int event_open_with_group(struct event *e, int group_fd) 64 { 65 return event_open_with_options(e, PERF_CURRENT_PID, PERF_NO_CPU, group_fd); 66 } 67 68 int event_open_with_pid(struct event *e, pid_t pid) 69 { 70 return event_open_with_options(e, pid, PERF_NO_CPU, PERF_NO_GROUP); 71 } 72 73 int event_open_with_cpu(struct event *e, int cpu) 74 { 75 return event_open_with_options(e, PERF_NO_PID, cpu, PERF_NO_GROUP); 76 } 77 78 int event_open(struct event *e) 79 { 80 return event_open_with_options(e, PERF_CURRENT_PID, PERF_NO_CPU, PERF_NO_GROUP); 81 } 82 83 void event_close(struct event *e) 84 { 85 close(e->fd); 86 } 87 88 int event_enable(struct event *e) 89 { 90 return ioctl(e->fd, PERF_EVENT_IOC_ENABLE); 91 } 92 93 int event_disable(struct event *e) 94 { 95 return ioctl(e->fd, PERF_EVENT_IOC_DISABLE); 96 } 97 98 int event_reset(struct event *e) 99 { 100 return ioctl(e->fd, PERF_EVENT_IOC_RESET); 101 } 102 103 int event_read(struct event *e) 104 { 105 int rc; 106 107 rc = read(e->fd, &e->result, sizeof(e->result)); 108 if (rc != sizeof(e->result)) { 109 fprintf(stderr, "read error on event %p!\n", e); 110 return -1; 111 } 112 113 return 0; 114 } 115 116 void event_report_justified(struct event *e, int name_width, int result_width) 117 { 118 printf("%*s: result %*llu ", name_width, e->name, result_width, 119 e->result.value); 120 121 if (e->result.running == e->result.enabled) 122 printf("running/enabled %llu\n", e->result.running); 123 else 124 printf("running %llu enabled %llu\n", e->result.running, 125 e->result.enabled); 126 } 127 128 void event_report(struct event *e) 129 { 130 event_report_justified(e, 0, 0); 131 } 132