Linux Perf
mmap-basic.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0
2 #include <errno.h>
3 #include <inttypes.h>
4 /* For the CLR_() macros */
5 #include <pthread.h>
6 
7 #include "evlist.h"
8 #include "evsel.h"
9 #include "thread_map.h"
10 #include "cpumap.h"
11 #include "tests.h"
12 #include <linux/err.h>
13 #include <linux/kernel.h>
14 
15 /*
16  * This test will generate random numbers of calls to some getpid syscalls,
17  * then establish an mmap for a group of events that are created to monitor
18  * the syscalls.
19  *
20  * It will receive the events, using mmap, use its PERF_SAMPLE_ID generated
21  * sample.id field to map back to its respective perf_evsel instance.
22  *
23  * Then it checks if the number of syscalls reported as perf events by
24  * the kernel corresponds to the number of syscalls made.
25  */
26 int test__basic_mmap(struct test *test __maybe_unused, int subtest __maybe_unused)
27 {
28  int err = -1;
29  union perf_event *event;
30  struct thread_map *threads;
31  struct cpu_map *cpus;
32  struct perf_evlist *evlist;
33  cpu_set_t cpu_set;
34  const char *syscall_names[] = { "getsid", "getppid", "getpgid", };
35  pid_t (*syscalls[])(void) = { (void *)getsid, getppid, (void*)getpgid };
36 #define nsyscalls ARRAY_SIZE(syscall_names)
37  unsigned int nr_events[nsyscalls],
38  expected_nr_events[nsyscalls], i, j;
39  struct perf_evsel *evsels[nsyscalls], *evsel;
40  char sbuf[STRERR_BUFSIZE];
41  struct perf_mmap *md;
42 
43  threads = thread_map__new(-1, getpid(), UINT_MAX);
44  if (threads == NULL) {
45  pr_debug("thread_map__new\n");
46  return -1;
47  }
48 
49  cpus = cpu_map__new(NULL);
50  if (cpus == NULL) {
51  pr_debug("cpu_map__new\n");
52  goto out_free_threads;
53  }
54 
55  CPU_ZERO(&cpu_set);
56  CPU_SET(cpus->map[0], &cpu_set);
57  sched_setaffinity(0, sizeof(cpu_set), &cpu_set);
58  if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) {
59  pr_debug("sched_setaffinity() failed on CPU %d: %s ",
60  cpus->map[0], str_error_r(errno, sbuf, sizeof(sbuf)));
61  goto out_free_cpus;
62  }
63 
64  evlist = perf_evlist__new();
65  if (evlist == NULL) {
66  pr_debug("perf_evlist__new\n");
67  goto out_free_cpus;
68  }
69 
70  perf_evlist__set_maps(evlist, cpus, threads);
71 
72  for (i = 0; i < nsyscalls; ++i) {
73  char name[64];
74 
75  snprintf(name, sizeof(name), "sys_enter_%s", syscall_names[i]);
76  evsels[i] = perf_evsel__newtp("syscalls", name);
77  if (IS_ERR(evsels[i])) {
78  pr_debug("perf_evsel__new(%s)\n", name);
79  goto out_delete_evlist;
80  }
81 
82  evsels[i]->attr.wakeup_events = 1;
83  perf_evsel__set_sample_id(evsels[i], false);
84 
85  perf_evlist__add(evlist, evsels[i]);
86 
87  if (perf_evsel__open(evsels[i], cpus, threads) < 0) {
88  pr_debug("failed to open counter: %s, "
89  "tweak /proc/sys/kernel/perf_event_paranoid?\n",
90  str_error_r(errno, sbuf, sizeof(sbuf)));
91  goto out_delete_evlist;
92  }
93 
94  nr_events[i] = 0;
95  expected_nr_events[i] = 1 + rand() % 127;
96  }
97 
98  if (perf_evlist__mmap(evlist, 128) < 0) {
99  pr_debug("failed to mmap events: %d (%s)\n", errno,
100  str_error_r(errno, sbuf, sizeof(sbuf)));
101  goto out_delete_evlist;
102  }
103 
104  for (i = 0; i < nsyscalls; ++i)
105  for (j = 0; j < expected_nr_events[i]; ++j) {
106  int foo = syscalls[i]();
107  ++foo;
108  }
109 
110  md = &evlist->mmap[0];
111  if (perf_mmap__read_init(md) < 0)
112  goto out_init;
113 
114  while ((event = perf_mmap__read_event(md)) != NULL) {
115  struct perf_sample sample;
116 
117  if (event->header.type != PERF_RECORD_SAMPLE) {
118  pr_debug("unexpected %s event\n",
119  perf_event__name(event->header.type));
120  goto out_delete_evlist;
121  }
122 
123  err = perf_evlist__parse_sample(evlist, event, &sample);
124  if (err) {
125  pr_err("Can't parse sample, err = %d\n", err);
126  goto out_delete_evlist;
127  }
128 
129  err = -1;
130  evsel = perf_evlist__id2evsel(evlist, sample.id);
131  if (evsel == NULL) {
132  pr_debug("event with id %" PRIu64
133  " doesn't map to an evsel\n", sample.id);
134  goto out_delete_evlist;
135  }
136  nr_events[evsel->idx]++;
137  perf_mmap__consume(md);
138  }
140 
141 out_init:
142  err = 0;
143  evlist__for_each_entry(evlist, evsel) {
144  if (nr_events[evsel->idx] != expected_nr_events[evsel->idx]) {
145  pr_debug("expected %d %s events, got %d\n",
146  expected_nr_events[evsel->idx],
147  perf_evsel__name(evsel), nr_events[evsel->idx]);
148  err = -1;
149  goto out_delete_evlist;
150  }
151  }
152 
153 out_delete_evlist:
154  perf_evlist__delete(evlist);
155  cpus = NULL;
156  threads = NULL;
157 out_free_cpus:
158  cpu_map__put(cpus);
159 out_free_threads:
160  thread_map__put(threads);
161  return err;
162 }
void perf_evlist__set_maps(struct perf_evlist *evlist, struct cpu_map *cpus, struct thread_map *threads)
Definition: evlist.c:1115
void perf_mmap__consume(struct perf_mmap *map)
Definition: mmap.c:118
int test__basic_mmap(struct test *test __maybe_unused, int subtest __maybe_unused)
Definition: mmap-basic.c:26
struct perf_mmap * mmap
Definition: evlist.h:45
int int err
Definition: 5sec.c:44
void perf_evlist__delete(struct perf_evlist *evlist)
Definition: evlist.c:133
Definition: cpumap.h:12
Definition: mmap.h:17
int idx
Definition: evsel.h:100
#define pr_err(fmt,...)
Definition: json.h:21
u64 id
Definition: event.h:196
void cpu_map__put(struct cpu_map *map)
Definition: cpumap.c:298
int perf_mmap__read_init(struct perf_mmap *map)
Definition: mmap.c:271
const char * name
#define nsyscalls
#define pr_debug(fmt,...)
Definition: json.h:27
#define evlist__for_each_entry(evlist, evsel)
Definition: evlist.h:247
int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event, struct perf_sample *sample)
Definition: evlist.c:1561
list cpus
Definition: stat-cpi.py:7
struct perf_evsel * perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id)
Definition: evlist.c:589
void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry)
Definition: evlist.c:176
#define event
const char * perf_event__name(unsigned int id)
Definition: event.c:75
int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages)
Definition: evlist.c:1061
int map[]
Definition: cpumap.h:15
const char * perf_evsel__name(struct perf_evsel *evsel)
Definition: evsel.c:577
static struct thread_data threads[THREADS]
void perf_mmap__read_done(struct perf_mmap *map)
Definition: mmap.c:329
struct perf_event_header header
Definition: event.h:624
int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, struct thread_map *threads)
Definition: evsel.c:1704
union perf_event * perf_mmap__read_event(struct perf_mmap *map)
Definition: mmap.c:78
Definition: tests.h:30
void perf_evsel__set_sample_id(struct perf_evsel *evsel, bool can_sample_identifier)
Definition: evsel.c:196
#define STRERR_BUFSIZE
Definition: debug.h:43
void thread_map__put(struct thread_map *map)
Definition: thread_map.c:361
static struct perf_evsel * perf_evsel__newtp(const char *sys, const char *name)
Definition: evsel.h:207
struct thread_map * thread_map__new(pid_t pid, pid_t tid, uid_t uid)
Definition: thread_map.c:192
struct cpu_map * cpu_map__new(const char *cpu_list)
Definition: cpumap.c:125
struct perf_evlist * perf_evlist__new(void)
Definition: evlist.c:54
struct perf_event_attr attr
Definition: evsel.h:93