int *fd_group_init(int num_events, char **events) { struct perf_event_attr *attr; int fd, ret, leader_fd, i; int *fds = malloc(num_events * sizeof(int)); if (!fds) err(1, "could not allocate memory"); attr = calloc(num_events, sizeof(*attr)); // do refs, then misses for (i = 0; i < num_events; i++) { /* * 1st argument: event string * 2nd argument: default privilege level (used if not specified in the event string) * 3rd argument: the perf_event_attr to initialize */ ret = pfm_get_perf_event_encoding(events[i], PFM_PLM3, &attr[i], NULL, NULL); if (ret != PFM_SUCCESS) errx(1, "evt %d: cannot find encoding: %s", i, pfm_strerror(ret)); printf("Using encoding %lx for event %s\n", attr[i].config, events[i]); attr[i].inherit = 0; // inheritance currently doesn't work with FORMAT_GROUP /* * request timing information because event may be multiplexed * and thus it may not count all the time. The scaling information * will be used to scale the raw count as if the event had run all * along */ attr[i].read_format = PERF_FORMAT_TOTAL_TIME_ENABLED|PERF_FORMAT_TOTAL_TIME_RUNNING | PERF_FORMAT_GROUP; /* do not start immediately after perf_event_open() */ attr[i].disabled = 1; /* * create the event and attach to self * Note that it attaches only to the main thread, there is no inheritance * to threads that may be created subsequently. * * if mulithreaded, then getpid() must be replaced by gettid() */ if (i == 0) { fd = perf_event_open(&attr[i], 0, -1, -1, 0); fds[i] = fd; leader_fd = fd; } else { fd = perf_event_open(&attr[i], 0, -1, leader_fd, 0); fds[i] = fd; } if (fd < 0) { warn("warning: evt %d: cannot create event", i); free(attr); free(fds); return NULL; } } free(attr); return fds; }
EXTERNAL void sysPerfEventCreate(int id, const char *eventName) { TRACE_PRINTF("%s: sysPerfEventCreate\n", Me); struct perf_event_attr *pe = (perf_event_attrs + id); int ret = pfm_get_perf_event_encoding(eventName, PFM_PLM3, pe, NULL, NULL); if (ret != PFM_SUCCESS) { errx(1, "error creating event %d '%s': %s\n", id, eventName, pfm_strerror(ret)); } pe->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_TOTAL_TIME_RUNNING; pe->disabled = 1; pe->inherit = 1; perf_event_fds[id] = perf_event_open(pe, 0, -1, -1, 0); if (perf_event_fds[id] == -1) { err(1, "error in perf_event_open for event %d '%s'", id, eventName); } }
bool pfm_instance::event_encoding(const std::string& event, unsigned int& type, unsigned long long& config) { int ret; struct perf_event_attr attr; memset(&attr, 0, sizeof(attr)); ret = pfm_get_perf_event_encoding(event.c_str(), PFM_PLM3, &attr, NULL, NULL); if (ret != PFM_SUCCESS) { type = 0; config = 0; return false; } type = attr.type; config = attr.config; return true; }
int main(int argc, char **argv) { struct perf_event_attr attr; int fd, ret; uint64_t count = 0, values[3]; setlocale(LC_ALL, ""); /* * Initialize libpfm library (required before we can use it) */ ret = pfm_initialize(); if (ret != PFM_SUCCESS) errx(1, "cannot initialize library: %s", pfm_strerror(ret)); memset(&attr, 0, sizeof(attr)); /* * 1st argument: event string * 2nd argument: default privilege level (used if not specified in the event string) * 3rd argument: the perf_event_attr to initialize */ ret = pfm_get_perf_event_encoding("cycles", PFM_PLM0|PFM_PLM3, &attr, NULL, NULL); if (ret != PFM_SUCCESS) errx(1, "cannot find encoding: %s", pfm_strerror(ret)); /* * request timing information because event may be multiplexed * and thus it may not count all the time. The scaling information * will be used to scale the raw count as if the event had run all * along */ attr.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED|PERF_FORMAT_TOTAL_TIME_RUNNING; /* do not start immediately after perf_event_open() */ attr.disabled = 1; /* * create the event and attach to self * Note that it attaches only to the main thread, there is no inheritance * to threads that may be created subsequently. * * if mulithreaded, then getpid() must be replaced by gettid() */ fd = perf_event_open(&attr, getpid(), -1, -1, 0); if (fd < 0) err(1, "cannot create event"); /* * start counting now */ ret = ioctl(fd, PERF_EVENT_IOC_ENABLE, 0); if (ret) err(1, "ioctl(enable) failed"); printf("Fibonacci(%d)=%lu\n", N, fib(N)); /* * stop counting */ ret = ioctl(fd, PERF_EVENT_IOC_DISABLE, 0); if (ret) err(1, "ioctl(disable) failed"); /* * read the count + scaling values * * It is not necessary to stop an event to read its value */ ret = read(fd, values, sizeof(values)); if (ret != sizeof(values)) err(1, "cannot read results: %s", strerror(errno)); /* * scale count * * values[0] = raw count * values[1] = TIME_ENABLED * values[2] = TIME_RUNNING */ if (values[2]) count = (uint64_t)((double)values[0] * values[1]/values[2]); printf("count=%'"PRIu64"\n", count); close(fd); /* free libpfm resources cleanly */ pfm_terminate(); return 0; }