Home | History | Annotate | Download | only in pmu
      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 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