// SPDX-License-Identifier: GPL-2.0#include <errno.h>#include <unistd.h>#include <sys/syscall.h>#include <perf/evsel.h>#include <perf/cpumap.h>#include <perf/threadmap.h>#include <linux/hash.h>#include <linux/list.h>#include <internal/evsel.h>#include <linux/zalloc.h>#include <stdlib.h>#include <internal/xyarray.h>#include <internal/cpumap.h>#include <internal/mmap.h>#include <internal/threadmap.h>#include <internal/lib.h>#include <linux/string.h>#include <sys/ioctl.h>#include <sys/mman.h>#include <asm/bug.h> void perf_evsel__init(struct perf_evsel *evsel, struct perf_event_attr *attr, int idx){ INIT_LIST_HEAD(&evsel->node); INIT_LIST_HEAD(&evsel->per_stream_periods); evsel->attr = *attr; evsel->idx = idx; evsel->leader = evsel;} struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr){ struct perf_evsel *evsel = zalloc(sizeof(*evsel)); if (evsel != NULL) perf_evsel__init(evsel, attr, 0); return evsel;} void perf_evsel__exit(struct perf_evsel *evsel){ assert(evsel->fd == NULL); /* If not fds were not closed. */ assert(evsel->mmap == NULL); /* If not munmap wasn't called. */ assert(evsel->sample_id == NULL); /* If not free_id wasn't called. */ perf_cpu_map__put(evsel->cpus); perf_cpu_map__put(evsel->pmu_cpus); perf_thread_map__put(evsel->threads);} void perf_evsel__delete(struct perf_evsel *evsel){ perf_evsel__exit(evsel); free(evsel);} #define FD(_evsel, _cpu_map_idx, _thread) \ ((int *)xyarray__entry(_evsel->fd, _cpu_map_idx, _thread))#define MMAP(_evsel, _cpu_map_idx, _thread) \ (_evsel->mmap ? ((struct perf_mmap *) xyarray__entry(_evsel->mmap, _cpu_map_idx, _thread)) \ : NULL) int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads){ evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int)); if (evsel->fd) { int idx, thread; for (idx = 0; idx < ncpus; idx++) { for (thread = 0; thread < nthreads; thread++) { int *fd = FD(evsel, idx, thread); if (fd) *fd = -1; } } } return evsel->fd != NULL ? 0 : -ENOMEM;} static int perf_evsel__alloc_mmap(struct perf_evsel *evsel, int ncpus, int nthreads){ evsel->mmap = xyarray__new(ncpus, nthreads, sizeof(struct perf_mmap)); return evsel->mmap != NULL ? 0 : -ENOMEM;} static intsys_perf_event_open(struct perf_event_attr *attr, pid_t pid, struct perf_cpu cpu, int group_fd, unsigned long flags){ return syscall(__NR_perf_event_open, attr, pid, cpu.cpu, group_fd, flags);} static int get_group_fd(struct perf_evsel *evsel, int cpu_map_idx, int thread, int *group_fd){ struct perf_evsel *leader = evsel->leader; int *fd; if (evsel == leader) { *group_fd = -1; return 0; } /* * Leader must be already processed/open, * if not it's a bug. */ if (!leader->fd) return -ENOTCONN; fd = FD(leader, cpu_map_idx, thread); if (fd == NULL || *fd == -1) return -EBADF; *group_fd = *fd; return 0;} int perf_evsel__open(struct perf_evsel *evsel, struct perf_cpu_map *cpus, struct perf_thread_map *threads){ struct perf_cpu cpu; unsigned int idx; int thread, err = 0; if (cpus == NULL) { static struct perf_cpu_map *empty_cpu_map; if (empty_cpu_map == NULL) { empty_cpu_map = perf_cpu_map__new_any_cpu(); if (empty_cpu_map == NULL) return -ENOMEM; } cpus = empty_cpu_map; } if (threads == NULL) { static struct perf_thread_map *empty_thread_map; if (empty_thread_map == NULL) { empty_thread_map = perf_thread_map__new_dummy(); if (empty_thread_map == NULL) return -ENOMEM; } threads = empty_thread_map; } if (evsel->fd == NULL && perf_evsel__alloc_fd(evsel, perf_cpu_map__nr(cpus), threads->nr) < 0) return -ENOMEM; perf_cpu_map__for_each_cpu(cpu, idx, cpus) { for (thread = 0; thread < threads->nr; thread++) { int fd, group_fd, *evsel_fd; evsel_fd = FD(evsel, idx, thread); if (evsel_fd == NULL) { err = -EINVAL; goto out; } err = get_group_fd(evsel, idx, thread, &group_fd); if (err < 0) goto out; fd = sys_perf_event_open(&evsel->attr, threads->map[thread].pid, cpu, group_fd, 0); if (fd < 0) { err = -errno; goto out; } *evsel_fd = fd; } }out: if (err) perf_evsel__close(evsel); return err;} static void perf_evsel__close_fd_cpu(struct perf_evsel *evsel, int cpu_map_idx){ int thread; for (thread = 0; thread < xyarray__max_y(evsel->fd); ++thread) { int *fd = FD(evsel, cpu_map_idx, thread); if (fd && *fd >= 0) { close(*fd); *fd = -1; } }} void perf_evsel__close_fd(struct perf_evsel *evsel){ for (int idx = 0; idx < xyarray__max_x(evsel->fd); idx++) perf_evsel__close_fd_cpu(evsel, idx);} void perf_evsel__free_fd(struct perf_evsel *evsel){ xyarray__delete(evsel->fd); evsel->fd = NULL;} void perf_evsel__close(struct perf_evsel *evsel){ if (evsel->fd == NULL) return; perf_evsel__close_fd(evsel); perf_evsel__free_fd(evsel);} void perf_evsel__close_cpu(struct perf_evsel *evsel, int cpu_map_idx){ if (evsel->fd == NULL) return; perf_evsel__close_fd_cpu(evsel, cpu_map_idx);} void perf_evsel__munmap(struct perf_evsel *evsel){ int idx, thread; if (evsel->fd == NULL || evsel->mmap == NULL) return; for (idx = 0; idx < xyarray__max_x(evsel->fd); idx++) { for (thread = 0; thread < xyarray__max_y(evsel->fd); thread++) { int *fd = FD(evsel, idx, thread); if (fd == NULL || *fd < 0) continue; perf_mmap__munmap(MMAP(evsel, idx, thread)); } } xyarray__delete(evsel->mmap); evsel->mmap = NULL;} int perf_evsel__mmap(struct perf_evsel *evsel, int pages){ int ret, idx, thread; struct perf_mmap_param mp = { .prot = PROT_READ | PROT_WRITE, .mask = (pages * page_size) - 1, }; if (evsel->fd == NULL || evsel->mmap) return -EINVAL; if (perf_evsel__alloc_mmap(evsel, xyarray__max_x(evsel->fd), xyarray__max_y(evsel->fd)) < 0) return -ENOMEM; for (idx = 0; idx < xyarray__max_x(evsel->fd); idx++) { for (thread = 0; thread < xyarray__max_y(evsel->fd); thread++) { int *fd = FD(evsel, idx, thread); struct perf_mmap *map; struct perf_cpu cpu = perf_cpu_map__cpu(evsel->cpus, idx); if (fd == NULL || *fd < 0) continue; map = MMAP(evsel, idx, thread); perf_mmap__init(map, NULL, false, NULL); ret = perf_mmap__mmap(map, &mp, *fd, cpu); if (ret) { perf_evsel__munmap(evsel); return ret; } } } return 0;} void *perf_evsel__mmap_base(struct perf_evsel *evsel, int cpu_map_idx, int thread){ int *fd = FD(evsel, cpu_map_idx, thread); if (fd == NULL || *fd < 0 || MMAP(evsel, cpu_map_idx, thread) == NULL) return NULL; return MMAP(evsel, cpu_map_idx, thread)->base;} int perf_evsel__read_size(struct perf_evsel *evsel){ u64 read_format = evsel->attr.read_format; int entry = sizeof(u64); /* value */ int size = 0; int nr = 1; if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) size += sizeof(u64); if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) size += sizeof(u64); if (read_format & PERF_FORMAT_ID) entry += sizeof(u64); if (read_format & PERF_FORMAT_LOST) entry += sizeof(u64); if (read_format & PERF_FORMAT_GROUP) { nr = evsel->nr_members; size += sizeof(u64); } size += entry * nr; return size;} /* This only reads values for the leader */static int perf_evsel__read_group(struct perf_evsel *evsel, int cpu_map_idx, int thread, struct perf_counts_values *count){ size_t size = perf_evsel__read_size(evsel); int *fd = FD(evsel, cpu_map_idx, thread); u64 read_format = evsel->attr.read_format; u64 *data; int idx = 1; if (fd == NULL || *fd < 0) return -EINVAL; data = calloc(1, size); if (data == NULL) return -ENOMEM; if (readn(*fd, data, size) <= 0) { free(data); return -errno; } /* * This reads only the leader event intentionally since we don't have * perf counts values for sibling events. */ if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) count->ena = data[idx++]; if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) count->run = data[idx++]; /* value is always available */ count->val = data[idx++]; if (read_format & PERF_FORMAT_ID) count->id = data[idx++]; if (read_format & PERF_FORMAT_LOST) count->lost = data[idx++]; free(data); return 0;} /* * The perf read format is very flexible. It needs to set the proper * values according to the read format. */static void perf_evsel__adjust_values(struct perf_evsel *evsel, u64 *buf, struct perf_counts_values *count){ u64 read_format = evsel->attr.read_format; int n = 0; count->val = buf[n++]; if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) count->ena = buf[n++]; if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) count->run = buf[n++]; if (read_format & PERF_FORMAT_ID) count->id = buf[n++]; if (read_format & PERF_FORMAT_LOST) count->lost = buf[n++];} int perf_evsel__read(struct perf_evsel *evsel, int cpu_map_idx, int thread, struct perf_counts_values *count){ size_t size = perf_evsel__read_size(evsel); int *fd = FD(evsel, cpu_map_idx, thread); u64 read_format = evsel->attr.read_format; struct perf_counts_values buf; memset(count, 0, sizeof(*count)); if (fd == NULL || *fd < 0) return -EINVAL; if (read_format & PERF_FORMAT_GROUP) return perf_evsel__read_group(evsel, cpu_map_idx, thread, count); if (MMAP(evsel, cpu_map_idx, thread) && !(read_format & (PERF_FORMAT_ID | PERF_FORMAT_LOST)) && !perf_mmap__read_self(MMAP(evsel, cpu_map_idx, thread), count)) return 0; if (readn(*fd, buf.values, size) <= 0) return -errno; perf_evsel__adjust_values(evsel, buf.values, count); return 0;} static int perf_evsel__ioctl(struct perf_evsel *evsel, int ioc, void *arg, int cpu_map_idx, int thread){ int *fd = FD(evsel, cpu_map_idx, thread); if (fd == NULL || *fd < 0) return -1; return ioctl(*fd, ioc, arg);} static int perf_evsel__run_ioctl(struct perf_evsel *evsel, int ioc, void *arg, int cpu_map_idx){ int thread; for (thread = 0; thread < xyarray__max_y(evsel->fd); thread++) { int err = perf_evsel__ioctl(evsel, ioc, arg, cpu_map_idx, thread); if (err) return err; } return 0;} int perf_evsel__enable_cpu(struct perf_evsel *evsel, int cpu_map_idx){ return perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_ENABLE, NULL, cpu_map_idx);} int perf_evsel__enable_thread(struct perf_evsel *evsel, int thread){ struct perf_cpu cpu __maybe_unused; unsigned int idx; int err; perf_cpu_map__for_each_cpu(cpu, idx, evsel->cpus) { err = perf_evsel__ioctl(evsel, PERF_EVENT_IOC_ENABLE, NULL, idx, thread); if (err) return err; } return 0;} int perf_evsel__enable(struct perf_evsel *evsel){ int i; int err = 0; for (i = 0; i < xyarray__max_x(evsel->fd) && !err; i++) err = perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_ENABLE, NULL, i); return err;} int perf_evsel__disable_cpu(struct perf_evsel *evsel, int cpu_map_idx){ return perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_DISABLE, NULL, cpu_map_idx);} int perf_evsel__disable(struct perf_evsel *evsel){ int i; int err = 0; for (i = 0; i < xyarray__max_x(evsel->fd) && !err; i++) err = perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_DISABLE, NULL, i); return err;} Lines 1–500 of 618. Load more
// SPDX-License-Identifier: GPL-2.0 #include <errno.h> #include <unistd.h> #include <sys/syscall.h> #include <perf/evsel.h> #include <perf/cpumap.h> #include <perf/threadmap.h> #include <linux/hash.h> #include <linux/list.h> #include <internal/evsel.h> #include <linux/zalloc.h> #include <stdlib.h> #include <internal/xyarray.h> #include <internal/cpumap.h> #include <internal/mmap.h> #include <internal/threadmap.h> #include <internal/lib.h> #include <linux/string.h> #include <sys/ioctl.h> #include <sys/mman.h> #include <asm/bug.h> void perf_evsel__init(struct perf_evsel *evsel, struct perf_event_attr *attr, int idx) { INIT_LIST_HEAD(&evsel->node); INIT_LIST_HEAD(&evsel->per_stream_periods); evsel->attr = *attr; evsel->idx = idx; evsel->leader = evsel; } struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr) { struct perf_evsel *evsel = zalloc(sizeof(*evsel)); if (evsel != NULL) perf_evsel__init(evsel, attr, 0); return evsel; } void perf_evsel__exit(struct perf_evsel *evsel) { assert(evsel->fd == NULL); /* If not fds were not closed. */ assert(evsel->mmap == NULL); /* If not munmap wasn't called. */ assert(evsel->sample_id == NULL); /* If not free_id wasn't called. */ perf_cpu_map__put(evsel->cpus); perf_cpu_map__put(evsel->pmu_cpus); perf_thread_map__put(evsel->threads); } void perf_evsel__delete(struct perf_evsel *evsel) { perf_evsel__exit(evsel); free(evsel); } #define FD(_evsel, _cpu_map_idx, _thread) \ ((int *)xyarray__entry(_evsel->fd, _cpu_map_idx, _thread)) #define MMAP(_evsel, _cpu_map_idx, _thread) \ (_evsel->mmap ? ((struct perf_mmap *) xyarray__entry(_evsel->mmap, _cpu_map_idx, _thread)) \ : NULL) int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) { evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int)); if (evsel->fd) { int idx, thread; for (idx = 0; idx < ncpus; idx++) { for (thread = 0; thread < nthreads; thread++) { int *fd = FD(evsel, idx, thread); if (fd) *fd = -1; } } } return evsel->fd != NULL ? 0 : -ENOMEM; } static int perf_evsel__alloc_mmap(struct perf_evsel *evsel, int ncpus, int nthreads) { evsel->mmap = xyarray__new(ncpus, nthreads, sizeof(struct perf_mmap)); return evsel->mmap != NULL ? 0 : -ENOMEM; } static int sys_perf_event_open(struct perf_event_attr *attr, pid_t pid, struct perf_cpu cpu, int group_fd, unsigned long flags) { return syscall(__NR_perf_event_open, attr, pid, cpu.cpu, group_fd, flags); } static int get_group_fd(struct perf_evsel *evsel, int cpu_map_idx, int thread, int *group_fd) { struct perf_evsel *leader = evsel->leader; int *fd; if (evsel == leader) { *group_fd = -1; return 0; } /* * Leader must be already processed/open, * if not it's a bug. */ if (!leader->fd) return -ENOTCONN; fd = FD(leader, cpu_map_idx, thread); if (fd == NULL || *fd == -1) return -EBADF; *group_fd = *fd; return 0; } int perf_evsel__open(struct perf_evsel *evsel, struct perf_cpu_map *cpus, struct perf_thread_map *threads) { struct perf_cpu cpu; unsigned int idx; int thread, err = 0; if (cpus == NULL) { static struct perf_cpu_map *empty_cpu_map; if (empty_cpu_map == NULL) { empty_cpu_map = perf_cpu_map__new_any_cpu(); if (empty_cpu_map == NULL) return -ENOMEM; } cpus = empty_cpu_map; } if (threads == NULL) { static struct perf_thread_map *empty_thread_map; if (empty_thread_map == NULL) { empty_thread_map = perf_thread_map__new_dummy(); if (empty_thread_map == NULL) return -ENOMEM; } threads = empty_thread_map; } if (evsel->fd == NULL && perf_evsel__alloc_fd(evsel, perf_cpu_map__nr(cpus), threads->nr) < 0) return -ENOMEM; perf_cpu_map__for_each_cpu(cpu, idx, cpus) { for (thread = 0; thread < threads->nr; thread++) { int fd, group_fd, *evsel_fd; evsel_fd = FD(evsel, idx, thread); if (evsel_fd == NULL) { err = -EINVAL; goto out; } err = get_group_fd(evsel, idx, thread, &group_fd); if (err < 0) goto out; fd = sys_perf_event_open(&evsel->attr, threads->map[thread].pid, cpu, group_fd, 0); if (fd < 0) { err = -errno; goto out; } *evsel_fd = fd; } } out: if (err) perf_evsel__close(evsel); return err; } static void perf_evsel__close_fd_cpu(struct perf_evsel *evsel, int cpu_map_idx) { int thread; for (thread = 0; thread < xyarray__max_y(evsel->fd); ++thread) { int *fd = FD(evsel, cpu_map_idx, thread); if (fd && *fd >= 0) { close(*fd); *fd = -1; } } } void perf_evsel__close_fd(struct perf_evsel *evsel) { for (int idx = 0; idx < xyarray__max_x(evsel->fd); idx++) perf_evsel__close_fd_cpu(evsel, idx); } void perf_evsel__free_fd(struct perf_evsel *evsel) { xyarray__delete(evsel->fd); evsel->fd = NULL; } void perf_evsel__close(struct perf_evsel *evsel) { if (evsel->fd == NULL) return; perf_evsel__close_fd(evsel); perf_evsel__free_fd(evsel); } void perf_evsel__close_cpu(struct perf_evsel *evsel, int cpu_map_idx) { if (evsel->fd == NULL) return; perf_evsel__close_fd_cpu(evsel, cpu_map_idx); } void perf_evsel__munmap(struct perf_evsel *evsel) { int idx, thread; if (evsel->fd == NULL || evsel->mmap == NULL) return; for (idx = 0; idx < xyarray__max_x(evsel->fd); idx++) { for (thread = 0; thread < xyarray__max_y(evsel->fd); thread++) { int *fd = FD(evsel, idx, thread); if (fd == NULL || *fd < 0) continue; perf_mmap__munmap(MMAP(evsel, idx, thread)); } } xyarray__delete(evsel->mmap); evsel->mmap = NULL; } int perf_evsel__mmap(struct perf_evsel *evsel, int pages) { int ret, idx, thread; struct perf_mmap_param mp = { .prot = PROT_READ | PROT_WRITE, .mask = (pages * page_size) - 1, }; if (evsel->fd == NULL || evsel->mmap) return -EINVAL; if (perf_evsel__alloc_mmap(evsel, xyarray__max_x(evsel->fd), xyarray__max_y(evsel->fd)) < 0) return -ENOMEM; for (idx = 0; idx < xyarray__max_x(evsel->fd); idx++) { for (thread = 0; thread < xyarray__max_y(evsel->fd); thread++) { int *fd = FD(evsel, idx, thread); struct perf_mmap *map; struct perf_cpu cpu = perf_cpu_map__cpu(evsel->cpus, idx); if (fd == NULL || *fd < 0) continue; map = MMAP(evsel, idx, thread); perf_mmap__init(map, NULL, false, NULL); ret = perf_mmap__mmap(map, &mp, *fd, cpu); if (ret) { perf_evsel__munmap(evsel); return ret; } } } return 0; } void *perf_evsel__mmap_base(struct perf_evsel *evsel, int cpu_map_idx, int thread) { int *fd = FD(evsel, cpu_map_idx, thread); if (fd == NULL || *fd < 0 || MMAP(evsel, cpu_map_idx, thread) == NULL) return NULL; return MMAP(evsel, cpu_map_idx, thread)->base; } int perf_evsel__read_size(struct perf_evsel *evsel) { u64 read_format = evsel->attr.read_format; int entry = sizeof(u64); /* value */ int size = 0; int nr = 1; if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) size += sizeof(u64); if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) size += sizeof(u64); if (read_format & PERF_FORMAT_ID) entry += sizeof(u64); if (read_format & PERF_FORMAT_LOST) entry += sizeof(u64); if (read_format & PERF_FORMAT_GROUP) { nr = evsel->nr_members; size += sizeof(u64); } size += entry * nr; return size; } /* This only reads values for the leader */ static int perf_evsel__read_group(struct perf_evsel *evsel, int cpu_map_idx, int thread, struct perf_counts_values *count) { size_t size = perf_evsel__read_size(evsel); int *fd = FD(evsel, cpu_map_idx, thread); u64 read_format = evsel->attr.read_format; u64 *data; int idx = 1; if (fd == NULL || *fd < 0) return -EINVAL; data = calloc(1, size); if (data == NULL) return -ENOMEM; if (readn(*fd, data, size) <= 0) { free(data); return -errno; } /* * This reads only the leader event intentionally since we don't have * perf counts values for sibling events. */ if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) count->ena = data[idx++]; if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) count->run = data[idx++]; /* value is always available */ count->val = data[idx++]; if (read_format & PERF_FORMAT_ID) count->id = data[idx++]; if (read_format & PERF_FORMAT_LOST) count->lost = data[idx++]; free(data); return 0; } /* * The perf read format is very flexible. It needs to set the proper * values according to the read format. */ static void perf_evsel__adjust_values(struct perf_evsel *evsel, u64 *buf, struct perf_counts_values *count) { u64 read_format = evsel->attr.read_format; int n = 0; count->val = buf[n++]; if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) count->ena = buf[n++]; if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) count->run = buf[n++]; if (read_format & PERF_FORMAT_ID) count->id = buf[n++]; if (read_format & PERF_FORMAT_LOST) count->lost = buf[n++]; } int perf_evsel__read(struct perf_evsel *evsel, int cpu_map_idx, int thread, struct perf_counts_values *count) { size_t size = perf_evsel__read_size(evsel); int *fd = FD(evsel, cpu_map_idx, thread); u64 read_format = evsel->attr.read_format; struct perf_counts_values buf; memset(count, 0, sizeof(*count)); if (fd == NULL || *fd < 0) return -EINVAL; if (read_format & PERF_FORMAT_GROUP) return perf_evsel__read_group(evsel, cpu_map_idx, thread, count); if (MMAP(evsel, cpu_map_idx, thread) && !(read_format & (PERF_FORMAT_ID | PERF_FORMAT_LOST)) && !perf_mmap__read_self(MMAP(evsel, cpu_map_idx, thread), count)) return 0; if (readn(*fd, buf.values, size) <= 0) return -errno; perf_evsel__adjust_values(evsel, buf.values, count); return 0; } static int perf_evsel__ioctl(struct perf_evsel *evsel, int ioc, void *arg, int cpu_map_idx, int thread) { int *fd = FD(evsel, cpu_map_idx, thread); if (fd == NULL || *fd < 0) return -1; return ioctl(*fd, ioc, arg); } static int perf_evsel__run_ioctl(struct perf_evsel *evsel, int ioc, void *arg, int cpu_map_idx) { int thread; for (thread = 0; thread < xyarray__max_y(evsel->fd); thread++) { int err = perf_evsel__ioctl(evsel, ioc, arg, cpu_map_idx, thread); if (err) return err; } return 0; } int perf_evsel__enable_cpu(struct perf_evsel *evsel, int cpu_map_idx) { return perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_ENABLE, NULL, cpu_map_idx); } int perf_evsel__enable_thread(struct perf_evsel *evsel, int thread) { struct perf_cpu cpu __maybe_unused; unsigned int idx; int err; perf_cpu_map__for_each_cpu(cpu, idx, evsel->cpus) { err = perf_evsel__ioctl(evsel, PERF_EVENT_IOC_ENABLE, NULL, idx, thread); if (err) return err; } return 0; } int perf_evsel__enable(struct perf_evsel *evsel) { int i; int err = 0; for (i = 0; i < xyarray__max_x(evsel->fd) && !err; i++) err = perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_ENABLE, NULL, i); return err; } int perf_evsel__disable_cpu(struct perf_evsel *evsel, int cpu_map_idx) { return perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_DISABLE, NULL, cpu_map_idx); } int perf_evsel__disable(struct perf_evsel *evsel) { int i; int err = 0; for (i = 0; i < xyarray__max_x(evsel->fd) && !err; i++) err = perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_DISABLE, NULL, i); return err; }