perf machine: Protect the machine->threads with a rwlock
[linux-2.6-block.git] / tools / perf / tests / hists_filter.c
CommitLineData
3c3cfd99
NK
1#include "perf.h"
2#include "util/debug.h"
3#include "util/symbol.h"
4#include "util/sort.h"
5#include "util/evsel.h"
6#include "util/evlist.h"
7#include "util/machine.h"
8#include "util/thread.h"
9#include "util/parse-events.h"
10#include "tests/tests.h"
11#include "tests/hists_common.h"
12
13struct sample {
14 u32 pid;
15 u64 ip;
16 struct thread *thread;
17 struct map *map;
18 struct symbol *sym;
19};
20
21/* For the numbers, see hists_common.c */
22static struct sample fake_samples[] = {
23 /* perf [kernel] schedule() */
a1891aa4 24 { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_KERNEL_SCHEDULE, },
3c3cfd99 25 /* perf [perf] main() */
a1891aa4 26 { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_PERF_MAIN, },
3c3cfd99 27 /* perf [libc] malloc() */
a1891aa4 28 { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_LIBC_MALLOC, },
3c3cfd99 29 /* perf [perf] main() */
a1891aa4 30 { .pid = FAKE_PID_PERF2, .ip = FAKE_IP_PERF_MAIN, }, /* will be merged */
3c3cfd99 31 /* perf [perf] cmd_record() */
a1891aa4 32 { .pid = FAKE_PID_PERF2, .ip = FAKE_IP_PERF_CMD_RECORD, },
3c3cfd99 33 /* perf [kernel] page_fault() */
a1891aa4 34 { .pid = FAKE_PID_PERF2, .ip = FAKE_IP_KERNEL_PAGE_FAULT, },
3c3cfd99 35 /* bash [bash] main() */
a1891aa4 36 { .pid = FAKE_PID_BASH, .ip = FAKE_IP_BASH_MAIN, },
3c3cfd99 37 /* bash [bash] xmalloc() */
a1891aa4 38 { .pid = FAKE_PID_BASH, .ip = FAKE_IP_BASH_XMALLOC, },
3c3cfd99 39 /* bash [libc] malloc() */
a1891aa4 40 { .pid = FAKE_PID_BASH, .ip = FAKE_IP_LIBC_MALLOC, },
3c3cfd99 41 /* bash [kernel] page_fault() */
a1891aa4 42 { .pid = FAKE_PID_BASH, .ip = FAKE_IP_KERNEL_PAGE_FAULT, },
3c3cfd99
NK
43};
44
69bcb019 45static int add_hist_entries(struct perf_evlist *evlist,
f498784c 46 struct machine *machine)
3c3cfd99
NK
47{
48 struct perf_evsel *evsel;
49 struct addr_location al;
a1891aa4 50 struct perf_sample sample = { .period = 100, };
3c3cfd99
NK
51 size_t i;
52
53 /*
54 * each evsel will have 10 samples but the 4th sample
55 * (perf [perf] main) will be collapsed to an existing entry
56 * so total 9 entries will be in the tree.
57 */
58 evlist__for_each(evlist, evsel) {
59 for (i = 0; i < ARRAY_SIZE(fake_samples); i++) {
60 const union perf_event event = {
61 .header = {
62 .misc = PERF_RECORD_MISC_USER,
63 },
64 };
69bcb019
NK
65 struct hist_entry_iter iter = {
66 .ops = &hist_iter_normal,
67 .hide_unresolved = false,
68 };
4ea062ed 69 struct hists *hists = evsel__hists(evsel);
3c3cfd99
NK
70
71 /* make sure it has no filter at first */
4ea062ed
ACM
72 hists->thread_filter = NULL;
73 hists->dso_filter = NULL;
74 hists->symbol_filter_str = NULL;
3c3cfd99
NK
75
76 sample.pid = fake_samples[i].pid;
13ce34df 77 sample.tid = fake_samples[i].pid;
3c3cfd99
NK
78 sample.ip = fake_samples[i].ip;
79
80 if (perf_event__preprocess_sample(&event, machine, &al,
81 &sample) < 0)
82 goto out;
83
69bcb019 84 if (hist_entry_iter__add(&iter, &al, evsel, &sample,
b91fc39f
ACM
85 PERF_MAX_STACK_DEPTH, NULL) < 0) {
86 addr_location__put(&al);
3c3cfd99 87 goto out;
b91fc39f 88 }
3c3cfd99
NK
89
90 fake_samples[i].thread = al.thread;
91 fake_samples[i].map = al.map;
92 fake_samples[i].sym = al.sym;
3c3cfd99
NK
93 }
94 }
95
96 return 0;
97
98out:
99 pr_debug("Not enough memory for adding a hist entry\n");
100 return TEST_FAIL;
101}
102
3c3cfd99
NK
103int test__hists_filter(void)
104{
105 int err = TEST_FAIL;
106 struct machines machines;
107 struct machine *machine;
108 struct perf_evsel *evsel;
109 struct perf_evlist *evlist = perf_evlist__new();
110
111 TEST_ASSERT_VAL("No memory", evlist);
112
b39b8393 113 err = parse_events(evlist, "cpu-clock", NULL);
3c3cfd99
NK
114 if (err)
115 goto out;
b39b8393 116 err = parse_events(evlist, "task-clock", NULL);
3c3cfd99
NK
117 if (err)
118 goto out;
119
120 /* default sort order (comm,dso,sym) will be used */
121 if (setup_sorting() < 0)
122 goto out;
123
124 machines__init(&machines);
125
126 /* setup threads/dso/map/symbols also */
127 machine = setup_fake_machine(&machines);
128 if (!machine)
129 goto out;
130
131 if (verbose > 1)
132 machine__fprintf(machine, stderr);
133
134 /* process sample events */
135 err = add_hist_entries(evlist, machine);
136 if (err < 0)
137 goto out;
138
139 evlist__for_each(evlist, evsel) {
4ea062ed 140 struct hists *hists = evsel__hists(evsel);
3c3cfd99
NK
141
142 hists__collapse_resort(hists, NULL);
740b97f9 143 hists__output_resort(hists, NULL);
3c3cfd99
NK
144
145 if (verbose > 2) {
146 pr_info("Normal histogram\n");
4e754e1c 147 print_hists_out(hists);
3c3cfd99
NK
148 }
149
150 TEST_ASSERT_VAL("Invalid nr samples",
151 hists->stats.nr_events[PERF_RECORD_SAMPLE] == 10);
152 TEST_ASSERT_VAL("Invalid nr hist entries",
153 hists->nr_entries == 9);
154 TEST_ASSERT_VAL("Invalid total period",
155 hists->stats.total_period == 1000);
156 TEST_ASSERT_VAL("Unmatched nr samples",
157 hists->stats.nr_events[PERF_RECORD_SAMPLE] ==
158 hists->stats.nr_non_filtered_samples);
159 TEST_ASSERT_VAL("Unmatched nr hist entries",
160 hists->nr_entries == hists->nr_non_filtered_entries);
161 TEST_ASSERT_VAL("Unmatched total period",
162 hists->stats.total_period ==
163 hists->stats.total_non_filtered_period);
164
165 /* now applying thread filter for 'bash' */
4ea062ed 166 hists->thread_filter = fake_samples[9].thread;
3c3cfd99
NK
167 hists__filter_by_thread(hists);
168
169 if (verbose > 2) {
170 pr_info("Histogram for thread filter\n");
4e754e1c 171 print_hists_out(hists);
3c3cfd99
NK
172 }
173
174 /* normal stats should be invariant */
175 TEST_ASSERT_VAL("Invalid nr samples",
176 hists->stats.nr_events[PERF_RECORD_SAMPLE] == 10);
177 TEST_ASSERT_VAL("Invalid nr hist entries",
178 hists->nr_entries == 9);
179 TEST_ASSERT_VAL("Invalid total period",
180 hists->stats.total_period == 1000);
181
182 /* but filter stats are changed */
183 TEST_ASSERT_VAL("Unmatched nr samples for thread filter",
184 hists->stats.nr_non_filtered_samples == 4);
185 TEST_ASSERT_VAL("Unmatched nr hist entries for thread filter",
186 hists->nr_non_filtered_entries == 4);
187 TEST_ASSERT_VAL("Unmatched total period for thread filter",
188 hists->stats.total_non_filtered_period == 400);
189
190 /* remove thread filter first */
4ea062ed 191 hists->thread_filter = NULL;
3c3cfd99
NK
192 hists__filter_by_thread(hists);
193
194 /* now applying dso filter for 'kernel' */
4ea062ed 195 hists->dso_filter = fake_samples[0].map->dso;
3c3cfd99
NK
196 hists__filter_by_dso(hists);
197
198 if (verbose > 2) {
199 pr_info("Histogram for dso filter\n");
4e754e1c 200 print_hists_out(hists);
3c3cfd99
NK
201 }
202
203 /* normal stats should be invariant */
204 TEST_ASSERT_VAL("Invalid nr samples",
205 hists->stats.nr_events[PERF_RECORD_SAMPLE] == 10);
206 TEST_ASSERT_VAL("Invalid nr hist entries",
207 hists->nr_entries == 9);
208 TEST_ASSERT_VAL("Invalid total period",
209 hists->stats.total_period == 1000);
210
211 /* but filter stats are changed */
212 TEST_ASSERT_VAL("Unmatched nr samples for dso filter",
213 hists->stats.nr_non_filtered_samples == 3);
214 TEST_ASSERT_VAL("Unmatched nr hist entries for dso filter",
215 hists->nr_non_filtered_entries == 3);
216 TEST_ASSERT_VAL("Unmatched total period for dso filter",
217 hists->stats.total_non_filtered_period == 300);
218
219 /* remove dso filter first */
4ea062ed 220 hists->dso_filter = NULL;
3c3cfd99
NK
221 hists__filter_by_dso(hists);
222
223 /*
224 * now applying symbol filter for 'main'. Also note that
225 * there's 3 samples that have 'main' symbol but the 4th
226 * entry of fake_samples was collapsed already so it won't
227 * be counted as a separate entry but the sample count and
228 * total period will be remained.
229 */
4ea062ed 230 hists->symbol_filter_str = "main";
3c3cfd99
NK
231 hists__filter_by_symbol(hists);
232
233 if (verbose > 2) {
234 pr_info("Histogram for symbol filter\n");
4e754e1c 235 print_hists_out(hists);
3c3cfd99
NK
236 }
237
238 /* normal stats should be invariant */
239 TEST_ASSERT_VAL("Invalid nr samples",
240 hists->stats.nr_events[PERF_RECORD_SAMPLE] == 10);
241 TEST_ASSERT_VAL("Invalid nr hist entries",
242 hists->nr_entries == 9);
243 TEST_ASSERT_VAL("Invalid total period",
244 hists->stats.total_period == 1000);
245
246 /* but filter stats are changed */
247 TEST_ASSERT_VAL("Unmatched nr samples for symbol filter",
248 hists->stats.nr_non_filtered_samples == 3);
249 TEST_ASSERT_VAL("Unmatched nr hist entries for symbol filter",
250 hists->nr_non_filtered_entries == 2);
251 TEST_ASSERT_VAL("Unmatched total period for symbol filter",
252 hists->stats.total_non_filtered_period == 300);
253
254 /* now applying all filters at once. */
4ea062ed
ACM
255 hists->thread_filter = fake_samples[1].thread;
256 hists->dso_filter = fake_samples[1].map->dso;
3c3cfd99
NK
257 hists__filter_by_thread(hists);
258 hists__filter_by_dso(hists);
259
260 if (verbose > 2) {
261 pr_info("Histogram for all filters\n");
4e754e1c 262 print_hists_out(hists);
3c3cfd99
NK
263 }
264
265 /* normal stats should be invariant */
266 TEST_ASSERT_VAL("Invalid nr samples",
267 hists->stats.nr_events[PERF_RECORD_SAMPLE] == 10);
268 TEST_ASSERT_VAL("Invalid nr hist entries",
269 hists->nr_entries == 9);
270 TEST_ASSERT_VAL("Invalid total period",
271 hists->stats.total_period == 1000);
272
273 /* but filter stats are changed */
274 TEST_ASSERT_VAL("Unmatched nr samples for all filter",
275 hists->stats.nr_non_filtered_samples == 2);
276 TEST_ASSERT_VAL("Unmatched nr hist entries for all filter",
277 hists->nr_non_filtered_entries == 1);
278 TEST_ASSERT_VAL("Unmatched total period for all filter",
279 hists->stats.total_non_filtered_period == 200);
280 }
281
282
283 err = TEST_OK;
284
285out:
286 /* tear down everything */
287 perf_evlist__delete(evlist);
f21d1815 288 reset_output_field();
3c3cfd99
NK
289 machines__exit(&machines);
290
291 return err;
292}