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