int create_perf_stat_counter(int pid, int system_wide) { struct perf_event_attr attr; //cache miss memcpy(&attr, attrs, sizeof(struct perf_event_attr)); if (scale) attr.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_TOTAL_TIME_RUNNING; if (system_wide) { unsigned int cpu; for (cpu = 0; cpu < nr_cpus; cpu++) { fd[cpu] = sys_perf_event_open(&attr, -1, cpu, -1, 0); } return fd[cpu - 1]; } else { attr.inherit = inherit; attr.disabled = 0; attr.enable_on_exec = 1; return sys_perf_event_open(&attr, pid, -1, -1, 0); } }
int main(int argc, char *argv[]) { (void) argc; (void) argv; perf_event_attr attr, attr2; // Execution sur un seul CPU pid_t tid = gettid(); cpu_set_t mask; CPU_ZERO(&mask); CPU_SET(0, &mask); qDebug() << sched_setaffinity(0, sizeof(mask), &mask); //(perf_hw_cache_id) | (perf_hw_cache_op_id << 8) | //(perf_hw_cache_op_result_id << 16) // premiere structure d'attributs memset(&attr, 0, sizeof(attr)); attr.size = sizeof(attr); attr.type = PERF_TYPE_HW_CACHE; attr.config = (PERF_COUNT_HW_CACHE_L1D) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16); attr.inherit = 1; attr.disabled = 0; // Deuxieme structure memset(&attr2, 0, sizeof(attr2)); attr2.size = sizeof(attr2); attr2.type = PERF_TYPE_HW_CACHE; attr2.config = (PERF_COUNT_HW_CACHE_L1D) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16); attr2.inherit = 1; attr2.disabled = 0; //pid == 0 and cpu == -1 //This measures the calling process/thread on any CPU. int fdRef = sys_perf_event_open(&attr, tid, -1, -1, 0); int fdMiss = sys_perf_event_open(&attr2, tid, -1, -1, 0); //int fdMiss = sys_perf_event_open(&attr2, tid, -1, fdRef, 0); QMap<int, double> results; for (qint64 len = 1; len < (1 << 26); len *= 2) { double miss_rate = experiment(len, fdRef, fdMiss); results.insert(len * sizeof(int), miss_rate); } // report std::cout << "size,miss_rate" << std::endl; for (int size : results.keys()) { std::cout << size << "," << results[size] << std::endl; } close(fdRef); close(fdMiss); return 0; }
static int open_counter(size_t nr_switches) { struct perf_event_attr attr; int fd; struct f_owner_ex own; memset(&attr, 0, sizeof(attr)); attr.size = sizeof(attr); attr.type = PERF_TYPE_SOFTWARE; attr.config = PERF_COUNT_SW_CONTEXT_SWITCHES; attr.disabled = 1; attr.sample_period = nr_switches; fd = sys_perf_event_open(&attr, 0/*self*/, -1/*any cpu*/, -1, 0); if (0 > fd) err(1, "perf_event_open(cs, period=%u)", nr_switches); if (fcntl(fd, F_SETFL, O_ASYNC)) err(1, "fcntl(O_ASYNC)"); own.type = F_OWNER_TID; own.pid = sys_gettid(); if (fcntl(fd, F_SETOWN_EX, &own)) err(1, "fcntl(SETOWN_EX)"); if (fcntl(fd, F_SETSIG, SIGIO)) err(1, "fcntl(SETSIG, SIGIO)"); return fd; }
static int perf_event_open_gen(struct perf_event_attr *attr, int group_fd) { // Group leader: Request time values for reference (so we can // detect multiplexing). Also ask for the whole group to return // results at the same time. #ifdef USE_PERF_FORMAT_GROUP if (group_fd == -1) { #endif attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_TOTAL_TIME_RUNNING #ifdef USE_PERF_FORMAT_GROUP | PERF_FORMAT_GROUP #endif ; #ifdef USE_PERF_FORMAT_GROUP } #endif // Exclude kernel and hypervisor, start disabled attr->exclude_kernel = 1; attr->exclude_hv = 1; attr->disabled = 1; #ifndef USE_PERF_FORMAT_GROUP attr->inherit = 1; #endif // Create the performance counter return sys_perf_event_open(attr, 0, -1, group_fd, 0); }
int perf_open(int inherit, counter_config config) { perf_event_attr attr; memset(&attr,0,sizeof(attr)); attr.size = sizeof(attr); attr.exclude_kernel = 1; attr.type = PERF_TYPE_HARDWARE; switch(config){ case INST : attr.config = PERF_COUNT_HW_INSTRUCTIONS; break; case HW_CYCLES : attr.config = PERF_COUNT_HW_CPU_CYCLES; break; default : fprintf(stderr, "Invalid counter configuration.\n"); exit(EXIT_FAILURE); break; } attr.inherit = inherit; attr.disabled = 0; return sys_perf_event_open(&attr, 0, -1, -1, 0); }
/* * perf_open() * open perf, get leader and perf fd's */ int perf_open(stress_perf_t *sp) { size_t i; if (!sp) return -1; if (g_shared->perf.no_perf) return -1; (void)memset(sp, 0, sizeof(*sp)); sp->perf_opened = 0; for (i = 0; i < STRESS_PERF_MAX; i++) { sp->perf_stat[i].fd = -1; sp->perf_stat[i].counter = 0; } for (i = 0; i < STRESS_PERF_MAX && perf_info[i].label; i++) { if (perf_info[i].config != UNRESOLVED) { struct perf_event_attr attr; (void)memset(&attr, 0, sizeof(attr)); attr.type = perf_info[i].type; attr.config = perf_info[i].config; attr.disabled = 1; attr.inherit = 1; attr.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_TOTAL_TIME_RUNNING; attr.size = sizeof(attr); sp->perf_stat[i].fd = sys_perf_event_open(&attr, 0, -1, -1, 0); if (sp->perf_stat[i].fd > -1) sp->perf_opened++; } } if (!sp->perf_opened) { int ret; ret = shim_pthread_spin_lock(&g_shared->perf.lock); if (!ret) { pr_dbg("perf: spin lock on perf.lock failed: %d (%s)\n", ret, strerror(ret)); return -1; } if (!g_shared->perf.no_perf) { pr_dbg("perf: perf_event_open failed, no " "perf events [%u]\n", getpid()); g_shared->perf.no_perf = true; } ret = shim_pthread_spin_unlock(&g_shared->perf.lock); if (!ret) { pr_dbg("perf: spin unlock on perf.lock failed: %d (%s)\n", ret, strerror(ret)); return -1; } return -1; } return 0; }
static int sampling_start(int *pmu_fd, int freq) { int i; struct perf_event_attr pe_sample_attr = { .type = PERF_TYPE_SOFTWARE, .freq = 1, .sample_period = freq, .config = PERF_COUNT_SW_CPU_CLOCK, .inherit = 1, }; for (i = 0; i < nr_cpus; i++) { pmu_fd[i] = sys_perf_event_open(&pe_sample_attr, -1 /* pid */, i, -1 /* group_fd */, 0 /* flags */); if (pmu_fd[i] < 0) { fprintf(stderr, "ERROR: Initializing perf sampling\n"); return 1; } assert(ioctl(pmu_fd[i], PERF_EVENT_IOC_SET_BPF, prog_fd[0]) == 0); assert(ioctl(pmu_fd[i], PERF_EVENT_IOC_ENABLE, 0) == 0); } return 0; } static void sampling_end(int *pmu_fd) { int i; for (i = 0; i < nr_cpus; i++) close(pmu_fd[i]); }
static int __event(bool is_x, void *addr, struct perf_event_attr *attr) { int fd; memset(attr, 0, sizeof(struct perf_event_attr)); attr->type = PERF_TYPE_BREAKPOINT; attr->size = sizeof(struct perf_event_attr); attr->config = 0; attr->bp_type = is_x ? HW_BREAKPOINT_X : HW_BREAKPOINT_W; attr->bp_addr = (unsigned long) addr; attr->bp_len = sizeof(long); attr->sample_period = 1; attr->sample_type = PERF_SAMPLE_IP; attr->exclude_kernel = 1; attr->exclude_hv = 1; fd = sys_perf_event_open(attr, -1, 0, -1, perf_event_open_cloexec_flag()); if (fd < 0) { pr_debug("failed opening event %llx\n", attr->config); return TEST_FAIL; } return fd; }
static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, struct thread_map *threads) { int cpu, thread; if (evsel->fd == NULL && perf_evsel__alloc_fd(evsel, cpus->nr, threads->nr) < 0) return -1; for (cpu = 0; cpu < cpus->nr; cpu++) { for (thread = 0; thread < threads->nr; thread++) { FD(evsel, cpu, thread) = sys_perf_event_open(&evsel->attr, threads->map[thread], cpus->map[cpu], -1, 0); if (FD(evsel, cpu, thread) < 0) goto out_close; } } return 0; out_close: do { while (--thread >= 0) { close(FD(evsel, cpu, thread)); FD(evsel, cpu, thread) = -1; } thread = threads->nr; } while (--cpu >= 0); return -1; }
bool PerfGroup::prepareCPU(const int cpu) { logg->logMessage("%s(%s:%i): Onlining cpu %i", __FUNCTION__, __FILE__, __LINE__, cpu); for (int i = 0; i < ARRAY_LENGTH(mKeys); ++i) { if (mKeys[i] < 0) { continue; } const int offset = i * gSessionData->mCores; if (mFds[cpu + offset] >= 0) { logg->logMessage("%s(%s:%i): cpu already online or not correctly cleaned up", __FUNCTION__, __FILE__, __LINE__); return false; } logg->logMessage("%s(%s:%i): perf_event_open cpu: %i type: %lli config: %lli sample: %lli sample_type: %lli", __FUNCTION__, __FILE__, __LINE__, cpu, (long long)mAttrs[i].type, (long long)mAttrs[i].config, (long long)mAttrs[i].sample_period, (long long)mAttrs[i].sample_type); mFds[cpu + offset] = sys_perf_event_open(&mAttrs[i], -1, cpu, i == 0 ? -1 : mFds[cpu], i == 0 ? 0 : PERF_FLAG_FD_OUTPUT); if (mFds[cpu + offset] < 0) { logg->logMessage("%s(%s:%i): failed %s", __FUNCTION__, __FILE__, __LINE__, strerror(errno)); continue; } if (!mPb->useFd(cpu, mFds[cpu + offset], mFds[cpu])) { logg->logMessage("%s(%s:%i): PerfBuffer::useFd failed", __FUNCTION__, __FILE__, __LINE__); return false; } } return true; }
bool PerfMeasurement::canMeasureSomething() { // Find out if the kernel implements the performance measurement // API. If it doesn't, syscall(__NR_perf_event_open, ...) is // guaranteed to return -1 and set errno to ENOSYS. // // We set up input parameters that should provoke an EINVAL error // from a kernel that does implement perf_event_open, but we can't // be sure it will (newer kernels might add more event types), so // we have to take care to close any valid fd it might return. struct perf_event_attr attr; memset(&attr, 0, sizeof(attr)); attr.size = sizeof(attr); attr.type = PERF_TYPE_MAX; int fd = sys_perf_event_open(&attr, 0, -1, -1, 0); if (fd >= 0) { close(fd); return true; } else { return errno != ENOSYS; } }
static bool perfPoll(struct perf_event_attr *const pea) { int fd = sys_perf_event_open(pea, -1, 0, -1, 0); if (fd < 0) { return false; } close(fd); return true; }
int PerfGroup::prepareCPU(const int cpu, Monitor *const monitor) { logg.logMessage("Onlining cpu %i", cpu); for (int i = 0; i < ARRAY_LENGTH(mKeys); ++i) { if (mKeys[i] < 0) { continue; } if ((cpu != 0) && !(mFlags[i] & PERF_GROUP_PER_CPU)) { continue; } if ((mFlags[i] & PERF_GROUP_PER_CPU) && !(mFlags[i] & PERF_GROUP_ALL_CLUSTERS) && gSessionData.mSharedData->mClusters[gSessionData.mSharedData->mClusterIds[cpu]] != mClusters[i]) { continue; } const int offset = i * gSessionData.mCores + cpu; if (mFds[offset] >= 0) { logg.logMessage("cpu already online or not correctly cleaned up"); return PG_FAILURE; } logg.logMessage("perf_event_open cpu: %i type: %i config: %lli sample: %lli sample_type: 0x%llx pinned: %lli mmap: %lli comm: %lli freq: %lli task: %lli sample_id_all: %lli", cpu, mAttrs[i].type, mAttrs[i].config, mAttrs[i].sample_period, mAttrs[i].sample_type, mAttrs[i].pinned, mAttrs[i].mmap, mAttrs[i].comm, mAttrs[i].freq, mAttrs[i].task, mAttrs[i].sample_id_all); mFds[offset] = sys_perf_event_open(&mAttrs[i], -1, cpu, mAttrs[i].pinned ? -1 : mFds[mLeaders[getEffectiveType(mAttrs[i].type, mFlags[i])] * gSessionData.mCores + cpu], mAttrs[i].pinned ? 0 : PERF_FLAG_FD_OUTPUT); if (mFds[offset] < 0) { logg.logMessage("failed %s", strerror(errno)); if (errno == ENODEV) { // The core is offline return PG_CPU_OFFLINE; } if (errno == ENOENT) { // This event doesn't apply to this CPU but should apply to a different one, ex bL continue; } logg.logMessage("perf_event_open failed"); return PG_FAILURE; } if (!mPb->useFd(cpu, mFds[offset])) { logg.logMessage("PerfBuffer::useFd failed"); return PG_FAILURE; } if (!monitor->add(mFds[offset])) { logg.logMessage("Monitor::add failed"); return PG_FAILURE; } } return PG_SUCCESS; }
static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, struct thread_map *threads, bool group, struct xyarray *group_fds) { int cpu, thread; unsigned long flags = 0; int pid = -1, err; if (evsel->fd == NULL && perf_evsel__alloc_fd(evsel, cpus->nr, threads->nr) < 0) return -ENOMEM; if (evsel->cgrp) { flags = PERF_FLAG_PID_CGROUP; pid = evsel->cgrp->fd; } for (cpu = 0; cpu < cpus->nr; cpu++) { int group_fd = group_fds ? GROUP_FD(group_fds, cpu) : -1; for (thread = 0; thread < threads->nr; thread++) { if (!evsel->cgrp) pid = threads->map[thread]; FD(evsel, cpu, thread) = sys_perf_event_open(&evsel->attr, pid, cpus->map[cpu], group_fd, flags); if (FD(evsel, cpu, thread) < 0) { err = -errno; goto out_close; } if (group && group_fd == -1) group_fd = FD(evsel, cpu, thread); } } return 0; out_close: do { while (--thread >= 0) { close(FD(evsel, cpu, thread)); FD(evsel, cpu, thread) = -1; } thread = threads->nr; } while (--cpu >= 0); return err; }
static int perf_flag_probe(void) { /* use 'safest' configuration as used in perf_evsel__fallback() */ struct perf_event_attr attr = { .type = PERF_COUNT_SW_CPU_CLOCK, .config = PERF_COUNT_SW_CPU_CLOCK, }; int fd; int err; /* check cloexec flag */ fd = sys_perf_event_open(&attr, 0, -1, -1, PERF_FLAG_FD_CLOEXEC); err = errno; if (fd >= 0) { close(fd); return 1; } WARN_ONCE(err != EINVAL, "perf_event_open(..., PERF_FLAG_FD_CLOEXEC) failed with unexpected error %d (%s)\n", err, strerror(err)); /* not supported, confirm error related to PERF_FLAG_FD_CLOEXEC */ fd = sys_perf_event_open(&attr, 0, -1, -1, 0); err = errno; if (WARN_ONCE(fd < 0, "perf_event_open(..., 0) failed unexpectedly with error %d (%s)\n", err, strerror(err))) return -1; close(fd); return 0; }
static int sampling_do_open(PyObject *obj) { int tid; int flags; PyPerfEvent *ev; struct f_owner_ex fown; struct perf_event_attr attr; if (!PyPerfEvent_CheckExact(obj)) return -1; ev = (PyPerfEvent *)obj; tid = gettid(); /* Open the perf event */ attr = ev->attr; attr.disabled = 0; /* do not start the event yet */ attr.watermark = 1; attr.wakeup_events = 1; ev->fd = sys_perf_event_open(&attr, tid, -1, -1, 0); if (ev->fd < 0) { ev->status = EVENT_STATUS_FAILED; return -1; } /* Configure fasync */ fown.type = F_OWNER_TID; fown.pid = tid; if (fcntl(ev->fd, F_SETOWN_EX, &fown) < 0) goto fail; flags = fcntl(ev->fd, F_GETFL); if (fcntl(ev->fd, F_SETFL, flags | FASYNC | O_ASYNC) < 0) goto fail; ev->status = EVENT_STATUS_OPENED; xev = ev; __sync_synchronize(); ioctl(xev->fd, PERF_EVENT_IOC_REFRESH, 1); ioctl(xev->fd, PERF_EVENT_IOC_ENABLE, 0); return 0; fail: close(ev->fd); ev->fd = -1; ev->status = EVENT_STATUS_FAILED; PyErr_SetString(PyExc_RuntimeError, "fcntl() failed"); return -1; }
static void test_perf_event_task(struct perf_event_attr *attr) { int pmu_fd; /* open task bound event */ pmu_fd = sys_perf_event_open(attr, 0, -1, -1, 0); if (pmu_fd < 0) { printf("sys_perf_event_open failed\n"); return; } assert(ioctl(pmu_fd, PERF_EVENT_IOC_SET_BPF, prog_fd[0]) == 0); assert(ioctl(pmu_fd, PERF_EVENT_IOC_ENABLE, 0) == 0); system("dd if=/dev/zero of=/dev/null count=5000k"); print_stacks(); close(pmu_fd); }
static int self_open_counters(void) { struct perf_event_attr attr; int fd; memset(&attr, 0, sizeof(attr)); attr.type = PERF_TYPE_SOFTWARE; attr.config = PERF_COUNT_SW_TASK_CLOCK; fd = sys_perf_event_open(&attr, 0, -1, -1, 0); if (fd < 0) pr_err("Error: sys_perf_event_open() syscall returned " "with %d (%s)\n", fd, strerror(errno)); return fd; }
static int create_perf_counter(struct perf_setup_s *p) { struct cpu_map *cpus; int cpu; cpus = cpu_map__new(NULL); if (p == NULL) return PERF_PERIODIC_ERROR; for (cpu = 0; cpu < cpus->nr; cpu++) { if (((1 << cpu) & cpumask) == 0) continue; p->perf_fd[cpu] = sys_perf_event_open(p->attr, target_pid, cpu, -1, 0); if (p->perf_fd[cpu] < 0) return PERF_PERIODIC_ERROR; } return 0; }
static int self_open_counters(struct perf_sched *sched, unsigned long cur_task) { struct perf_event_attr attr; char sbuf[STRERR_BUFSIZE], info[STRERR_BUFSIZE]; int fd; struct rlimit limit; bool need_privilege = false; memset(&attr, 0, sizeof(attr)); attr.type = PERF_TYPE_SOFTWARE; attr.config = PERF_COUNT_SW_TASK_CLOCK; force_again: fd = sys_perf_event_open(&attr, 0, -1, -1, perf_event_open_cloexec_flag()); if (fd < 0) { if (errno == EMFILE) { if (sched->force) { BUG_ON(getrlimit(RLIMIT_NOFILE, &limit) == -1); limit.rlim_cur += sched->nr_tasks - cur_task; if (limit.rlim_cur > limit.rlim_max) { limit.rlim_max = limit.rlim_cur; need_privilege = true; } if (setrlimit(RLIMIT_NOFILE, &limit) == -1) { if (need_privilege && errno == EPERM) strcpy(info, "Need privilege\n"); } else goto force_again; } else strcpy(info, "Have a try with -f option\n"); } pr_err("Error: sys_perf_event_open() syscall returned " "with %d (%s)\n%s", fd, strerror_r(errno, sbuf, sizeof(sbuf)), info); exit(EXIT_FAILURE); } return fd; }
static void test_perf_event_all_cpu(struct perf_event_attr *attr) { int nr_cpus = sysconf(_SC_NPROCESSORS_CONF); int *pmu_fd = malloc(nr_cpus * sizeof(int)); int i; /* open perf_event on all cpus */ for (i = 0; i < nr_cpus; i++) { pmu_fd[i] = sys_perf_event_open(attr, -1, i, -1, 0); if (pmu_fd[i] < 0) { printf("sys_perf_event_open failed\n"); goto all_cpu_err; } assert(ioctl(pmu_fd[i], PERF_EVENT_IOC_SET_BPF, prog_fd[0]) == 0); assert(ioctl(pmu_fd[i], PERF_EVENT_IOC_ENABLE, 0) == 0); } system("dd if=/dev/zero of=/dev/null count=5000k"); print_stacks(); all_cpu_err: for (i--; i >= 0; i--) close(pmu_fd[i]); free(pmu_fd); }
static int load_and_attach(const char *event, struct bpf_insn *prog, int size) { bool is_socket = strncmp(event, "socket", 6) == 0; bool is_kprobe = strncmp(event, "kprobe/", 7) == 0; bool is_kretprobe = strncmp(event, "kretprobe/", 10) == 0; bool is_tracepoint = strncmp(event, "tracepoint/", 11) == 0; bool is_xdp = strncmp(event, "xdp", 3) == 0; bool is_perf_event = strncmp(event, "perf_event", 10) == 0; bool is_cgroup_skb = strncmp(event, "cgroup/skb", 10) == 0; bool is_cgroup_sk = strncmp(event, "cgroup/sock", 11) == 0; size_t insns_cnt = size / sizeof(struct bpf_insn); enum bpf_prog_type prog_type; char buf[256]; int fd, efd, err, id; struct perf_event_attr attr = {}; attr.type = PERF_TYPE_TRACEPOINT; attr.sample_type = PERF_SAMPLE_RAW; attr.sample_period = 1; attr.wakeup_events = 1; if (is_socket) { prog_type = BPF_PROG_TYPE_SOCKET_FILTER; } else if (is_kprobe || is_kretprobe) { prog_type = BPF_PROG_TYPE_KPROBE; } else if (is_tracepoint) { prog_type = BPF_PROG_TYPE_TRACEPOINT; } else if (is_xdp) { prog_type = BPF_PROG_TYPE_XDP; } else if (is_perf_event) { prog_type = BPF_PROG_TYPE_PERF_EVENT; } else if (is_cgroup_skb) { prog_type = BPF_PROG_TYPE_CGROUP_SKB; } else if (is_cgroup_sk) { prog_type = BPF_PROG_TYPE_CGROUP_SOCK; } else { printf("Unknown event '%s'\n", event); return -1; } fd = bpf_load_program(prog_type, prog, insns_cnt, license, kern_version, bpf_log_buf, BPF_LOG_BUF_SIZE); if (fd < 0) { printf("bpf_load_program() err=%d\n%s", errno, bpf_log_buf); return -1; } prog_fd[prog_cnt++] = fd; if (is_xdp || is_perf_event || is_cgroup_skb || is_cgroup_sk) return 0; if (is_socket) { event += 6; if (*event != '/') return 0; event++; if (!isdigit(*event)) { printf("invalid prog number\n"); return -1; } return populate_prog_array(event, fd); } if (is_kprobe || is_kretprobe) { if (is_kprobe) event += 7; else event += 10; if (*event == 0) { printf("event name cannot be empty\n"); return -1; } if (isdigit(*event)) return populate_prog_array(event, fd); snprintf(buf, sizeof(buf), "echo '%c:%s %s' >> /sys/kernel/debug/tracing/kprobe_events", is_kprobe ? 'p' : 'r', event, event); err = system(buf); if (err < 0) { printf("failed to create kprobe '%s' error '%s'\n", event, strerror(errno)); return -1; } strcpy(buf, DEBUGFS); strcat(buf, "events/kprobes/"); strcat(buf, event); strcat(buf, "/id"); } else if (is_tracepoint) { event += 11; if (*event == 0) { printf("event name cannot be empty\n"); return -1; } strcpy(buf, DEBUGFS); strcat(buf, "events/"); strcat(buf, event); strcat(buf, "/id"); } efd = open(buf, O_RDONLY, 0); if (efd < 0) { printf("failed to open event %s\n", event); return -1; } err = read(efd, buf, sizeof(buf)); if (err < 0 || err >= sizeof(buf)) { printf("read from '%s' failed '%s'\n", event, strerror(errno)); return -1; } close(efd); buf[err] = 0; id = atoi(buf); attr.config = id; efd = sys_perf_event_open(&attr, -1/*pid*/, 0/*cpu*/, -1/*group_fd*/, 0); if (efd < 0) { printf("event %d fd %d err %s\n", id, efd, strerror(errno)); return -1; } event_fd[prog_cnt - 1] = efd; ioctl(efd, PERF_EVENT_IOC_ENABLE, 0); ioctl(efd, PERF_EVENT_IOC_SET_BPF, fd); return 0; }
static int perf_flag_probe(void) { /* use 'safest' configuration as used in perf_evsel__fallback() */ struct perf_event_attr attr = { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CPU_CLOCK, .exclude_kernel = 1, }; int fd; int err; int cpu; pid_t pid = -1; char sbuf[STRERR_BUFSIZE]; cpu = sched_getcpu(); if (cpu < 0) cpu = 0; /* * Using -1 for the pid is a workaround to avoid gratuitous jump label * changes. */ while (1) { /* check cloexec flag */ fd = sys_perf_event_open(&attr, pid, cpu, -1, PERF_FLAG_FD_CLOEXEC); if (fd < 0 && pid == -1 && errno == EACCES) { pid = 0; continue; } break; } err = errno; if (fd >= 0) { close(fd); return 1; } WARN_ONCE(err != EINVAL && err != EBUSY, "perf_event_open(..., PERF_FLAG_FD_CLOEXEC) failed with unexpected error %d (%s)\n", err, strerror_r(err, sbuf, sizeof(sbuf))); /* not supported, confirm error related to PERF_FLAG_FD_CLOEXEC */ while (1) { fd = sys_perf_event_open(&attr, pid, cpu, -1, 0); if (fd < 0 && pid == -1 && errno == EACCES) { pid = 0; continue; } break; } err = errno; if (fd >= 0) close(fd); if (WARN_ONCE(fd < 0 && err != EBUSY, "perf_event_open(..., 0) failed unexpectedly with error %d (%s)\n", err, strerror_r(err, sbuf, sizeof(sbuf)))) return -1; return 0; } unsigned long perf_event_open_cloexec_flag(void) { static bool probed; if (!probed) { if (perf_flag_probe() <= 0) flag = 0; probed = true; } return flag; }
static void create_perf_event(void) { struct perf_event_attr attr; int ret; struct { __u64 count; __u64 time_enabled; __u64 time_running; __u64 id; } read_data; memset(&attr, 0, sizeof(attr)); attr.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_TOTAL_TIME_RUNNING | PERF_FORMAT_ID; attr.sample_freq = 0; attr.sample_period = 1; attr.sample_type |= PERF_SAMPLE_RAW; attr.mmap = 1; attr.comm = 1; attr.inherit = 0; attr.disabled = 1; attr.type = PERF_TYPE_TRACEPOINT; attr.config = get_trace_type(); if (attr.config <= 0) return; perf_fd = sys_perf_event_open(&attr, -1, 0, -1, 0); if (perf_fd < 0) { fprintf(stderr, "Perf syscall failed: %i / %i (%s)\n", perf_fd, errno, strerror(errno)); return; } if (read(perf_fd, &read_data, sizeof(read_data)) == -1) { perror("Unable to read perf file descriptor\n"); exit(-1); } fcntl(perf_fd, F_SETFL, O_NONBLOCK); perf_mmap = mmap(NULL, (128+1)*getpagesize(), PROT_READ | PROT_WRITE, MAP_SHARED, perf_fd, 0); if (perf_mmap == MAP_FAILED) { fprintf(stderr, "failed to mmap with %d (%s)\n", errno, strerror(errno)); return; } ret = ioctl(perf_fd, PERF_EVENT_IOC_ENABLE); if (ret < 0) fprintf(stderr, "failed to enable perf \n"); pc = perf_mmap; data_mmap = perf_mmap + getpagesize(); }
HRESULT CaPerfEvent::startEvent(bool enable) { PerfPmuTarget& pmuTgt = m_profConfig->getPMUTarget(); const CAThreadVec& threadVec = m_profConfig->getThreadVec(); size_t nbr = m_nbrfds; OS_OUTPUT_FORMAT_DEBUG_LOG(OS_DEBUG_LOG_DEBUG, L"nbr(%d) in startEvent", nbr); pid_t pid = -1; int group_fd = -1; int ret; int cpu; int fd; // Set perf_event_attr::disabled field m_attr.disabled = ~enable; if (pmuTgt.isSWP()) { for (size_t i = 0; i < nbr; i++) { cpu = pmuTgt.m_pCpus[i]; fd = sys_perf_event_open(&m_attr, pid, cpu, group_fd, 0); int err = errno; if (fd < 0) { OS_OUTPUT_DEBUG_LOG(L"sys_perf_event_open failed..", OS_DEBUG_LOG_ERROR); if ((EACCES == err) || (EPERM == err)) { OS_OUTPUT_DEBUG_LOG(L"sys_perf_event_open failed due to Access Permissions...", OS_DEBUG_LOG_EXTENSIVE); return E_ACCESSDENIED; } else if (ENODEV == err) { // invalid cpu list OS_OUTPUT_DEBUG_LOG(L"sys_perf_event_open failed - ENODEV...", OS_DEBUG_LOG_EXTENSIVE); return E_INVALIDARG; } else if (ENOENT == err) { // invalid cpu list OS_OUTPUT_DEBUG_LOG(L"sys_perf_event_open failed - ENOENT...", OS_DEBUG_LOG_EXTENSIVE); return E_INVALIDARG; } else if (EINVAL == err) { // invalid cpu list OS_OUTPUT_DEBUG_LOG(L"sys_perf_event_open failed - EINVAL...", OS_DEBUG_LOG_EXTENSIVE); return E_INVALIDARG; } else { OS_OUTPUT_FORMAT_DEBUG_LOG(OS_DEBUG_LOG_EXTENSIVE, L"sys_perf_event_open failed - errno(%d)", err); return E_FAIL; } } else { OS_OUTPUT_FORMAT_DEBUG_LOG(OS_DEBUG_LOG_EXTENSIVE, L"for cpu(%d) fd(%d)", cpu, fd); } m_pCountData[i].m_fd = fd; // If the event is sampling event, get the sample-id // We set the attr::read_format to PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_TOTAL_TIME_RUNNING // | PERF_FORMAT_ID; // for this the format of the data returned by read() on the fd is: // struct read_format { // u64 value; // u64 time_enabled; // u64 time_running; // u64 id; // } // if (m_samplingEvent) { ret = readn(fd, m_pCountData[i].m_values, (PERF_MAX_NBR_VALUES * sizeof(uint64_t))); // on error, return if (-1 == ret) { OS_OUTPUT_FORMAT_DEBUG_LOG(OS_DEBUG_LOG_ERROR, L"error in reading samplie-id for event(%d, %lx), fd(%d) errno(%d)\n", m_attr.type, m_attr.config, fd, errno); return E_FAIL; } m_pCountData[i].m_sampleId = m_pCountData[i].m_values[3]; // Now push this into m_eventDataList // TODO: Eventually we will discard pCountData stuff OS_OUTPUT_FORMAT_DEBUG_LOG(OS_DEBUG_LOG_EXTENSIVE, L"push elemnt in m_eventDataList i(%d)\n", i); m_eventDataList.push_back(m_pCountData[i]); } } } else { OS_OUTPUT_FORMAT_DEBUG_LOG(OS_DEBUG_LOG_DEBUG, L"nbrPids(%d) nbrThreads(%d).\n", pmuTgt.m_nbrPids, threadVec.size()); int cnt = 0; for (size_t i = 0; i < pmuTgt.m_nbrCpus; i++) { cpu = pmuTgt.m_pCpus[i]; for (size_t j = 0; j < threadVec.size(); j++, cnt++) { pid = threadVec[j]; fd = sys_perf_event_open(&m_attr, pid, cpu, group_fd, 0); if (-1 == fd) { OS_OUTPUT_FORMAT_DEBUG_LOG(OS_DEBUG_LOG_ERROR, L"sys_perf_event_open failed cpu(%d), pid(%d), cnt(%d)", cpu, pid, cnt); } else { OS_OUTPUT_FORMAT_DEBUG_LOG(OS_DEBUG_LOG_EXTENSIVE, L"for cpu(%d), pid(%d), cnt(%d), fd(%d)", cpu, pid, cnt, fd); } m_pCountData[cnt].m_fd = fd; // If the event is sampling event, get the sample-id if (m_samplingEvent) { ret = readn(fd, m_pCountData[cnt].m_values, (PERF_MAX_NBR_VALUES * sizeof(uint64_t))); // on error, return if (-1 == ret) { OS_OUTPUT_FORMAT_DEBUG_LOG(OS_DEBUG_LOG_ERROR, L"error in reading samplie-id for event(%d, %lx), fd(%d) errno(%d)", m_attr.type, m_attr.config, fd, errno); return E_FAIL; } // If the event is sampling event, get the sample-id // We set the attr::read_format to PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_TOTAL_TIME_RUNNING // | PERF_FORMAT_ID; // for this the format of the data returned by read() on the fd is: // struct read_format { // u64 value; // u64 time_enabled; // u64 time_running; // u64 id; // } // m_pCountData[cnt].m_sampleId = m_pCountData[cnt].m_values[3]; // Now push this into m_eventDataList // TODO: Eventually we will discard pCountData stuff OS_OUTPUT_FORMAT_DEBUG_LOG(OS_DEBUG_LOG_EXTENSIVE, L"push elemnt in m_eventDataList cnt(%d)\n", cnt); m_eventDataList.push_back(m_pCountData[i]); } } // threads } // cpus } // per process OS_OUTPUT_FORMAT_DEBUG_LOG(OS_DEBUG_LOG_DEBUG, L"size of m_eventDataList (%d)\n", m_eventDataList.size()); return S_OK; }
static int bpf_perf_event_open(int map_fd, int key, int cpu) { struct perf_event_attr attr = { .sample_type = PERF_SAMPLE_RAW | PERF_SAMPLE_TIME, .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_BPF_OUTPUT, }; int pmu_fd; pmu_fd = sys_perf_event_open(&attr, -1, cpu, -1, 0); if (pmu_fd < 0) { p_err("failed to open perf event %d for CPU %d", key, cpu); return -1; } if (bpf_map_update_elem(map_fd, &key, &pmu_fd, BPF_ANY)) { p_err("failed to update map for event %d for CPU %d", key, cpu); goto err_close; } if (ioctl(pmu_fd, PERF_EVENT_IOC_ENABLE, 0)) { p_err("failed to enable event %d for CPU %d", key, cpu); goto err_close; } return pmu_fd; err_close: close(pmu_fd); return -1; } int do_event_pipe(int argc, char **argv) { int i, nfds, map_fd, index = -1, cpu = -1; struct bpf_map_info map_info = {}; struct event_ring_info *rings; size_t tmp_buf_sz = 0; void *tmp_buf = NULL; struct pollfd *pfds; __u32 map_info_len; bool do_all = true; map_info_len = sizeof(map_info); map_fd = map_parse_fd_and_info(&argc, &argv, &map_info, &map_info_len); if (map_fd < 0) return -1; if (map_info.type != BPF_MAP_TYPE_PERF_EVENT_ARRAY) { p_err("map is not a perf event array"); goto err_close_map; } while (argc) { if (argc < 2) BAD_ARG(); if (is_prefix(*argv, "cpu")) { char *endptr; NEXT_ARG(); cpu = strtoul(*argv, &endptr, 0); if (*endptr) { p_err("can't parse %s as CPU ID", **argv); goto err_close_map; } NEXT_ARG(); } else if (is_prefix(*argv, "index")) { char *endptr; NEXT_ARG(); index = strtoul(*argv, &endptr, 0); if (*endptr) { p_err("can't parse %s as index", **argv); goto err_close_map; } NEXT_ARG(); } else { BAD_ARG(); } do_all = false; } if (!do_all) { if (index == -1 || cpu == -1) { p_err("cpu and index must be specified together"); goto err_close_map; } nfds = 1; } else { nfds = min(get_possible_cpus(), map_info.max_entries); cpu = 0; index = 0; } rings = calloc(nfds, sizeof(rings[0])); if (!rings) goto err_close_map; pfds = calloc(nfds, sizeof(pfds[0])); if (!pfds) goto err_free_rings; for (i = 0; i < nfds; i++) { rings[i].cpu = cpu + i; rings[i].key = index + i; rings[i].fd = bpf_perf_event_open(map_fd, rings[i].key, rings[i].cpu); if (rings[i].fd < 0) goto err_close_fds_prev; rings[i].mem = perf_event_mmap(rings[i].fd); if (!rings[i].mem) goto err_close_fds_current; pfds[i].fd = rings[i].fd; pfds[i].events = POLLIN; } signal(SIGINT, int_exit); signal(SIGHUP, int_exit); signal(SIGTERM, int_exit); if (json_output) jsonw_start_array(json_wtr); while (!stop) { poll(pfds, nfds, 200); for (i = 0; i < nfds; i++) perf_event_read(&rings[i], &tmp_buf, &tmp_buf_sz); } free(tmp_buf); if (json_output) jsonw_end_array(json_wtr); for (i = 0; i < nfds; i++) { perf_event_unmap(rings[i].mem); close(rings[i].fd); } free(pfds); free(rings); close(map_fd); return 0; err_close_fds_prev: while (i--) { perf_event_unmap(rings[i].mem); err_close_fds_current: close(rings[i].fd); } free(pfds); err_free_rings: free(rings); err_close_map: close(map_fd); return -1; }
static void create_counter(int counter, int cpu, pid_t pid) { char *filter = filters[counter]; struct perf_event_attr *attr = attrs + counter; struct perf_header_attr *h_attr; int track = !counter; /* only the first counter needs these */ int ret; struct { u64 count; u64 time_enabled; u64 time_running; u64 id; } read_data; attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_TOTAL_TIME_RUNNING | PERF_FORMAT_ID; attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID; if (freq) { attr->sample_type |= PERF_SAMPLE_PERIOD; attr->freq = 1; attr->sample_freq = freq; } if (no_samples) attr->sample_freq = 0; if (inherit_stat) attr->inherit_stat = 1; if (sample_address) attr->sample_type |= PERF_SAMPLE_ADDR; if (call_graph) attr->sample_type |= PERF_SAMPLE_CALLCHAIN; if (raw_samples) { attr->sample_type |= PERF_SAMPLE_TIME; attr->sample_type |= PERF_SAMPLE_RAW; attr->sample_type |= PERF_SAMPLE_CPU; } attr->mmap = track; attr->comm = track; attr->inherit = (cpu < 0) && inherit; attr->disabled = 1; try_again: fd[nr_cpu][counter] = sys_perf_event_open(attr, pid, cpu, group_fd, 0); if (fd[nr_cpu][counter] < 0) { int err = errno; if (err == EPERM || err == EACCES) die("Permission error - are you root?\n"); else if (err == ENODEV && profile_cpu != -1) die("No such device - did you specify an out-of-range profile CPU?\n"); /* * If it's cycles then fall back to hrtimer * based cpu-clock-tick sw counter, which * is always available even if no PMU support: */ if (attr->type == PERF_TYPE_HARDWARE && attr->config == PERF_COUNT_HW_CPU_CYCLES) { if (verbose) warning(" ... trying to fall back to cpu-clock-ticks\n"); attr->type = PERF_TYPE_SOFTWARE; attr->config = PERF_COUNT_SW_CPU_CLOCK; goto try_again; } printf("\n"); error("perfcounter syscall returned with %d (%s)\n", fd[nr_cpu][counter], strerror(err)); #if defined(__i386__) || defined(__x86_64__) if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP) die("No hardware sampling interrupt available. No APIC? If so then you can boot the kernel with the \"lapic\" boot parameter to force-enable it.\n"); #endif die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); exit(-1); } h_attr = get_header_attr(attr, counter); if (h_attr == NULL) die("nomem\n"); if (!file_new) { if (memcmp(&h_attr->attr, attr, sizeof(*attr))) { fprintf(stderr, "incompatible append\n"); exit(-1); } } if (read(fd[nr_cpu][counter], &read_data, sizeof(read_data)) == -1) { perror("Unable to read perf file descriptor\n"); exit(-1); } if (perf_header_attr__add_id(h_attr, read_data.id) < 0) { pr_warning("Not enough memory to add id\n"); exit(-1); } assert(fd[nr_cpu][counter] >= 0); fcntl(fd[nr_cpu][counter], F_SETFL, O_NONBLOCK); /* * First counter acts as the group leader: */ if (group && group_fd == -1) group_fd = fd[nr_cpu][counter]; if (multiplex && multiplex_fd == -1) multiplex_fd = fd[nr_cpu][counter]; if (multiplex && fd[nr_cpu][counter] != multiplex_fd) { ret = ioctl(fd[nr_cpu][counter], PERF_EVENT_IOC_SET_OUTPUT, multiplex_fd); assert(ret != -1); } else { event_array[nr_poll].fd = fd[nr_cpu][counter]; event_array[nr_poll].events = POLLIN; nr_poll++; mmap_array[nr_cpu][counter].counter = counter; mmap_array[nr_cpu][counter].prev = 0; mmap_array[nr_cpu][counter].mask = mmap_pages*page_size - 1; mmap_array[nr_cpu][counter].base = mmap(NULL, (mmap_pages+1)*page_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd[nr_cpu][counter], 0); if (mmap_array[nr_cpu][counter].base == MAP_FAILED) { error("failed to mmap with %d (%s)\n", errno, strerror(errno)); exit(-1); } } if (filter != NULL) { ret = ioctl(fd[nr_cpu][counter], PERF_EVENT_IOC_SET_FILTER, filter); if (ret) { error("failed to set filter with %d (%s)\n", errno, strerror(errno)); exit(-1); } } ioctl(fd[nr_cpu][counter], PERF_EVENT_IOC_ENABLE); }
int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); QElapsedTimer timer; perf_event_attr attr_inst, attr_cpu, attr_miss; memset(&attr_inst, 0, sizeof(attr_inst)); attr_inst.size = sizeof(attr_inst); attr_inst.type = PERF_TYPE_HARDWARE; attr_inst.config = PERF_COUNT_HW_INSTRUCTIONS; memset(&attr_cpu, 0, sizeof(attr_cpu)); attr_cpu.size = sizeof(attr_cpu); attr_cpu.type = PERF_TYPE_SOFTWARE; attr_cpu.config = PERF_COUNT_SW_TASK_CLOCK; memset(&attr_miss, 0, sizeof(attr_miss)); attr_miss.size = sizeof(attr_miss); attr_miss.type = PERF_TYPE_HW_CACHE; attr_miss.config = (PERF_COUNT_HW_CACHE_L1D) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16); pid_t tid = gettid(); int fd_inst = sys_perf_event_open(&attr_inst, tid, -1, -1, 0); int fd_cpu = sys_perf_event_open(&attr_cpu, tid, -1, -1, 0); int fd_miss = sys_perf_event_open(&attr_cpu, tid, -1, -1, 0); int n = 50; QVector<Sample> samples(n); int sz = 100000; QVector<int> idx_rnd(sz); // 100 000 * sizeof(int) = 400 kio, L1 32kio, LLC 4mb QVector<int> idx_lin(sz); QVector<int> buf_large(sz); QVector<int> buf_small(10); for (int i = 0; i < sz; i++) { idx_rnd[i] = i; idx_lin[i] = i; } std::random_shuffle(idx_rnd.begin(), idx_rnd.end()); for (int i = 0; i < n; i++) { //qDebug() << "before"; timer.restart(); qint64 ret = 0; qint64 val_inst0, val_inst1; qint64 val_cpu0, val_cpu1; qint64 val_miss0, val_miss1; ret |= read(fd_inst, &val_inst0, sizeof(val_inst0)); ret |= read(fd_cpu, &val_cpu0, sizeof(val_cpu0)); ret = read(fd_miss, &val_miss0, sizeof(val_miss0)); assert(ret > 0); bool slow = (i % 6) == 0; if (slow) { // Tests::read_data(buf_large, idx_rnd); Tests::factorial(100); } else { // Tests::read_data(buf_small, idx_lin); Tests::factorial(10); } // do_compute(work[i % work.size()] * scale); ret |= read(fd_inst, &val_inst1, sizeof(val_inst1)); ret |= read(fd_cpu, &val_cpu1, sizeof(val_cpu1)); ret |= read(fd_miss, &val_miss1, sizeof(val_miss1)); qint64 delta = timer.nsecsElapsed() / 1000; //qDebug() << "after" << delta; samples[i].slow = slow; samples[i].delta = delta; samples[i].inst = (val_inst1 - val_inst0) / 1000; samples[i].cpu = (val_cpu1 - val_cpu0) / 1000; samples[i].miss = (val_miss1 - val_miss0); } //run through all of them: for (int i = 0; i < n; i++) { Sample s = samples[i]; qDebug() << s; } //write the csv: QFile file("sample.csv"); if (file.open(QIODevice::WriteOnly | QIODevice::Text)) { QTextStream out(&file); for (const Sample &s: samples) { out << s.slow << "," << s.delta << "," << s.inst << "," << s.cpu << "," << s.miss << "\n"; } file.close(); } return 0; }
/* * Create an event group that contains both a sampled hardware * (cpu-cycles) and software (intel_cqm/llc_occupancy/) event. We then * wait for the hardware perf counter to overflow and generate a PMI, * which triggers an event read for both of the events in the group. * * Since reading Intel CQM event counters requires sending SMP IPIs, the * CQM pmu needs to handle the above situation gracefully, and return * the last read counter value to avoid triggering a WARN_ON_ONCE() in * smp_call_function_many() caused by sending IPIs from NMI context. */ int test__intel_cqm_count_nmi_context(int subtest __maybe_unused) { struct perf_evlist *evlist = NULL; struct perf_evsel *evsel = NULL; struct perf_event_attr pe; int i, fd[2], flag, ret; size_t mmap_len; void *event; pid_t pid; int err = TEST_FAIL; flag = perf_event_open_cloexec_flag(); evlist = perf_evlist__new(); if (!evlist) { pr_debug("perf_evlist__new failed\n"); return TEST_FAIL; } ret = parse_events(evlist, "intel_cqm/llc_occupancy/", NULL); if (ret) { pr_debug("parse_events failed, is \"intel_cqm/llc_occupancy/\" available?\n"); err = TEST_SKIP; goto out; } evsel = perf_evlist__first(evlist); if (!evsel) { pr_debug("perf_evlist__first failed\n"); goto out; } memset(&pe, 0, sizeof(pe)); pe.size = sizeof(pe); pe.type = PERF_TYPE_HARDWARE; pe.config = PERF_COUNT_HW_CPU_CYCLES; pe.read_format = PERF_FORMAT_GROUP; pe.sample_period = 128; pe.sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_READ; pid = spawn(); fd[0] = sys_perf_event_open(&pe, pid, -1, -1, flag); if (fd[0] < 0) { pr_debug("failed to open event\n"); goto out; } memset(&pe, 0, sizeof(pe)); pe.size = sizeof(pe); pe.type = evsel->attr.type; pe.config = evsel->attr.config; fd[1] = sys_perf_event_open(&pe, pid, -1, fd[0], flag); if (fd[1] < 0) { pr_debug("failed to open event\n"); goto out; } /* * Pick a power-of-two number of pages + 1 for the meta-data * page (struct perf_event_mmap_page). See tools/perf/design.txt. */ mmap_len = page_size * 65; event = mmap(NULL, mmap_len, PROT_READ, MAP_SHARED, fd[0], 0); if (event == (void *)(-1)) { pr_debug("failed to mmap %d\n", errno); goto out; } sleep(1); err = TEST_OK; munmap(event, mmap_len); for (i = 0; i < 2; i++) close(fd[i]); kill(pid, SIGKILL); wait(NULL); out: perf_evlist__delete(evlist); return err; }
void perf_event::create_perf_event(char *eventname, int _cpu) { struct perf_event_attr attr; int ret; int err; struct { __u64 count; __u64 time_enabled; __u64 time_running; __u64 id; } read_data; if (perf_fd != -1) clear(); memset(&attr, 0, sizeof(attr)); attr.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_TOTAL_TIME_RUNNING | PERF_FORMAT_ID; attr.sample_freq = 0; attr.sample_period = 1; attr.sample_type |= PERF_SAMPLE_RAW | PERF_SAMPLE_CPU | PERF_SAMPLE_TIME; attr.mmap = 1; attr.comm = 1; attr.inherit = 0; attr.disabled = 1; attr.type = PERF_TYPE_TRACEPOINT; attr.config = trace_type; if (attr.config <= 0) return; perf_fd = sys_perf_event_open(&attr, -1, _cpu, -1, 0); if (perf_fd < 0) { err = errno; reset_display(); if (err == EMFILE) fprintf(stderr, _("Too many open files, please increase the limit of open file descriptors.\n")); else { fprintf(stderr, _("PowerTOP %s needs the kernel to support the 'perf' subsystem\n"), POWERTOP_VERSION); fprintf(stderr, _("as well as support for trace points in the kernel:\n")); fprintf(stderr, "CONFIG_PERF_EVENTS=y\nCONFIG_PERF_COUNTERS=y\nCONFIG_TRACEPOINTS=y\nCONFIG_TRACING=y\n"); } exit(EXIT_FAILURE); } if (read(perf_fd, &read_data, sizeof(read_data)) == -1) { reset_display(); perror("Unable to read perf file descriptor\n"); exit(-1); } fcntl(perf_fd, F_SETFL, O_NONBLOCK); perf_mmap = mmap(NULL, (bufsize+1)*getpagesize(), PROT_READ | PROT_WRITE, MAP_SHARED, perf_fd, 0); if (perf_mmap == MAP_FAILED) { fprintf(stderr, "failed to mmap with %d (%s)\n", errno, strerror(errno)); return; } ret = ioctl(perf_fd, PERF_EVENT_IOC_ENABLE, 0); if (ret < 0) { fprintf(stderr, "failed to enable perf \n"); } pc = (perf_event_mmap_page *)perf_mmap; data_mmap = (unsigned char *)perf_mmap + getpagesize(); }