1 /* 2 * Copyright 2013, Michael Ellerman, IBM Corp. 3 * Licensed under GPLv2. 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 #define PERF_CURRENT_PID 0 43 #define PERF_NO_CPU -1 44 #define PERF_NO_GROUP -1 45 46 int event_open_with_options(struct event *e, pid_t pid, int cpu, int group_fd) 47 { 48 e->fd = perf_event_open(&e->attr, pid, cpu, group_fd, 0); 49 if (e->fd == -1) { 50 perror("perf_event_open"); 51 return -1; 52 } 53 54 return 0; 55 } 56 57 int event_open_with_group(struct event *e, int group_fd) 58 { 59 return event_open_with_options(e, PERF_CURRENT_PID, PERF_NO_CPU, group_fd); 60 } 61 62 int event_open(struct event *e) 63 { 64 return event_open_with_options(e, PERF_CURRENT_PID, PERF_NO_CPU, PERF_NO_GROUP); 65 } 66 67 void event_close(struct event *e) 68 { 69 close(e->fd); 70 } 71 72 int event_reset(struct event *e) 73 { 74 return ioctl(e->fd, PERF_EVENT_IOC_RESET); 75 } 76 77 int event_read(struct event *e) 78 { 79 int rc; 80 81 rc = read(e->fd, &e->result, sizeof(e->result)); 82 if (rc != sizeof(e->result)) { 83 fprintf(stderr, "read error on event %p!\n", e); 84 return -1; 85 } 86 87 return 0; 88 } 89 90 void event_report_justified(struct event *e, int name_width, int result_width) 91 { 92 printf("%*s: result %*llu ", name_width, e->name, result_width, 93 e->result.value); 94 95 if (e->result.running == e->result.enabled) 96 printf("running/enabled %llu\n", e->result.running); 97 else 98 printf("running %llu enabled %llu\n", e->result.running, 99 e->result.enabled); 100 } 101 102 void event_report(struct event *e) 103 { 104 event_report_justified(e, 0, 0); 105 } 106