summaryrefslogtreecommitdiffstats
path: root/llvm/include/pmu/pmu-utils.h
blob: 5e3e014b21e098b8e88f4f36cd502cdfa8a28882 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
/*
 *  (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
 */
OpenPOWER on IntegriCloud