162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci#define _GNU_SOURCE // needed for sched.h to get sched_[gs]etaffinity and CPU_(ZERO,SET) 362306a36Sopenharmony_ci#include <inttypes.h> 462306a36Sopenharmony_ci#include <sched.h> 562306a36Sopenharmony_ci#include <stdio.h> 662306a36Sopenharmony_ci#include <stdarg.h> 762306a36Sopenharmony_ci#include <unistd.h> 862306a36Sopenharmony_ci#include <stdlib.h> 962306a36Sopenharmony_ci#include <linux/perf_event.h> 1062306a36Sopenharmony_ci#include <linux/limits.h> 1162306a36Sopenharmony_ci#include <sys/types.h> 1262306a36Sopenharmony_ci#include <sys/wait.h> 1362306a36Sopenharmony_ci#include <sys/prctl.h> 1462306a36Sopenharmony_ci#include <perf/cpumap.h> 1562306a36Sopenharmony_ci#include <perf/threadmap.h> 1662306a36Sopenharmony_ci#include <perf/evlist.h> 1762306a36Sopenharmony_ci#include <perf/evsel.h> 1862306a36Sopenharmony_ci#include <perf/mmap.h> 1962306a36Sopenharmony_ci#include <perf/event.h> 2062306a36Sopenharmony_ci#include <internal/tests.h> 2162306a36Sopenharmony_ci#include <api/fs/fs.h> 2262306a36Sopenharmony_ci#include "tests.h" 2362306a36Sopenharmony_ci#include <internal/evsel.h> 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#define EVENT_NUM 15 2662306a36Sopenharmony_ci#define WAIT_COUNT 100000000UL 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_cistatic int libperf_print(enum libperf_print_level level, 2962306a36Sopenharmony_ci const char *fmt, va_list ap) 3062306a36Sopenharmony_ci{ 3162306a36Sopenharmony_ci return vfprintf(stderr, fmt, ap); 3262306a36Sopenharmony_ci} 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_cistatic int test_stat_cpu(void) 3562306a36Sopenharmony_ci{ 3662306a36Sopenharmony_ci struct perf_cpu_map *cpus; 3762306a36Sopenharmony_ci struct perf_evlist *evlist; 3862306a36Sopenharmony_ci struct perf_evsel *evsel, *leader; 3962306a36Sopenharmony_ci struct perf_event_attr attr1 = { 4062306a36Sopenharmony_ci .type = PERF_TYPE_SOFTWARE, 4162306a36Sopenharmony_ci .config = PERF_COUNT_SW_CPU_CLOCK, 4262306a36Sopenharmony_ci }; 4362306a36Sopenharmony_ci struct perf_event_attr attr2 = { 4462306a36Sopenharmony_ci .type = PERF_TYPE_SOFTWARE, 4562306a36Sopenharmony_ci .config = PERF_COUNT_SW_TASK_CLOCK, 4662306a36Sopenharmony_ci }; 4762306a36Sopenharmony_ci int err, idx; 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci cpus = perf_cpu_map__new(NULL); 5062306a36Sopenharmony_ci __T("failed to create cpus", cpus); 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci evlist = perf_evlist__new(); 5362306a36Sopenharmony_ci __T("failed to create evlist", evlist); 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci evsel = leader = perf_evsel__new(&attr1); 5662306a36Sopenharmony_ci __T("failed to create evsel1", evsel); 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci perf_evlist__add(evlist, evsel); 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci evsel = perf_evsel__new(&attr2); 6162306a36Sopenharmony_ci __T("failed to create evsel2", evsel); 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci perf_evlist__add(evlist, evsel); 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci perf_evlist__set_leader(evlist); 6662306a36Sopenharmony_ci __T("failed to set leader", leader->leader == leader); 6762306a36Sopenharmony_ci __T("failed to set leader", evsel->leader == leader); 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci perf_evlist__set_maps(evlist, cpus, NULL); 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci err = perf_evlist__open(evlist); 7262306a36Sopenharmony_ci __T("failed to open evlist", err == 0); 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci perf_evlist__for_each_evsel(evlist, evsel) { 7562306a36Sopenharmony_ci cpus = perf_evsel__cpus(evsel); 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci for (idx = 0; idx < perf_cpu_map__nr(cpus); idx++) { 7862306a36Sopenharmony_ci struct perf_counts_values counts = { .val = 0 }; 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci perf_evsel__read(evsel, idx, 0, &counts); 8162306a36Sopenharmony_ci __T("failed to read value for evsel", counts.val != 0); 8262306a36Sopenharmony_ci } 8362306a36Sopenharmony_ci } 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci perf_evlist__close(evlist); 8662306a36Sopenharmony_ci perf_evlist__delete(evlist); 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci perf_cpu_map__put(cpus); 8962306a36Sopenharmony_ci return 0; 9062306a36Sopenharmony_ci} 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_cistatic int test_stat_thread(void) 9362306a36Sopenharmony_ci{ 9462306a36Sopenharmony_ci struct perf_counts_values counts = { .val = 0 }; 9562306a36Sopenharmony_ci struct perf_thread_map *threads; 9662306a36Sopenharmony_ci struct perf_evlist *evlist; 9762306a36Sopenharmony_ci struct perf_evsel *evsel, *leader; 9862306a36Sopenharmony_ci struct perf_event_attr attr1 = { 9962306a36Sopenharmony_ci .type = PERF_TYPE_SOFTWARE, 10062306a36Sopenharmony_ci .config = PERF_COUNT_SW_CPU_CLOCK, 10162306a36Sopenharmony_ci }; 10262306a36Sopenharmony_ci struct perf_event_attr attr2 = { 10362306a36Sopenharmony_ci .type = PERF_TYPE_SOFTWARE, 10462306a36Sopenharmony_ci .config = PERF_COUNT_SW_TASK_CLOCK, 10562306a36Sopenharmony_ci }; 10662306a36Sopenharmony_ci int err; 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci threads = perf_thread_map__new_dummy(); 10962306a36Sopenharmony_ci __T("failed to create threads", threads); 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci perf_thread_map__set_pid(threads, 0, 0); 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci evlist = perf_evlist__new(); 11462306a36Sopenharmony_ci __T("failed to create evlist", evlist); 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci evsel = leader = perf_evsel__new(&attr1); 11762306a36Sopenharmony_ci __T("failed to create evsel1", evsel); 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci perf_evlist__add(evlist, evsel); 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci evsel = perf_evsel__new(&attr2); 12262306a36Sopenharmony_ci __T("failed to create evsel2", evsel); 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci perf_evlist__add(evlist, evsel); 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci perf_evlist__set_leader(evlist); 12762306a36Sopenharmony_ci __T("failed to set leader", leader->leader == leader); 12862306a36Sopenharmony_ci __T("failed to set leader", evsel->leader == leader); 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci perf_evlist__set_maps(evlist, NULL, threads); 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci err = perf_evlist__open(evlist); 13362306a36Sopenharmony_ci __T("failed to open evlist", err == 0); 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci perf_evlist__for_each_evsel(evlist, evsel) { 13662306a36Sopenharmony_ci perf_evsel__read(evsel, 0, 0, &counts); 13762306a36Sopenharmony_ci __T("failed to read value for evsel", counts.val != 0); 13862306a36Sopenharmony_ci } 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci perf_evlist__close(evlist); 14162306a36Sopenharmony_ci perf_evlist__delete(evlist); 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci perf_thread_map__put(threads); 14462306a36Sopenharmony_ci return 0; 14562306a36Sopenharmony_ci} 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_cistatic int test_stat_thread_enable(void) 14862306a36Sopenharmony_ci{ 14962306a36Sopenharmony_ci struct perf_counts_values counts = { .val = 0 }; 15062306a36Sopenharmony_ci struct perf_thread_map *threads; 15162306a36Sopenharmony_ci struct perf_evlist *evlist; 15262306a36Sopenharmony_ci struct perf_evsel *evsel, *leader; 15362306a36Sopenharmony_ci struct perf_event_attr attr1 = { 15462306a36Sopenharmony_ci .type = PERF_TYPE_SOFTWARE, 15562306a36Sopenharmony_ci .config = PERF_COUNT_SW_CPU_CLOCK, 15662306a36Sopenharmony_ci .disabled = 1, 15762306a36Sopenharmony_ci }; 15862306a36Sopenharmony_ci struct perf_event_attr attr2 = { 15962306a36Sopenharmony_ci .type = PERF_TYPE_SOFTWARE, 16062306a36Sopenharmony_ci .config = PERF_COUNT_SW_TASK_CLOCK, 16162306a36Sopenharmony_ci .disabled = 1, 16262306a36Sopenharmony_ci }; 16362306a36Sopenharmony_ci int err; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci threads = perf_thread_map__new_dummy(); 16662306a36Sopenharmony_ci __T("failed to create threads", threads); 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci perf_thread_map__set_pid(threads, 0, 0); 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci evlist = perf_evlist__new(); 17162306a36Sopenharmony_ci __T("failed to create evlist", evlist); 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci evsel = leader = perf_evsel__new(&attr1); 17462306a36Sopenharmony_ci __T("failed to create evsel1", evsel); 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci perf_evlist__add(evlist, evsel); 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci evsel = perf_evsel__new(&attr2); 17962306a36Sopenharmony_ci __T("failed to create evsel2", evsel); 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci perf_evlist__add(evlist, evsel); 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci perf_evlist__set_leader(evlist); 18462306a36Sopenharmony_ci __T("failed to set leader", leader->leader == leader); 18562306a36Sopenharmony_ci __T("failed to set leader", evsel->leader == leader); 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci perf_evlist__set_maps(evlist, NULL, threads); 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci err = perf_evlist__open(evlist); 19062306a36Sopenharmony_ci __T("failed to open evlist", err == 0); 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci perf_evlist__for_each_evsel(evlist, evsel) { 19362306a36Sopenharmony_ci perf_evsel__read(evsel, 0, 0, &counts); 19462306a36Sopenharmony_ci __T("failed to read value for evsel", counts.val == 0); 19562306a36Sopenharmony_ci } 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci perf_evlist__enable(evlist); 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci perf_evlist__for_each_evsel(evlist, evsel) { 20062306a36Sopenharmony_ci perf_evsel__read(evsel, 0, 0, &counts); 20162306a36Sopenharmony_ci __T("failed to read value for evsel", counts.val != 0); 20262306a36Sopenharmony_ci } 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci perf_evlist__disable(evlist); 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci perf_evlist__close(evlist); 20762306a36Sopenharmony_ci perf_evlist__delete(evlist); 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci perf_thread_map__put(threads); 21062306a36Sopenharmony_ci return 0; 21162306a36Sopenharmony_ci} 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_cistatic int test_mmap_thread(void) 21462306a36Sopenharmony_ci{ 21562306a36Sopenharmony_ci struct perf_evlist *evlist; 21662306a36Sopenharmony_ci struct perf_evsel *evsel; 21762306a36Sopenharmony_ci struct perf_mmap *map; 21862306a36Sopenharmony_ci struct perf_cpu_map *cpus; 21962306a36Sopenharmony_ci struct perf_thread_map *threads; 22062306a36Sopenharmony_ci struct perf_event_attr attr = { 22162306a36Sopenharmony_ci .type = PERF_TYPE_TRACEPOINT, 22262306a36Sopenharmony_ci .sample_period = 1, 22362306a36Sopenharmony_ci .wakeup_watermark = 1, 22462306a36Sopenharmony_ci .disabled = 1, 22562306a36Sopenharmony_ci }; 22662306a36Sopenharmony_ci char path[PATH_MAX]; 22762306a36Sopenharmony_ci int id, err, pid, go_pipe[2]; 22862306a36Sopenharmony_ci union perf_event *event; 22962306a36Sopenharmony_ci int count = 0; 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci snprintf(path, PATH_MAX, "%s/kernel/debug/tracing/events/syscalls/sys_enter_prctl/id", 23262306a36Sopenharmony_ci sysfs__mountpoint()); 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci if (filename__read_int(path, &id)) { 23562306a36Sopenharmony_ci tests_failed++; 23662306a36Sopenharmony_ci fprintf(stderr, "error: failed to get tracepoint id: %s\n", path); 23762306a36Sopenharmony_ci return -1; 23862306a36Sopenharmony_ci } 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci attr.config = id; 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci err = pipe(go_pipe); 24362306a36Sopenharmony_ci __T("failed to create pipe", err == 0); 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci fflush(NULL); 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci pid = fork(); 24862306a36Sopenharmony_ci if (!pid) { 24962306a36Sopenharmony_ci int i; 25062306a36Sopenharmony_ci char bf; 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci read(go_pipe[0], &bf, 1); 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci /* Generate 100 prctl calls. */ 25562306a36Sopenharmony_ci for (i = 0; i < 100; i++) 25662306a36Sopenharmony_ci prctl(0, 0, 0, 0, 0); 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci exit(0); 25962306a36Sopenharmony_ci } 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci threads = perf_thread_map__new_dummy(); 26262306a36Sopenharmony_ci __T("failed to create threads", threads); 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci cpus = perf_cpu_map__dummy_new(); 26562306a36Sopenharmony_ci __T("failed to create cpus", cpus); 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci perf_thread_map__set_pid(threads, 0, pid); 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci evlist = perf_evlist__new(); 27062306a36Sopenharmony_ci __T("failed to create evlist", evlist); 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci evsel = perf_evsel__new(&attr); 27362306a36Sopenharmony_ci __T("failed to create evsel1", evsel); 27462306a36Sopenharmony_ci __T("failed to set leader", evsel->leader == evsel); 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci perf_evlist__add(evlist, evsel); 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci perf_evlist__set_maps(evlist, cpus, threads); 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci err = perf_evlist__open(evlist); 28162306a36Sopenharmony_ci __T("failed to open evlist", err == 0); 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci err = perf_evlist__mmap(evlist, 4); 28462306a36Sopenharmony_ci __T("failed to mmap evlist", err == 0); 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci perf_evlist__enable(evlist); 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci /* kick the child and wait for it to finish */ 28962306a36Sopenharmony_ci write(go_pipe[1], "A", 1); 29062306a36Sopenharmony_ci waitpid(pid, NULL, 0); 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci /* 29362306a36Sopenharmony_ci * There's no need to call perf_evlist__disable, 29462306a36Sopenharmony_ci * monitored process is dead now. 29562306a36Sopenharmony_ci */ 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci perf_evlist__for_each_mmap(evlist, map, false) { 29862306a36Sopenharmony_ci if (perf_mmap__read_init(map) < 0) 29962306a36Sopenharmony_ci continue; 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci while ((event = perf_mmap__read_event(map)) != NULL) { 30262306a36Sopenharmony_ci count++; 30362306a36Sopenharmony_ci perf_mmap__consume(map); 30462306a36Sopenharmony_ci } 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci perf_mmap__read_done(map); 30762306a36Sopenharmony_ci } 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci /* calls perf_evlist__munmap/perf_evlist__close */ 31062306a36Sopenharmony_ci perf_evlist__delete(evlist); 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci perf_thread_map__put(threads); 31362306a36Sopenharmony_ci perf_cpu_map__put(cpus); 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci /* 31662306a36Sopenharmony_ci * The generated prctl calls should match the 31762306a36Sopenharmony_ci * number of events in the buffer. 31862306a36Sopenharmony_ci */ 31962306a36Sopenharmony_ci __T("failed count", count == 100); 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci return 0; 32262306a36Sopenharmony_ci} 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_cistatic int test_mmap_cpus(void) 32562306a36Sopenharmony_ci{ 32662306a36Sopenharmony_ci struct perf_evlist *evlist; 32762306a36Sopenharmony_ci struct perf_evsel *evsel; 32862306a36Sopenharmony_ci struct perf_mmap *map; 32962306a36Sopenharmony_ci struct perf_cpu_map *cpus; 33062306a36Sopenharmony_ci struct perf_event_attr attr = { 33162306a36Sopenharmony_ci .type = PERF_TYPE_TRACEPOINT, 33262306a36Sopenharmony_ci .sample_period = 1, 33362306a36Sopenharmony_ci .wakeup_watermark = 1, 33462306a36Sopenharmony_ci .disabled = 1, 33562306a36Sopenharmony_ci }; 33662306a36Sopenharmony_ci cpu_set_t saved_mask; 33762306a36Sopenharmony_ci char path[PATH_MAX]; 33862306a36Sopenharmony_ci int id, err, tmp; 33962306a36Sopenharmony_ci struct perf_cpu cpu; 34062306a36Sopenharmony_ci union perf_event *event; 34162306a36Sopenharmony_ci int count = 0; 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci snprintf(path, PATH_MAX, "%s/kernel/debug/tracing/events/syscalls/sys_enter_prctl/id", 34462306a36Sopenharmony_ci sysfs__mountpoint()); 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci if (filename__read_int(path, &id)) { 34762306a36Sopenharmony_ci fprintf(stderr, "error: failed to get tracepoint id: %s\n", path); 34862306a36Sopenharmony_ci return -1; 34962306a36Sopenharmony_ci } 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci attr.config = id; 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci cpus = perf_cpu_map__new(NULL); 35462306a36Sopenharmony_ci __T("failed to create cpus", cpus); 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci evlist = perf_evlist__new(); 35762306a36Sopenharmony_ci __T("failed to create evlist", evlist); 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci evsel = perf_evsel__new(&attr); 36062306a36Sopenharmony_ci __T("failed to create evsel1", evsel); 36162306a36Sopenharmony_ci __T("failed to set leader", evsel->leader == evsel); 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci perf_evlist__add(evlist, evsel); 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci perf_evlist__set_maps(evlist, cpus, NULL); 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci err = perf_evlist__open(evlist); 36862306a36Sopenharmony_ci __T("failed to open evlist", err == 0); 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci err = perf_evlist__mmap(evlist, 4); 37162306a36Sopenharmony_ci __T("failed to mmap evlist", err == 0); 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci perf_evlist__enable(evlist); 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci err = sched_getaffinity(0, sizeof(saved_mask), &saved_mask); 37662306a36Sopenharmony_ci __T("sched_getaffinity failed", err == 0); 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci perf_cpu_map__for_each_cpu(cpu, tmp, cpus) { 37962306a36Sopenharmony_ci cpu_set_t mask; 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci CPU_ZERO(&mask); 38262306a36Sopenharmony_ci CPU_SET(cpu.cpu, &mask); 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci err = sched_setaffinity(0, sizeof(mask), &mask); 38562306a36Sopenharmony_ci __T("sched_setaffinity failed", err == 0); 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci prctl(0, 0, 0, 0, 0); 38862306a36Sopenharmony_ci } 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci err = sched_setaffinity(0, sizeof(saved_mask), &saved_mask); 39162306a36Sopenharmony_ci __T("sched_setaffinity failed", err == 0); 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci perf_evlist__disable(evlist); 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci perf_evlist__for_each_mmap(evlist, map, false) { 39662306a36Sopenharmony_ci if (perf_mmap__read_init(map) < 0) 39762306a36Sopenharmony_ci continue; 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci while ((event = perf_mmap__read_event(map)) != NULL) { 40062306a36Sopenharmony_ci count++; 40162306a36Sopenharmony_ci perf_mmap__consume(map); 40262306a36Sopenharmony_ci } 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci perf_mmap__read_done(map); 40562306a36Sopenharmony_ci } 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci /* calls perf_evlist__munmap/perf_evlist__close */ 40862306a36Sopenharmony_ci perf_evlist__delete(evlist); 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci /* 41162306a36Sopenharmony_ci * The generated prctl events should match the 41262306a36Sopenharmony_ci * number of cpus or be bigger (we are system-wide). 41362306a36Sopenharmony_ci */ 41462306a36Sopenharmony_ci __T("failed count", count >= perf_cpu_map__nr(cpus)); 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci perf_cpu_map__put(cpus); 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci return 0; 41962306a36Sopenharmony_ci} 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_cistatic double display_error(long long average, 42262306a36Sopenharmony_ci long long high, 42362306a36Sopenharmony_ci long long low, 42462306a36Sopenharmony_ci long long expected) 42562306a36Sopenharmony_ci{ 42662306a36Sopenharmony_ci double error; 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci error = (((double)average - expected) / expected) * 100.0; 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci __T_VERBOSE(" Expected: %lld\n", expected); 43162306a36Sopenharmony_ci __T_VERBOSE(" High: %lld Low: %lld Average: %lld\n", 43262306a36Sopenharmony_ci high, low, average); 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci __T_VERBOSE(" Average Error = %.2f%%\n", error); 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci return error; 43762306a36Sopenharmony_ci} 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_cistatic int test_stat_multiplexing(void) 44062306a36Sopenharmony_ci{ 44162306a36Sopenharmony_ci struct perf_counts_values expected_counts = { .val = 0 }; 44262306a36Sopenharmony_ci struct perf_counts_values counts[EVENT_NUM] = {{ .val = 0 },}; 44362306a36Sopenharmony_ci struct perf_thread_map *threads; 44462306a36Sopenharmony_ci struct perf_evlist *evlist; 44562306a36Sopenharmony_ci struct perf_evsel *evsel; 44662306a36Sopenharmony_ci struct perf_event_attr attr = { 44762306a36Sopenharmony_ci .type = PERF_TYPE_HARDWARE, 44862306a36Sopenharmony_ci .config = PERF_COUNT_HW_INSTRUCTIONS, 44962306a36Sopenharmony_ci .read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 45062306a36Sopenharmony_ci PERF_FORMAT_TOTAL_TIME_RUNNING, 45162306a36Sopenharmony_ci .disabled = 1, 45262306a36Sopenharmony_ci }; 45362306a36Sopenharmony_ci int err, i, nonzero = 0; 45462306a36Sopenharmony_ci unsigned long count; 45562306a36Sopenharmony_ci long long max = 0, min = 0, avg = 0; 45662306a36Sopenharmony_ci double error = 0.0; 45762306a36Sopenharmony_ci s8 scaled = 0; 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_ci /* read for non-multiplexing event count */ 46062306a36Sopenharmony_ci threads = perf_thread_map__new_dummy(); 46162306a36Sopenharmony_ci __T("failed to create threads", threads); 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci perf_thread_map__set_pid(threads, 0, 0); 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci evsel = perf_evsel__new(&attr); 46662306a36Sopenharmony_ci __T("failed to create evsel", evsel); 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci err = perf_evsel__open(evsel, NULL, threads); 46962306a36Sopenharmony_ci __T("failed to open evsel", err == 0); 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci err = perf_evsel__enable(evsel); 47262306a36Sopenharmony_ci __T("failed to enable evsel", err == 0); 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci /* wait loop */ 47562306a36Sopenharmony_ci count = WAIT_COUNT; 47662306a36Sopenharmony_ci while (count--) 47762306a36Sopenharmony_ci ; 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci perf_evsel__read(evsel, 0, 0, &expected_counts); 48062306a36Sopenharmony_ci __T("failed to read value for evsel", expected_counts.val != 0); 48162306a36Sopenharmony_ci __T("failed to read non-multiplexing event count", 48262306a36Sopenharmony_ci expected_counts.ena == expected_counts.run); 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_ci err = perf_evsel__disable(evsel); 48562306a36Sopenharmony_ci __T("failed to enable evsel", err == 0); 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci perf_evsel__close(evsel); 48862306a36Sopenharmony_ci perf_evsel__delete(evsel); 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci perf_thread_map__put(threads); 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci /* read for multiplexing event count */ 49362306a36Sopenharmony_ci threads = perf_thread_map__new_dummy(); 49462306a36Sopenharmony_ci __T("failed to create threads", threads); 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_ci perf_thread_map__set_pid(threads, 0, 0); 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci evlist = perf_evlist__new(); 49962306a36Sopenharmony_ci __T("failed to create evlist", evlist); 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci for (i = 0; i < EVENT_NUM; i++) { 50262306a36Sopenharmony_ci evsel = perf_evsel__new(&attr); 50362306a36Sopenharmony_ci __T("failed to create evsel", evsel); 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_ci perf_evlist__add(evlist, evsel); 50662306a36Sopenharmony_ci } 50762306a36Sopenharmony_ci perf_evlist__set_maps(evlist, NULL, threads); 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci err = perf_evlist__open(evlist); 51062306a36Sopenharmony_ci __T("failed to open evlist", err == 0); 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci perf_evlist__enable(evlist); 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci /* wait loop */ 51562306a36Sopenharmony_ci count = WAIT_COUNT; 51662306a36Sopenharmony_ci while (count--) 51762306a36Sopenharmony_ci ; 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ci i = 0; 52062306a36Sopenharmony_ci perf_evlist__for_each_evsel(evlist, evsel) { 52162306a36Sopenharmony_ci perf_evsel__read(evsel, 0, 0, &counts[i]); 52262306a36Sopenharmony_ci __T("failed to read value for evsel", counts[i].val != 0); 52362306a36Sopenharmony_ci i++; 52462306a36Sopenharmony_ci } 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci perf_evlist__disable(evlist); 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ci min = counts[0].val; 52962306a36Sopenharmony_ci for (i = 0; i < EVENT_NUM; i++) { 53062306a36Sopenharmony_ci __T_VERBOSE("Event %2d -- Raw count = %" PRIu64 ", run = %" PRIu64 ", enable = %" PRIu64 "\n", 53162306a36Sopenharmony_ci i, counts[i].val, counts[i].run, counts[i].ena); 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci perf_counts_values__scale(&counts[i], true, &scaled); 53462306a36Sopenharmony_ci if (scaled == 1) { 53562306a36Sopenharmony_ci __T_VERBOSE("\t Scaled count = %" PRIu64 " (%.2lf%%, %" PRIu64 "/%" PRIu64 ")\n", 53662306a36Sopenharmony_ci counts[i].val, 53762306a36Sopenharmony_ci (double)counts[i].run / (double)counts[i].ena * 100.0, 53862306a36Sopenharmony_ci counts[i].run, counts[i].ena); 53962306a36Sopenharmony_ci } else if (scaled == -1) { 54062306a36Sopenharmony_ci __T_VERBOSE("\t Not Running\n"); 54162306a36Sopenharmony_ci } else { 54262306a36Sopenharmony_ci __T_VERBOSE("\t Not Scaling\n"); 54362306a36Sopenharmony_ci } 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci if (counts[i].val > max) 54662306a36Sopenharmony_ci max = counts[i].val; 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci if (counts[i].val < min) 54962306a36Sopenharmony_ci min = counts[i].val; 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ci avg += counts[i].val; 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci if (counts[i].val != 0) 55462306a36Sopenharmony_ci nonzero++; 55562306a36Sopenharmony_ci } 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_ci if (nonzero != 0) 55862306a36Sopenharmony_ci avg = avg / nonzero; 55962306a36Sopenharmony_ci else 56062306a36Sopenharmony_ci avg = 0; 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci error = display_error(avg, max, min, expected_counts.val); 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_ci __T("Error out of range!", ((error <= 1.0) && (error >= -1.0))); 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_ci perf_evlist__close(evlist); 56762306a36Sopenharmony_ci perf_evlist__delete(evlist); 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci perf_thread_map__put(threads); 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_ci return 0; 57262306a36Sopenharmony_ci} 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ciint test_evlist(int argc, char **argv) 57562306a36Sopenharmony_ci{ 57662306a36Sopenharmony_ci __T_START; 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_ci libperf_init(libperf_print); 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_ci test_stat_cpu(); 58162306a36Sopenharmony_ci test_stat_thread(); 58262306a36Sopenharmony_ci test_stat_thread_enable(); 58362306a36Sopenharmony_ci test_mmap_thread(); 58462306a36Sopenharmony_ci test_mmap_cpus(); 58562306a36Sopenharmony_ci test_stat_multiplexing(); 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_ci __T_END; 58862306a36Sopenharmony_ci return tests_failed == 0 ? 0 : -1; 58962306a36Sopenharmony_ci} 590