root/tools/perf/lib/evsel.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. perf_evsel__init
  2. perf_evsel__new
  3. perf_evsel__delete
  4. perf_evsel__alloc_fd
  5. sys_perf_event_open
  6. perf_evsel__open
  7. perf_evsel__close_fd
  8. perf_evsel__free_fd
  9. perf_evsel__close
  10. perf_evsel__read_size
  11. perf_evsel__read
  12. perf_evsel__run_ioctl
  13. perf_evsel__enable
  14. perf_evsel__disable
  15. perf_evsel__apply_filter
  16. perf_evsel__cpus
  17. perf_evsel__threads
  18. perf_evsel__attr
  19. perf_evsel__alloc_id
  20. perf_evsel__free_id

   1 // SPDX-License-Identifier: GPL-2.0
   2 #include <errno.h>
   3 #include <unistd.h>
   4 #include <sys/syscall.h>
   5 #include <perf/evsel.h>
   6 #include <perf/cpumap.h>
   7 #include <perf/threadmap.h>
   8 #include <linux/list.h>
   9 #include <internal/evsel.h>
  10 #include <linux/zalloc.h>
  11 #include <stdlib.h>
  12 #include <internal/xyarray.h>
  13 #include <internal/cpumap.h>
  14 #include <internal/threadmap.h>
  15 #include <internal/lib.h>
  16 #include <linux/string.h>
  17 #include <sys/ioctl.h>
  18 
  19 void perf_evsel__init(struct perf_evsel *evsel, struct perf_event_attr *attr)
  20 {
  21         INIT_LIST_HEAD(&evsel->node);
  22         evsel->attr = *attr;
  23 }
  24 
  25 struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr)
  26 {
  27         struct perf_evsel *evsel = zalloc(sizeof(*evsel));
  28 
  29         if (evsel != NULL)
  30                 perf_evsel__init(evsel, attr);
  31 
  32         return evsel;
  33 }
  34 
  35 void perf_evsel__delete(struct perf_evsel *evsel)
  36 {
  37         free(evsel);
  38 }
  39 
  40 #define FD(e, x, y) (*(int *) xyarray__entry(e->fd, x, y))
  41 
  42 int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
  43 {
  44         evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int));
  45 
  46         if (evsel->fd) {
  47                 int cpu, thread;
  48                 for (cpu = 0; cpu < ncpus; cpu++) {
  49                         for (thread = 0; thread < nthreads; thread++) {
  50                                 FD(evsel, cpu, thread) = -1;
  51                         }
  52                 }
  53         }
  54 
  55         return evsel->fd != NULL ? 0 : -ENOMEM;
  56 }
  57 
  58 static int
  59 sys_perf_event_open(struct perf_event_attr *attr,
  60                     pid_t pid, int cpu, int group_fd,
  61                     unsigned long flags)
  62 {
  63         return syscall(__NR_perf_event_open, attr, pid, cpu, group_fd, flags);
  64 }
  65 
  66 int perf_evsel__open(struct perf_evsel *evsel, struct perf_cpu_map *cpus,
  67                      struct perf_thread_map *threads)
  68 {
  69         int cpu, thread, err = 0;
  70 
  71         if (cpus == NULL) {
  72                 static struct perf_cpu_map *empty_cpu_map;
  73 
  74                 if (empty_cpu_map == NULL) {
  75                         empty_cpu_map = perf_cpu_map__dummy_new();
  76                         if (empty_cpu_map == NULL)
  77                                 return -ENOMEM;
  78                 }
  79 
  80                 cpus = empty_cpu_map;
  81         }
  82 
  83         if (threads == NULL) {
  84                 static struct perf_thread_map *empty_thread_map;
  85 
  86                 if (empty_thread_map == NULL) {
  87                         empty_thread_map = perf_thread_map__new_dummy();
  88                         if (empty_thread_map == NULL)
  89                                 return -ENOMEM;
  90                 }
  91 
  92                 threads = empty_thread_map;
  93         }
  94 
  95         if (evsel->fd == NULL &&
  96             perf_evsel__alloc_fd(evsel, cpus->nr, threads->nr) < 0)
  97                 return -ENOMEM;
  98 
  99         for (cpu = 0; cpu < cpus->nr; cpu++) {
 100                 for (thread = 0; thread < threads->nr; thread++) {
 101                         int fd;
 102 
 103                         fd = sys_perf_event_open(&evsel->attr,
 104                                                  threads->map[thread].pid,
 105                                                  cpus->map[cpu], -1, 0);
 106 
 107                         if (fd < 0)
 108                                 return -errno;
 109 
 110                         FD(evsel, cpu, thread) = fd;
 111                 }
 112         }
 113 
 114         return err;
 115 }
 116 
 117 void perf_evsel__close_fd(struct perf_evsel *evsel)
 118 {
 119         int cpu, thread;
 120 
 121         for (cpu = 0; cpu < xyarray__max_x(evsel->fd); cpu++)
 122                 for (thread = 0; thread < xyarray__max_y(evsel->fd); ++thread) {
 123                         close(FD(evsel, cpu, thread));
 124                         FD(evsel, cpu, thread) = -1;
 125                 }
 126 }
 127 
 128 void perf_evsel__free_fd(struct perf_evsel *evsel)
 129 {
 130         xyarray__delete(evsel->fd);
 131         evsel->fd = NULL;
 132 }
 133 
 134 void perf_evsel__close(struct perf_evsel *evsel)
 135 {
 136         if (evsel->fd == NULL)
 137                 return;
 138 
 139         perf_evsel__close_fd(evsel);
 140         perf_evsel__free_fd(evsel);
 141 }
 142 
 143 int perf_evsel__read_size(struct perf_evsel *evsel)
 144 {
 145         u64 read_format = evsel->attr.read_format;
 146         int entry = sizeof(u64); /* value */
 147         int size = 0;
 148         int nr = 1;
 149 
 150         if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
 151                 size += sizeof(u64);
 152 
 153         if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
 154                 size += sizeof(u64);
 155 
 156         if (read_format & PERF_FORMAT_ID)
 157                 entry += sizeof(u64);
 158 
 159         if (read_format & PERF_FORMAT_GROUP) {
 160                 nr = evsel->nr_members;
 161                 size += sizeof(u64);
 162         }
 163 
 164         size += entry * nr;
 165         return size;
 166 }
 167 
 168 int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread,
 169                      struct perf_counts_values *count)
 170 {
 171         size_t size = perf_evsel__read_size(evsel);
 172 
 173         memset(count, 0, sizeof(*count));
 174 
 175         if (FD(evsel, cpu, thread) < 0)
 176                 return -EINVAL;
 177 
 178         if (readn(FD(evsel, cpu, thread), count->values, size) <= 0)
 179                 return -errno;
 180 
 181         return 0;
 182 }
 183 
 184 static int perf_evsel__run_ioctl(struct perf_evsel *evsel,
 185                                  int ioc,  void *arg)
 186 {
 187         int cpu, thread;
 188 
 189         for (cpu = 0; cpu < xyarray__max_x(evsel->fd); cpu++) {
 190                 for (thread = 0; thread < xyarray__max_y(evsel->fd); thread++) {
 191                         int fd = FD(evsel, cpu, thread),
 192                             err = ioctl(fd, ioc, arg);
 193 
 194                         if (err)
 195                                 return err;
 196                 }
 197         }
 198 
 199         return 0;
 200 }
 201 
 202 int perf_evsel__enable(struct perf_evsel *evsel)
 203 {
 204         return perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_ENABLE, 0);
 205 }
 206 
 207 int perf_evsel__disable(struct perf_evsel *evsel)
 208 {
 209         return perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_DISABLE, 0);
 210 }
 211 
 212 int perf_evsel__apply_filter(struct perf_evsel *evsel, const char *filter)
 213 {
 214         return perf_evsel__run_ioctl(evsel,
 215                                      PERF_EVENT_IOC_SET_FILTER,
 216                                      (void *)filter);
 217 }
 218 
 219 struct perf_cpu_map *perf_evsel__cpus(struct perf_evsel *evsel)
 220 {
 221         return evsel->cpus;
 222 }
 223 
 224 struct perf_thread_map *perf_evsel__threads(struct perf_evsel *evsel)
 225 {
 226         return evsel->threads;
 227 }
 228 
 229 struct perf_event_attr *perf_evsel__attr(struct perf_evsel *evsel)
 230 {
 231         return &evsel->attr;
 232 }
 233 
 234 int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads)
 235 {
 236         if (ncpus == 0 || nthreads == 0)
 237                 return 0;
 238 
 239         if (evsel->system_wide)
 240                 nthreads = 1;
 241 
 242         evsel->sample_id = xyarray__new(ncpus, nthreads, sizeof(struct perf_sample_id));
 243         if (evsel->sample_id == NULL)
 244                 return -ENOMEM;
 245 
 246         evsel->id = zalloc(ncpus * nthreads * sizeof(u64));
 247         if (evsel->id == NULL) {
 248                 xyarray__delete(evsel->sample_id);
 249                 evsel->sample_id = NULL;
 250                 return -ENOMEM;
 251         }
 252 
 253         return 0;
 254 }
 255 
 256 void perf_evsel__free_id(struct perf_evsel *evsel)
 257 {
 258         xyarray__delete(evsel->sample_id);
 259         evsel->sample_id = NULL;
 260         zfree(&evsel->id);
 261         evsel->ids = 0;
 262 }

/* [<][>][^][v][top][bottom][index][help] */