18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci#include <linux/types.h> 38c2ecf20Sopenharmony_ci#include <limits.h> 48c2ecf20Sopenharmony_ci#include <unistd.h> 58c2ecf20Sopenharmony_ci#include <sys/prctl.h> 68c2ecf20Sopenharmony_ci#include <perf/cpumap.h> 78c2ecf20Sopenharmony_ci#include <perf/evlist.h> 88c2ecf20Sopenharmony_ci#include <perf/mmap.h> 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include "debug.h" 118c2ecf20Sopenharmony_ci#include "parse-events.h" 128c2ecf20Sopenharmony_ci#include "evlist.h" 138c2ecf20Sopenharmony_ci#include "evsel.h" 148c2ecf20Sopenharmony_ci#include "record.h" 158c2ecf20Sopenharmony_ci#include "thread_map.h" 168c2ecf20Sopenharmony_ci#include "tests.h" 178c2ecf20Sopenharmony_ci#include "util/mmap.h" 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#define CHECK__(x) { \ 208c2ecf20Sopenharmony_ci while ((x) < 0) { \ 218c2ecf20Sopenharmony_ci pr_debug(#x " failed!\n"); \ 228c2ecf20Sopenharmony_ci goto out_err; \ 238c2ecf20Sopenharmony_ci } \ 248c2ecf20Sopenharmony_ci} 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#define CHECK_NOT_NULL__(x) { \ 278c2ecf20Sopenharmony_ci while ((x) == NULL) { \ 288c2ecf20Sopenharmony_ci pr_debug(#x " failed!\n"); \ 298c2ecf20Sopenharmony_ci goto out_err; \ 308c2ecf20Sopenharmony_ci } \ 318c2ecf20Sopenharmony_ci} 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cistatic int find_comm(struct evlist *evlist, const char *comm) 348c2ecf20Sopenharmony_ci{ 358c2ecf20Sopenharmony_ci union perf_event *event; 368c2ecf20Sopenharmony_ci struct mmap *md; 378c2ecf20Sopenharmony_ci int i, found; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci found = 0; 408c2ecf20Sopenharmony_ci for (i = 0; i < evlist->core.nr_mmaps; i++) { 418c2ecf20Sopenharmony_ci md = &evlist->mmap[i]; 428c2ecf20Sopenharmony_ci if (perf_mmap__read_init(&md->core) < 0) 438c2ecf20Sopenharmony_ci continue; 448c2ecf20Sopenharmony_ci while ((event = perf_mmap__read_event(&md->core)) != NULL) { 458c2ecf20Sopenharmony_ci if (event->header.type == PERF_RECORD_COMM && 468c2ecf20Sopenharmony_ci (pid_t)event->comm.pid == getpid() && 478c2ecf20Sopenharmony_ci (pid_t)event->comm.tid == getpid() && 488c2ecf20Sopenharmony_ci strcmp(event->comm.comm, comm) == 0) 498c2ecf20Sopenharmony_ci found += 1; 508c2ecf20Sopenharmony_ci perf_mmap__consume(&md->core); 518c2ecf20Sopenharmony_ci } 528c2ecf20Sopenharmony_ci perf_mmap__read_done(&md->core); 538c2ecf20Sopenharmony_ci } 548c2ecf20Sopenharmony_ci return found; 558c2ecf20Sopenharmony_ci} 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci/** 588c2ecf20Sopenharmony_ci * test__keep_tracking - test using a dummy software event to keep tracking. 598c2ecf20Sopenharmony_ci * 608c2ecf20Sopenharmony_ci * This function implements a test that checks that tracking events continue 618c2ecf20Sopenharmony_ci * when an event is disabled but a dummy software event is not disabled. If the 628c2ecf20Sopenharmony_ci * test passes %0 is returned, otherwise %-1 is returned. 638c2ecf20Sopenharmony_ci */ 648c2ecf20Sopenharmony_ciint test__keep_tracking(struct test *test __maybe_unused, int subtest __maybe_unused) 658c2ecf20Sopenharmony_ci{ 668c2ecf20Sopenharmony_ci struct record_opts opts = { 678c2ecf20Sopenharmony_ci .mmap_pages = UINT_MAX, 688c2ecf20Sopenharmony_ci .user_freq = UINT_MAX, 698c2ecf20Sopenharmony_ci .user_interval = ULLONG_MAX, 708c2ecf20Sopenharmony_ci .target = { 718c2ecf20Sopenharmony_ci .uses_mmap = true, 728c2ecf20Sopenharmony_ci }, 738c2ecf20Sopenharmony_ci }; 748c2ecf20Sopenharmony_ci struct perf_thread_map *threads = NULL; 758c2ecf20Sopenharmony_ci struct perf_cpu_map *cpus = NULL; 768c2ecf20Sopenharmony_ci struct evlist *evlist = NULL; 778c2ecf20Sopenharmony_ci struct evsel *evsel = NULL; 788c2ecf20Sopenharmony_ci int found, err = -1; 798c2ecf20Sopenharmony_ci const char *comm; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci threads = thread_map__new(-1, getpid(), UINT_MAX); 828c2ecf20Sopenharmony_ci CHECK_NOT_NULL__(threads); 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci cpus = perf_cpu_map__new(NULL); 858c2ecf20Sopenharmony_ci CHECK_NOT_NULL__(cpus); 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci evlist = evlist__new(); 888c2ecf20Sopenharmony_ci CHECK_NOT_NULL__(evlist); 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci perf_evlist__set_maps(&evlist->core, cpus, threads); 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci CHECK__(parse_events(evlist, "dummy:u", NULL)); 938c2ecf20Sopenharmony_ci CHECK__(parse_events(evlist, "cycles:u", NULL)); 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci perf_evlist__config(evlist, &opts, NULL); 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci evsel = evlist__first(evlist); 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci evsel->core.attr.comm = 1; 1008c2ecf20Sopenharmony_ci evsel->core.attr.disabled = 1; 1018c2ecf20Sopenharmony_ci evsel->core.attr.enable_on_exec = 0; 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci if (evlist__open(evlist) < 0) { 1048c2ecf20Sopenharmony_ci pr_debug("Unable to open dummy and cycles event\n"); 1058c2ecf20Sopenharmony_ci err = TEST_SKIP; 1068c2ecf20Sopenharmony_ci goto out_err; 1078c2ecf20Sopenharmony_ci } 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci CHECK__(evlist__mmap(evlist, UINT_MAX)); 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci /* 1128c2ecf20Sopenharmony_ci * First, test that a 'comm' event can be found when the event is 1138c2ecf20Sopenharmony_ci * enabled. 1148c2ecf20Sopenharmony_ci */ 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci evlist__enable(evlist); 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci comm = "Test COMM 1"; 1198c2ecf20Sopenharmony_ci CHECK__(prctl(PR_SET_NAME, (unsigned long)comm, 0, 0, 0)); 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci evlist__disable(evlist); 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci found = find_comm(evlist, comm); 1248c2ecf20Sopenharmony_ci if (found != 1) { 1258c2ecf20Sopenharmony_ci pr_debug("First time, failed to find tracking event.\n"); 1268c2ecf20Sopenharmony_ci goto out_err; 1278c2ecf20Sopenharmony_ci } 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci /* 1308c2ecf20Sopenharmony_ci * Secondly, test that a 'comm' event can be found when the event is 1318c2ecf20Sopenharmony_ci * disabled with the dummy event still enabled. 1328c2ecf20Sopenharmony_ci */ 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci evlist__enable(evlist); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci evsel = evlist__last(evlist); 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci CHECK__(evsel__disable(evsel)); 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci comm = "Test COMM 2"; 1418c2ecf20Sopenharmony_ci CHECK__(prctl(PR_SET_NAME, (unsigned long)comm, 0, 0, 0)); 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci evlist__disable(evlist); 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci found = find_comm(evlist, comm); 1468c2ecf20Sopenharmony_ci if (found != 1) { 1478c2ecf20Sopenharmony_ci pr_debug("Second time, failed to find tracking event.\n"); 1488c2ecf20Sopenharmony_ci goto out_err; 1498c2ecf20Sopenharmony_ci } 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci err = 0; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ciout_err: 1548c2ecf20Sopenharmony_ci if (evlist) { 1558c2ecf20Sopenharmony_ci evlist__disable(evlist); 1568c2ecf20Sopenharmony_ci evlist__delete(evlist); 1578c2ecf20Sopenharmony_ci } else { 1588c2ecf20Sopenharmony_ci perf_cpu_map__put(cpus); 1598c2ecf20Sopenharmony_ci perf_thread_map__put(threads); 1608c2ecf20Sopenharmony_ci } 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci return err; 1638c2ecf20Sopenharmony_ci} 164