Linux Perf
event-times.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/compiler.h>
3 #include <errno.h>
4 #include <inttypes.h>
5 #include <string.h>
6 #include <sys/wait.h>
7 #include "tests.h"
8 #include "evlist.h"
9 #include "evsel.h"
10 #include "util.h"
11 #include "debug.h"
12 #include "thread_map.h"
13 #include "target.h"
14 
15 static int attach__enable_on_exec(struct perf_evlist *evlist)
16 {
17  struct perf_evsel *evsel = perf_evlist__last(evlist);
18  struct target target = {
19  .uid = UINT_MAX,
20  };
21  const char *argv[] = { "true", NULL, };
22  char sbuf[STRERR_BUFSIZE];
23  int err;
24 
25  pr_debug("attaching to spawned child, enable on exec\n");
26 
27  err = perf_evlist__create_maps(evlist, &target);
28  if (err < 0) {
29  pr_debug("Not enough memory to create thread/cpu maps\n");
30  return err;
31  }
32 
33  err = perf_evlist__prepare_workload(evlist, &target, argv, false, NULL);
34  if (err < 0) {
35  pr_debug("Couldn't run the workload!\n");
36  return err;
37  }
38 
39  evsel->attr.enable_on_exec = 1;
40 
41  err = perf_evlist__open(evlist);
42  if (err < 0) {
43  pr_debug("perf_evlist__open: %s\n",
44  str_error_r(errno, sbuf, sizeof(sbuf)));
45  return err;
46  }
47 
48  return perf_evlist__start_workload(evlist) == 1 ? TEST_OK : TEST_FAIL;
49 }
50 
51 static int detach__enable_on_exec(struct perf_evlist *evlist)
52 {
53  waitpid(evlist->workload.pid, NULL, 0);
54  return 0;
55 }
56 
57 static int attach__current_disabled(struct perf_evlist *evlist)
58 {
59  struct perf_evsel *evsel = perf_evlist__last(evlist);
60  struct thread_map *threads;
61  int err;
62 
63  pr_debug("attaching to current thread as disabled\n");
64 
65  threads = thread_map__new(-1, getpid(), UINT_MAX);
66  if (threads == NULL) {
67  pr_debug("thread_map__new\n");
68  return -1;
69  }
70 
71  evsel->attr.disabled = 1;
72 
73  err = perf_evsel__open_per_thread(evsel, threads);
74  if (err) {
75  pr_debug("Failed to open event cpu-clock:u\n");
76  return err;
77  }
78 
79  thread_map__put(threads);
80  return perf_evsel__enable(evsel) == 0 ? TEST_OK : TEST_FAIL;
81 }
82 
83 static int attach__current_enabled(struct perf_evlist *evlist)
84 {
85  struct perf_evsel *evsel = perf_evlist__last(evlist);
86  struct thread_map *threads;
87  int err;
88 
89  pr_debug("attaching to current thread as enabled\n");
90 
91  threads = thread_map__new(-1, getpid(), UINT_MAX);
92  if (threads == NULL) {
93  pr_debug("failed to call thread_map__new\n");
94  return -1;
95  }
96 
97  err = perf_evsel__open_per_thread(evsel, threads);
98 
99  thread_map__put(threads);
100  return err == 0 ? TEST_OK : TEST_FAIL;
101 }
102 
103 static int detach__disable(struct perf_evlist *evlist)
104 {
105  struct perf_evsel *evsel = perf_evlist__last(evlist);
106 
107  return perf_evsel__enable(evsel);
108 }
109 
111 {
112  struct perf_evsel *evsel = perf_evlist__last(evlist);
113  struct cpu_map *cpus;
114  int err;
115 
116  pr_debug("attaching to CPU 0 as enabled\n");
117 
118  cpus = cpu_map__new("0");
119  if (cpus == NULL) {
120  pr_debug("failed to call cpu_map__new\n");
121  return -1;
122  }
123 
124  evsel->attr.disabled = 1;
125 
126  err = perf_evsel__open_per_cpu(evsel, cpus);
127  if (err) {
128  if (err == -EACCES)
129  return TEST_SKIP;
130 
131  pr_debug("Failed to open event cpu-clock:u\n");
132  return err;
133  }
134 
135  cpu_map__put(cpus);
136  return perf_evsel__enable(evsel);
137 }
138 
139 static int attach__cpu_enabled(struct perf_evlist *evlist)
140 {
141  struct perf_evsel *evsel = perf_evlist__last(evlist);
142  struct cpu_map *cpus;
143  int err;
144 
145  pr_debug("attaching to CPU 0 as enabled\n");
146 
147  cpus = cpu_map__new("0");
148  if (cpus == NULL) {
149  pr_debug("failed to call cpu_map__new\n");
150  return -1;
151  }
152 
153  err = perf_evsel__open_per_cpu(evsel, cpus);
154  if (err == -EACCES)
155  return TEST_SKIP;
156 
157  cpu_map__put(cpus);
158  return err ? TEST_FAIL : TEST_OK;
159 }
160 
161 static int test_times(int (attach)(struct perf_evlist *),
162  int (detach)(struct perf_evlist *))
163 {
164  struct perf_counts_values count;
165  struct perf_evlist *evlist = NULL;
166  struct perf_evsel *evsel;
167  int err = -1, i;
168 
169  evlist = perf_evlist__new();
170  if (!evlist) {
171  pr_debug("failed to create event list\n");
172  goto out_err;
173  }
174 
175  err = parse_events(evlist, "cpu-clock:u", NULL);
176  if (err) {
177  pr_debug("failed to parse event cpu-clock:u\n");
178  goto out_err;
179  }
180 
181  evsel = perf_evlist__last(evlist);
182  evsel->attr.read_format |=
183  PERF_FORMAT_TOTAL_TIME_ENABLED |
184  PERF_FORMAT_TOTAL_TIME_RUNNING;
185 
186  err = attach(evlist);
187  if (err == TEST_SKIP) {
188  pr_debug(" SKIP : not enough rights\n");
189  return err;
190  }
191 
192  TEST_ASSERT_VAL("failed to attach", !err);
193 
194  for (i = 0; i < 100000000; i++) { }
195 
196  TEST_ASSERT_VAL("failed to detach", !detach(evlist));
197 
198  perf_evsel__read(evsel, 0, 0, &count);
199 
200  err = !(count.ena == count.run);
201 
202  pr_debug(" %s: ena %" PRIu64", run %" PRIu64"\n",
203  !err ? "OK " : "FAILED",
204  count.ena, count.run);
205 
206 out_err:
207  perf_evlist__delete(evlist);
208  return !err ? TEST_OK : TEST_FAIL;
209 }
210 
211 /*
212  * This test creates software event 'cpu-clock'
213  * attaches it in several ways (explained below)
214  * and checks that enabled and running times
215  * match.
216  */
217 int test__event_times(struct test *test __maybe_unused, int subtest __maybe_unused)
218 {
219  int err, ret = 0;
220 
221 #define _T(attach, detach) \
222  err = test_times(attach, detach); \
223  if (err && (ret == TEST_OK || ret == TEST_SKIP)) \
224  ret = err;
225 
226  /* attach on newly spawned process after exec */
228  /* attach on current process as enabled */
230  /* attach on current process as disabled */
232  /* attach on cpu as disabled */
234  /* attach on cpu as enabled */
236 
237 #undef _T
238  return ret;
239 }
int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *target, const char *argv[], bool pipe_output, void(*exec_error)(int signo, siginfo_t *info, void *ucontext))
Definition: evlist.c:1428
struct perf_evlist::@110 workload
int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)
Definition: evlist.c:1066
int int err
Definition: 5sec.c:44
static int detach__disable(struct perf_evlist *evlist)
Definition: event-times.c:103
#define TEST_ASSERT_VAL(text, cond)
Definition: tests.h:7
int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread, struct perf_counts_values *count)
Definition: evsel.c:1333
static int attach__cpu_disabled(struct perf_evlist *evlist)
Definition: event-times.c:110
void perf_evlist__delete(struct perf_evlist *evlist)
Definition: evlist.c:133
static int attach__enable_on_exec(struct perf_evlist *evlist)
Definition: event-times.c:15
Definition: cpumap.h:12
int perf_evlist__start_workload(struct perf_evlist *evlist)
Definition: evlist.c:1542
#define _T(attach, detach)
int parse_events(struct perf_evlist *evlist, const char *str, struct parse_events_error *err)
int perf_evsel__open_per_cpu(struct perf_evsel *evsel, struct cpu_map *cpus)
Definition: evsel.c:1957
void cpu_map__put(struct cpu_map *map)
Definition: cpumap.c:298
struct perf_evlist * evlist
Definition: evsel.h:92
#define pr_debug(fmt,...)
Definition: json.h:27
pid_t pid
Definition: evlist.h:42
static int attach__current_enabled(struct perf_evlist *evlist)
Definition: event-times.c:83
int perf_evlist__open(struct perf_evlist *evlist)
Definition: evlist.c:1398
int perf_evsel__open_per_thread(struct perf_evsel *evsel, struct thread_map *threads)
Definition: evsel.c:1963
static int attach__current_disabled(struct perf_evlist *evlist)
Definition: event-times.c:57
static int test_times(int(attach)(struct perf_evlist *), int(detach)(struct perf_evlist *))
Definition: event-times.c:161
static int attach__cpu_enabled(struct perf_evlist *evlist)
Definition: event-times.c:139
static int detach__enable_on_exec(struct perf_evlist *evlist)
Definition: event-times.c:51
list cpus
Definition: stat-cpi.py:7
static struct thread_data threads[THREADS]
uid_t uid
Definition: target.h:13
Definition: tests.h:30
int perf_evsel__enable(struct perf_evsel *evsel)
Definition: evsel.c:1175
#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_evlist__last(struct perf_evlist *evlist)
Definition: evlist.h:220
struct thread_map * thread_map__new(pid_t pid, pid_t tid, uid_t uid)
Definition: thread_map.c:192
int test__event_times(struct test *test __maybe_unused, int subtest __maybe_unused)
Definition: event-times.c:217
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
Definition: target.h:8
Definition: tests.h:25