/* * (C) 2018 by Computer System Laboratory, IIS, Academia Sinica, Taiwan. * See COPYRIGHT in top-level directory. */ #ifndef __PMU_UTILS_H #define __PMU_UTILS_H #include <unistd.h> #include <string.h> #include <pthread.h> #include <sys/types.h> #include <sys/ioctl.h> #include <sys/syscall.h> #include "perf_event.h" #ifndef ACCESS_ONCE #define ACCESS_ONCE(x) (*(volatile decltype(x) *)&(x)) #endif namespace pmu { static inline int sys_perf_event_open(struct perf_event_attr *attr, pid_t pid, int cpu, int group_fd, unsigned long flags) { return syscall(__NR_perf_event_open, attr, pid, cpu, group_fd, flags); } static inline void perf_attr_init(struct perf_event_attr *attr, int type, int config) { memset(attr, 0, sizeof(struct perf_event_attr)); attr->type = type; attr->config = config; attr->size = sizeof(struct perf_event_attr); attr->disabled = 1; attr->exclude_kernel = 1; attr->exclude_guest = 1; attr->exclude_hv = 1; } static inline int perf_event_start(int fd) { return ioctl(fd, PERF_EVENT_IOC_ENABLE, 0); } static inline int perf_event_stop(int fd) { return ioctl(fd, PERF_EVENT_IOC_DISABLE, 0); } static inline int perf_event_reset(int fd) { return ioctl(fd, PERF_EVENT_IOC_RESET, 0); } static inline int perf_event_set_filter(int fd, const char *arg) { return ioctl(fd, PERF_EVENT_IOC_SET_FILTER, (void *)arg); } static inline uint64_t perf_read_data_head(void *header) { struct perf_event_mmap_page *pc = (struct perf_event_mmap_page *)header; uint64_t head = ACCESS_ONCE(pc->data_head); pmu_rmb(); return head; } static inline void perf_write_data_tail(void *header, uint64_t val) { struct perf_event_mmap_page *pc = (struct perf_event_mmap_page *)header; pmu_mb(); pc->data_tail = val; } static inline uint64_t perf_read_aux_head(void *header) { struct perf_event_mmap_page *pc = (struct perf_event_mmap_page *)header; uint64_t head = ACCESS_ONCE(pc->aux_head); pmu_rmb(); return head; } static inline void perf_write_aux_tail(void *header, uint64_t val) { struct perf_event_mmap_page *pc = (struct perf_event_mmap_page *)header; pmu_mb(); pc->aux_tail = val; } static inline int isPowerOf2(uint64_t value) { if (!value) return 0; return !(value & (value - 1)); } /* Convert system errno to PMU error code. */ static inline int ErrorCode(int err) { switch (err) { case EPERM: case EACCES: return PMU_EPERM; case ENOMEM: return PMU_ENOMEM; default: return PMU_EEVENT; } } } /* namespace pmu */ #endif /* __PMU_UTILS_H */ /* * vim: ts=8 sts=4 sw=4 expandtab */