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 16int 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 23void 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 37void event_init_named(struct event *e, u64 config, char *name) 38{ 39 event_init_opts(e, config, PERF_TYPE_RAW, name); 40} 41 42void 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 52int 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 63int 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 68int 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 73int 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 78int event_open(struct event *e) 79{ 80 return event_open_with_options(e, PERF_CURRENT_PID, PERF_NO_CPU, PERF_NO_GROUP); 81} 82 83void event_close(struct event *e) 84{ 85 close(e->fd); 86} 87 88int event_enable(struct event *e) 89{ 90 return ioctl(e->fd, PERF_EVENT_IOC_ENABLE); 91} 92 93int event_disable(struct event *e) 94{ 95 return ioctl(e->fd, PERF_EVENT_IOC_DISABLE); 96} 97 98int event_reset(struct event *e) 99{ 100 return ioctl(e->fd, PERF_EVENT_IOC_RESET); 101} 102 103int 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 116void 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 128void event_report(struct event *e) 129{ 130 event_report_justified(e, 0, 0); 131} 132