diff options
Diffstat (limited to 'tools')
41 files changed, 770 insertions, 305 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 952b5ece6740..d4da6929597f 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c | |||
@@ -36,7 +36,8 @@ | |||
36 | 36 | ||
37 | struct perf_annotate { | 37 | struct perf_annotate { |
38 | struct perf_tool tool; | 38 | struct perf_tool tool; |
39 | bool force, use_tui, use_stdio, use_gtk; | 39 | struct perf_session *session; |
40 | bool use_tui, use_stdio, use_gtk; | ||
40 | bool full_paths; | 41 | bool full_paths; |
41 | bool print_line; | 42 | bool print_line; |
42 | bool skip_missing; | 43 | bool skip_missing; |
@@ -188,18 +189,9 @@ find_next: | |||
188 | static int __cmd_annotate(struct perf_annotate *ann) | 189 | static int __cmd_annotate(struct perf_annotate *ann) |
189 | { | 190 | { |
190 | int ret; | 191 | int ret; |
191 | struct perf_session *session; | 192 | struct perf_session *session = ann->session; |
192 | struct perf_evsel *pos; | 193 | struct perf_evsel *pos; |
193 | u64 total_nr_samples; | 194 | u64 total_nr_samples; |
194 | struct perf_data_file file = { | ||
195 | .path = input_name, | ||
196 | .mode = PERF_DATA_MODE_READ, | ||
197 | .force = ann->force, | ||
198 | }; | ||
199 | |||
200 | session = perf_session__new(&file, false, &ann->tool); | ||
201 | if (session == NULL) | ||
202 | return -ENOMEM; | ||
203 | 195 | ||
204 | machines__set_symbol_filter(&session->machines, symbol__annotate_init); | 196 | machines__set_symbol_filter(&session->machines, symbol__annotate_init); |
205 | 197 | ||
@@ -207,22 +199,22 @@ static int __cmd_annotate(struct perf_annotate *ann) | |||
207 | ret = perf_session__cpu_bitmap(session, ann->cpu_list, | 199 | ret = perf_session__cpu_bitmap(session, ann->cpu_list, |
208 | ann->cpu_bitmap); | 200 | ann->cpu_bitmap); |
209 | if (ret) | 201 | if (ret) |
210 | goto out_delete; | 202 | goto out; |
211 | } | 203 | } |
212 | 204 | ||
213 | if (!objdump_path) { | 205 | if (!objdump_path) { |
214 | ret = perf_session_env__lookup_objdump(&session->header.env); | 206 | ret = perf_session_env__lookup_objdump(&session->header.env); |
215 | if (ret) | 207 | if (ret) |
216 | goto out_delete; | 208 | goto out; |
217 | } | 209 | } |
218 | 210 | ||
219 | ret = perf_session__process_events(session, &ann->tool); | 211 | ret = perf_session__process_events(session, &ann->tool); |
220 | if (ret) | 212 | if (ret) |
221 | goto out_delete; | 213 | goto out; |
222 | 214 | ||
223 | if (dump_trace) { | 215 | if (dump_trace) { |
224 | perf_session__fprintf_nr_events(session, stdout); | 216 | perf_session__fprintf_nr_events(session, stdout); |
225 | goto out_delete; | 217 | goto out; |
226 | } | 218 | } |
227 | 219 | ||
228 | if (verbose > 3) | 220 | if (verbose > 3) |
@@ -250,8 +242,8 @@ static int __cmd_annotate(struct perf_annotate *ann) | |||
250 | } | 242 | } |
251 | 243 | ||
252 | if (total_nr_samples == 0) { | 244 | if (total_nr_samples == 0) { |
253 | ui__error("The %s file has no samples!\n", file.path); | 245 | ui__error("The %s file has no samples!\n", session->file->path); |
254 | goto out_delete; | 246 | goto out; |
255 | } | 247 | } |
256 | 248 | ||
257 | if (use_browser == 2) { | 249 | if (use_browser == 2) { |
@@ -261,24 +253,12 @@ static int __cmd_annotate(struct perf_annotate *ann) | |||
261 | "perf_gtk__show_annotations"); | 253 | "perf_gtk__show_annotations"); |
262 | if (show_annotations == NULL) { | 254 | if (show_annotations == NULL) { |
263 | ui__error("GTK browser not found!\n"); | 255 | ui__error("GTK browser not found!\n"); |
264 | goto out_delete; | 256 | goto out; |
265 | } | 257 | } |
266 | show_annotations(); | 258 | show_annotations(); |
267 | } | 259 | } |
268 | 260 | ||
269 | out_delete: | 261 | out: |
270 | /* | ||
271 | * Speed up the exit process, for large files this can | ||
272 | * take quite a while. | ||
273 | * | ||
274 | * XXX Enable this when using valgrind or if we ever | ||
275 | * librarize this command. | ||
276 | * | ||
277 | * Also experiment with obstacks to see how much speed | ||
278 | * up we'll get here. | ||
279 | * | ||
280 | * perf_session__delete(session); | ||
281 | */ | ||
282 | return ret; | 262 | return ret; |
283 | } | 263 | } |
284 | 264 | ||
@@ -301,6 +281,10 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused) | |||
301 | .ordering_requires_timestamps = true, | 281 | .ordering_requires_timestamps = true, |
302 | }, | 282 | }, |
303 | }; | 283 | }; |
284 | struct perf_data_file file = { | ||
285 | .path = input_name, | ||
286 | .mode = PERF_DATA_MODE_READ, | ||
287 | }; | ||
304 | const struct option options[] = { | 288 | const struct option options[] = { |
305 | OPT_STRING('i', "input", &input_name, "file", | 289 | OPT_STRING('i', "input", &input_name, "file", |
306 | "input file name"), | 290 | "input file name"), |
@@ -308,7 +292,7 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused) | |||
308 | "only consider symbols in these dsos"), | 292 | "only consider symbols in these dsos"), |
309 | OPT_STRING('s', "symbol", &annotate.sym_hist_filter, "symbol", | 293 | OPT_STRING('s', "symbol", &annotate.sym_hist_filter, "symbol", |
310 | "symbol to annotate"), | 294 | "symbol to annotate"), |
311 | OPT_BOOLEAN('f', "force", &annotate.force, "don't complain, do it"), | 295 | OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"), |
312 | OPT_INCR('v', "verbose", &verbose, | 296 | OPT_INCR('v', "verbose", &verbose, |
313 | "be more verbose (show symbol address, etc)"), | 297 | "be more verbose (show symbol address, etc)"), |
314 | OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, | 298 | OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, |
@@ -341,6 +325,7 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused) | |||
341 | "Show event group information together"), | 325 | "Show event group information together"), |
342 | OPT_END() | 326 | OPT_END() |
343 | }; | 327 | }; |
328 | int ret; | ||
344 | 329 | ||
345 | argc = parse_options(argc, argv, options, annotate_usage, 0); | 330 | argc = parse_options(argc, argv, options, annotate_usage, 0); |
346 | 331 | ||
@@ -353,11 +338,16 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused) | |||
353 | 338 | ||
354 | setup_browser(true); | 339 | setup_browser(true); |
355 | 340 | ||
341 | annotate.session = perf_session__new(&file, false, &annotate.tool); | ||
342 | if (annotate.session == NULL) | ||
343 | return -ENOMEM; | ||
344 | |||
356 | symbol_conf.priv_size = sizeof(struct annotation); | 345 | symbol_conf.priv_size = sizeof(struct annotation); |
357 | symbol_conf.try_vmlinux_path = true; | 346 | symbol_conf.try_vmlinux_path = true; |
358 | 347 | ||
359 | if (symbol__init() < 0) | 348 | ret = symbol__init(&annotate.session->header.env); |
360 | return -1; | 349 | if (ret < 0) |
350 | goto out_delete; | ||
361 | 351 | ||
362 | if (setup_sorting() < 0) | 352 | if (setup_sorting() < 0) |
363 | usage_with_options(annotate_usage, options); | 353 | usage_with_options(annotate_usage, options); |
@@ -373,5 +363,20 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused) | |||
373 | annotate.sym_hist_filter = argv[0]; | 363 | annotate.sym_hist_filter = argv[0]; |
374 | } | 364 | } |
375 | 365 | ||
376 | return __cmd_annotate(&annotate); | 366 | ret = __cmd_annotate(&annotate); |
367 | |||
368 | out_delete: | ||
369 | /* | ||
370 | * Speed up the exit process, for large files this can | ||
371 | * take quite a while. | ||
372 | * | ||
373 | * XXX Enable this when using valgrind or if we ever | ||
374 | * librarize this command. | ||
375 | * | ||
376 | * Also experiment with obstacks to see how much speed | ||
377 | * up we'll get here. | ||
378 | * | ||
379 | * perf_session__delete(session); | ||
380 | */ | ||
381 | return ret; | ||
377 | } | 382 | } |
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c index 2a2c78f80876..ac5838e0b1bd 100644 --- a/tools/perf/builtin-buildid-cache.c +++ b/tools/perf/builtin-buildid-cache.c | |||
@@ -246,20 +246,9 @@ static bool dso__missing_buildid_cache(struct dso *dso, int parm __maybe_unused) | |||
246 | return true; | 246 | return true; |
247 | } | 247 | } |
248 | 248 | ||
249 | static int build_id_cache__fprintf_missing(const char *filename, bool force, FILE *fp) | 249 | static int build_id_cache__fprintf_missing(struct perf_session *session, FILE *fp) |
250 | { | 250 | { |
251 | struct perf_data_file file = { | ||
252 | .path = filename, | ||
253 | .mode = PERF_DATA_MODE_READ, | ||
254 | .force = force, | ||
255 | }; | ||
256 | struct perf_session *session = perf_session__new(&file, false, NULL); | ||
257 | if (session == NULL) | ||
258 | return -1; | ||
259 | |||
260 | perf_session__fprintf_dsos_buildid(session, fp, dso__missing_buildid_cache, 0); | 251 | perf_session__fprintf_dsos_buildid(session, fp, dso__missing_buildid_cache, 0); |
261 | perf_session__delete(session); | ||
262 | |||
263 | return 0; | 252 | return 0; |
264 | } | 253 | } |
265 | 254 | ||
@@ -303,6 +292,11 @@ int cmd_buildid_cache(int argc, const char **argv, | |||
303 | *update_name_list_str = NULL, | 292 | *update_name_list_str = NULL, |
304 | *kcore_filename; | 293 | *kcore_filename; |
305 | 294 | ||
295 | struct perf_data_file file = { | ||
296 | .mode = PERF_DATA_MODE_READ, | ||
297 | }; | ||
298 | struct perf_session *session = NULL; | ||
299 | |||
306 | const struct option buildid_cache_options[] = { | 300 | const struct option buildid_cache_options[] = { |
307 | OPT_STRING('a', "add", &add_name_list_str, | 301 | OPT_STRING('a', "add", &add_name_list_str, |
308 | "file list", "file(s) to add"), | 302 | "file list", "file(s) to add"), |
@@ -326,8 +320,17 @@ int cmd_buildid_cache(int argc, const char **argv, | |||
326 | argc = parse_options(argc, argv, buildid_cache_options, | 320 | argc = parse_options(argc, argv, buildid_cache_options, |
327 | buildid_cache_usage, 0); | 321 | buildid_cache_usage, 0); |
328 | 322 | ||
329 | if (symbol__init() < 0) | 323 | if (missing_filename) { |
330 | return -1; | 324 | file.path = missing_filename; |
325 | file.force = force; | ||
326 | |||
327 | session = perf_session__new(&file, false, NULL); | ||
328 | if (session == NULL) | ||
329 | return -1; | ||
330 | } | ||
331 | |||
332 | if (symbol__init(session ? &session->header.env : NULL) < 0) | ||
333 | goto out; | ||
331 | 334 | ||
332 | setup_pager(); | 335 | setup_pager(); |
333 | 336 | ||
@@ -370,7 +373,7 @@ int cmd_buildid_cache(int argc, const char **argv, | |||
370 | } | 373 | } |
371 | 374 | ||
372 | if (missing_filename) | 375 | if (missing_filename) |
373 | ret = build_id_cache__fprintf_missing(missing_filename, force, stdout); | 376 | ret = build_id_cache__fprintf_missing(session, stdout); |
374 | 377 | ||
375 | if (update_name_list_str) { | 378 | if (update_name_list_str) { |
376 | list = strlist__new(true, update_name_list_str); | 379 | list = strlist__new(true, update_name_list_str); |
@@ -394,5 +397,9 @@ int cmd_buildid_cache(int argc, const char **argv, | |||
394 | build_id_cache__add_kcore(kcore_filename, debugdir, force)) | 397 | build_id_cache__add_kcore(kcore_filename, debugdir, force)) |
395 | pr_warning("Couldn't add %s\n", kcore_filename); | 398 | pr_warning("Couldn't add %s\n", kcore_filename); |
396 | 399 | ||
400 | out: | ||
401 | if (session) | ||
402 | perf_session__delete(session); | ||
403 | |||
397 | return ret; | 404 | return ret; |
398 | } | 405 | } |
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index c10cc44bae19..190d0b6b28cc 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c | |||
@@ -1143,7 +1143,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1143 | 1143 | ||
1144 | argc = parse_options(argc, argv, options, diff_usage, 0); | 1144 | argc = parse_options(argc, argv, options, diff_usage, 0); |
1145 | 1145 | ||
1146 | if (symbol__init() < 0) | 1146 | if (symbol__init(NULL) < 0) |
1147 | return -1; | 1147 | return -1; |
1148 | 1148 | ||
1149 | if (data_init(argc, argv) < 0) | 1149 | if (data_init(argc, argv) < 0) |
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index ee875cca13b1..3a62b6b3c8fd 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c | |||
@@ -23,6 +23,7 @@ | |||
23 | 23 | ||
24 | struct perf_inject { | 24 | struct perf_inject { |
25 | struct perf_tool tool; | 25 | struct perf_tool tool; |
26 | struct perf_session *session; | ||
26 | bool build_ids; | 27 | bool build_ids; |
27 | bool sched_stat; | 28 | bool sched_stat; |
28 | const char *input_name; | 29 | const char *input_name; |
@@ -340,12 +341,8 @@ static int perf_evsel__check_stype(struct perf_evsel *evsel, | |||
340 | 341 | ||
341 | static int __cmd_inject(struct perf_inject *inject) | 342 | static int __cmd_inject(struct perf_inject *inject) |
342 | { | 343 | { |
343 | struct perf_session *session; | ||
344 | int ret = -EINVAL; | 344 | int ret = -EINVAL; |
345 | struct perf_data_file file = { | 345 | struct perf_session *session = inject->session; |
346 | .path = inject->input_name, | ||
347 | .mode = PERF_DATA_MODE_READ, | ||
348 | }; | ||
349 | struct perf_data_file *file_out = &inject->output; | 346 | struct perf_data_file *file_out = &inject->output; |
350 | 347 | ||
351 | signal(SIGINT, sig_handler); | 348 | signal(SIGINT, sig_handler); |
@@ -357,10 +354,6 @@ static int __cmd_inject(struct perf_inject *inject) | |||
357 | inject->tool.tracing_data = perf_event__repipe_tracing_data; | 354 | inject->tool.tracing_data = perf_event__repipe_tracing_data; |
358 | } | 355 | } |
359 | 356 | ||
360 | session = perf_session__new(&file, true, &inject->tool); | ||
361 | if (session == NULL) | ||
362 | return -ENOMEM; | ||
363 | |||
364 | if (inject->build_ids) { | 357 | if (inject->build_ids) { |
365 | inject->tool.sample = perf_event__inject_buildid; | 358 | inject->tool.sample = perf_event__inject_buildid; |
366 | } else if (inject->sched_stat) { | 359 | } else if (inject->sched_stat) { |
@@ -396,8 +389,6 @@ static int __cmd_inject(struct perf_inject *inject) | |||
396 | perf_session__write_header(session, session->evlist, file_out->fd, true); | 389 | perf_session__write_header(session, session->evlist, file_out->fd, true); |
397 | } | 390 | } |
398 | 391 | ||
399 | perf_session__delete(session); | ||
400 | |||
401 | return ret; | 392 | return ret; |
402 | } | 393 | } |
403 | 394 | ||
@@ -427,6 +418,11 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) | |||
427 | .mode = PERF_DATA_MODE_WRITE, | 418 | .mode = PERF_DATA_MODE_WRITE, |
428 | }, | 419 | }, |
429 | }; | 420 | }; |
421 | struct perf_data_file file = { | ||
422 | .mode = PERF_DATA_MODE_READ, | ||
423 | }; | ||
424 | int ret; | ||
425 | |||
430 | const struct option options[] = { | 426 | const struct option options[] = { |
431 | OPT_BOOLEAN('b', "build-ids", &inject.build_ids, | 427 | OPT_BOOLEAN('b', "build-ids", &inject.build_ids, |
432 | "Inject build-ids into the output stream"), | 428 | "Inject build-ids into the output stream"), |
@@ -461,8 +457,17 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) | |||
461 | return -1; | 457 | return -1; |
462 | } | 458 | } |
463 | 459 | ||
464 | if (symbol__init() < 0) | 460 | file.path = inject.input_name; |
461 | inject.session = perf_session__new(&file, true, &inject.tool); | ||
462 | if (inject.session == NULL) | ||
463 | return -ENOMEM; | ||
464 | |||
465 | if (symbol__init(&inject.session->header.env) < 0) | ||
465 | return -1; | 466 | return -1; |
466 | 467 | ||
467 | return __cmd_inject(&inject); | 468 | ret = __cmd_inject(&inject); |
469 | |||
470 | perf_session__delete(inject.session); | ||
471 | |||
472 | return ret; | ||
468 | } | 473 | } |
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index 84b82397a28e..23762187a219 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c | |||
@@ -405,10 +405,9 @@ static void sort_result(void) | |||
405 | __sort_result(&root_caller_stat, &root_caller_sorted, &caller_sort); | 405 | __sort_result(&root_caller_stat, &root_caller_sorted, &caller_sort); |
406 | } | 406 | } |
407 | 407 | ||
408 | static int __cmd_kmem(void) | 408 | static int __cmd_kmem(struct perf_session *session) |
409 | { | 409 | { |
410 | int err = -EINVAL; | 410 | int err = -EINVAL; |
411 | struct perf_session *session; | ||
412 | const struct perf_evsel_str_handler kmem_tracepoints[] = { | 411 | const struct perf_evsel_str_handler kmem_tracepoints[] = { |
413 | { "kmem:kmalloc", perf_evsel__process_alloc_event, }, | 412 | { "kmem:kmalloc", perf_evsel__process_alloc_event, }, |
414 | { "kmem:kmem_cache_alloc", perf_evsel__process_alloc_event, }, | 413 | { "kmem:kmem_cache_alloc", perf_evsel__process_alloc_event, }, |
@@ -417,31 +416,22 @@ static int __cmd_kmem(void) | |||
417 | { "kmem:kfree", perf_evsel__process_free_event, }, | 416 | { "kmem:kfree", perf_evsel__process_free_event, }, |
418 | { "kmem:kmem_cache_free", perf_evsel__process_free_event, }, | 417 | { "kmem:kmem_cache_free", perf_evsel__process_free_event, }, |
419 | }; | 418 | }; |
420 | struct perf_data_file file = { | ||
421 | .path = input_name, | ||
422 | .mode = PERF_DATA_MODE_READ, | ||
423 | }; | ||
424 | |||
425 | session = perf_session__new(&file, false, &perf_kmem); | ||
426 | if (session == NULL) | ||
427 | return -ENOMEM; | ||
428 | 419 | ||
429 | if (!perf_session__has_traces(session, "kmem record")) | 420 | if (!perf_session__has_traces(session, "kmem record")) |
430 | goto out_delete; | 421 | goto out; |
431 | 422 | ||
432 | if (perf_session__set_tracepoints_handlers(session, kmem_tracepoints)) { | 423 | if (perf_session__set_tracepoints_handlers(session, kmem_tracepoints)) { |
433 | pr_err("Initializing perf session tracepoint handlers failed\n"); | 424 | pr_err("Initializing perf session tracepoint handlers failed\n"); |
434 | return -1; | 425 | goto out; |
435 | } | 426 | } |
436 | 427 | ||
437 | setup_pager(); | 428 | setup_pager(); |
438 | err = perf_session__process_events(session, &perf_kmem); | 429 | err = perf_session__process_events(session, &perf_kmem); |
439 | if (err != 0) | 430 | if (err != 0) |
440 | goto out_delete; | 431 | goto out; |
441 | sort_result(); | 432 | sort_result(); |
442 | print_result(session); | 433 | print_result(session); |
443 | out_delete: | 434 | out: |
444 | perf_session__delete(session); | ||
445 | return err; | 435 | return err; |
446 | } | 436 | } |
447 | 437 | ||
@@ -688,29 +678,46 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused) | |||
688 | NULL, | 678 | NULL, |
689 | NULL | 679 | NULL |
690 | }; | 680 | }; |
681 | struct perf_session *session; | ||
682 | struct perf_data_file file = { | ||
683 | .path = input_name, | ||
684 | .mode = PERF_DATA_MODE_READ, | ||
685 | }; | ||
686 | int ret = -1; | ||
687 | |||
691 | argc = parse_options_subcommand(argc, argv, kmem_options, | 688 | argc = parse_options_subcommand(argc, argv, kmem_options, |
692 | kmem_subcommands, kmem_usage, 0); | 689 | kmem_subcommands, kmem_usage, 0); |
693 | 690 | ||
694 | if (!argc) | 691 | if (!argc) |
695 | usage_with_options(kmem_usage, kmem_options); | 692 | usage_with_options(kmem_usage, kmem_options); |
696 | 693 | ||
697 | symbol__init(); | ||
698 | |||
699 | if (!strncmp(argv[0], "rec", 3)) { | 694 | if (!strncmp(argv[0], "rec", 3)) { |
695 | symbol__init(NULL); | ||
700 | return __cmd_record(argc, argv); | 696 | return __cmd_record(argc, argv); |
701 | } else if (!strcmp(argv[0], "stat")) { | 697 | } |
698 | |||
699 | session = perf_session__new(&file, false, &perf_kmem); | ||
700 | if (session == NULL) | ||
701 | return -ENOMEM; | ||
702 | |||
703 | symbol__init(&session->header.env); | ||
704 | |||
705 | if (!strcmp(argv[0], "stat")) { | ||
702 | if (cpu__setup_cpunode_map()) | 706 | if (cpu__setup_cpunode_map()) |
703 | return -1; | 707 | goto out_delete; |
704 | 708 | ||
705 | if (list_empty(&caller_sort)) | 709 | if (list_empty(&caller_sort)) |
706 | setup_sorting(&caller_sort, default_sort_order); | 710 | setup_sorting(&caller_sort, default_sort_order); |
707 | if (list_empty(&alloc_sort)) | 711 | if (list_empty(&alloc_sort)) |
708 | setup_sorting(&alloc_sort, default_sort_order); | 712 | setup_sorting(&alloc_sort, default_sort_order); |
709 | 713 | ||
710 | return __cmd_kmem(); | 714 | ret = __cmd_kmem(session); |
711 | } else | 715 | } else |
712 | usage_with_options(kmem_usage, kmem_options); | 716 | usage_with_options(kmem_usage, kmem_options); |
713 | 717 | ||
714 | return 0; | 718 | out_delete: |
719 | perf_session__delete(session); | ||
720 | |||
721 | return ret; | ||
715 | } | 722 | } |
716 | 723 | ||
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index 7ccceadcd9f8..14d03edc81c2 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c | |||
@@ -885,15 +885,11 @@ static int fd_set_nonblock(int fd) | |||
885 | return 0; | 885 | return 0; |
886 | } | 886 | } |
887 | 887 | ||
888 | static | 888 | static int perf_kvm__handle_stdin(void) |
889 | int perf_kvm__handle_stdin(struct termios *tc_now, struct termios *tc_save) | ||
890 | { | 889 | { |
891 | int c; | 890 | int c; |
892 | 891 | ||
893 | tcsetattr(0, TCSANOW, tc_now); | ||
894 | c = getc(stdin); | 892 | c = getc(stdin); |
895 | tcsetattr(0, TCSAFLUSH, tc_save); | ||
896 | |||
897 | if (c == 'q') | 893 | if (c == 'q') |
898 | return 1; | 894 | return 1; |
899 | 895 | ||
@@ -904,7 +900,7 @@ static int kvm_events_live_report(struct perf_kvm_stat *kvm) | |||
904 | { | 900 | { |
905 | struct pollfd *pollfds = NULL; | 901 | struct pollfd *pollfds = NULL; |
906 | int nr_fds, nr_stdin, ret, err = -EINVAL; | 902 | int nr_fds, nr_stdin, ret, err = -EINVAL; |
907 | struct termios tc, save; | 903 | struct termios save; |
908 | 904 | ||
909 | /* live flag must be set first */ | 905 | /* live flag must be set first */ |
910 | kvm->live = true; | 906 | kvm->live = true; |
@@ -919,14 +915,9 @@ static int kvm_events_live_report(struct perf_kvm_stat *kvm) | |||
919 | goto out; | 915 | goto out; |
920 | } | 916 | } |
921 | 917 | ||
918 | set_term_quiet_input(&save); | ||
922 | init_kvm_event_record(kvm); | 919 | init_kvm_event_record(kvm); |
923 | 920 | ||
924 | tcgetattr(0, &save); | ||
925 | tc = save; | ||
926 | tc.c_lflag &= ~(ICANON | ECHO); | ||
927 | tc.c_cc[VMIN] = 0; | ||
928 | tc.c_cc[VTIME] = 0; | ||
929 | |||
930 | signal(SIGINT, sig_handler); | 921 | signal(SIGINT, sig_handler); |
931 | signal(SIGTERM, sig_handler); | 922 | signal(SIGTERM, sig_handler); |
932 | 923 | ||
@@ -972,7 +963,7 @@ static int kvm_events_live_report(struct perf_kvm_stat *kvm) | |||
972 | goto out; | 963 | goto out; |
973 | 964 | ||
974 | if (pollfds[nr_stdin].revents & POLLIN) | 965 | if (pollfds[nr_stdin].revents & POLLIN) |
975 | done = perf_kvm__handle_stdin(&tc, &save); | 966 | done = perf_kvm__handle_stdin(); |
976 | 967 | ||
977 | if (!rc && !done) | 968 | if (!rc && !done) |
978 | err = poll(pollfds, nr_fds, 100); | 969 | err = poll(pollfds, nr_fds, 100); |
@@ -989,6 +980,7 @@ out: | |||
989 | if (kvm->timerfd >= 0) | 980 | if (kvm->timerfd >= 0) |
990 | close(kvm->timerfd); | 981 | close(kvm->timerfd); |
991 | 982 | ||
983 | tcsetattr(0, TCSAFLUSH, &save); | ||
992 | free(pollfds); | 984 | free(pollfds); |
993 | return err; | 985 | return err; |
994 | } | 986 | } |
@@ -1072,6 +1064,8 @@ static int read_events(struct perf_kvm_stat *kvm) | |||
1072 | return -EINVAL; | 1064 | return -EINVAL; |
1073 | } | 1065 | } |
1074 | 1066 | ||
1067 | symbol__init(&kvm->session->header.env); | ||
1068 | |||
1075 | if (!perf_session__has_traces(kvm->session, "kvm record")) | 1069 | if (!perf_session__has_traces(kvm->session, "kvm record")) |
1076 | return -EINVAL; | 1070 | return -EINVAL; |
1077 | 1071 | ||
@@ -1201,8 +1195,6 @@ kvm_events_report(struct perf_kvm_stat *kvm, int argc, const char **argv) | |||
1201 | NULL | 1195 | NULL |
1202 | }; | 1196 | }; |
1203 | 1197 | ||
1204 | symbol__init(); | ||
1205 | |||
1206 | if (argc) { | 1198 | if (argc) { |
1207 | argc = parse_options(argc, argv, | 1199 | argc = parse_options(argc, argv, |
1208 | kvm_events_report_options, | 1200 | kvm_events_report_options, |
@@ -1322,7 +1314,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm, | |||
1322 | kvm->opts.target.uid_str = NULL; | 1314 | kvm->opts.target.uid_str = NULL; |
1323 | kvm->opts.target.uid = UINT_MAX; | 1315 | kvm->opts.target.uid = UINT_MAX; |
1324 | 1316 | ||
1325 | symbol__init(); | 1317 | symbol__init(NULL); |
1326 | disable_buildid_cache(); | 1318 | disable_buildid_cache(); |
1327 | 1319 | ||
1328 | use_browser = 0; | 1320 | use_browser = 0; |
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c index c8122d323621..92790ed7af45 100644 --- a/tools/perf/builtin-lock.c +++ b/tools/perf/builtin-lock.c | |||
@@ -865,6 +865,8 @@ static int __cmd_report(bool display_info) | |||
865 | return -ENOMEM; | 865 | return -ENOMEM; |
866 | } | 866 | } |
867 | 867 | ||
868 | symbol__init(&session->header.env); | ||
869 | |||
868 | if (!perf_session__has_traces(session, "lock record")) | 870 | if (!perf_session__has_traces(session, "lock record")) |
869 | goto out_delete; | 871 | goto out_delete; |
870 | 872 | ||
@@ -974,7 +976,6 @@ int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused) | |||
974 | unsigned int i; | 976 | unsigned int i; |
975 | int rc = 0; | 977 | int rc = 0; |
976 | 978 | ||
977 | symbol__init(); | ||
978 | for (i = 0; i < LOCKHASH_SIZE; i++) | 979 | for (i = 0; i < LOCKHASH_SIZE; i++) |
979 | INIT_LIST_HEAD(lockhash_table + i); | 980 | INIT_LIST_HEAD(lockhash_table + i); |
980 | 981 | ||
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c index 80e57c84adef..8b4a87fe3858 100644 --- a/tools/perf/builtin-mem.c +++ b/tools/perf/builtin-mem.c | |||
@@ -133,7 +133,7 @@ static int report_raw_events(struct perf_mem *mem) | |||
133 | goto out_delete; | 133 | goto out_delete; |
134 | } | 134 | } |
135 | 135 | ||
136 | if (symbol__init() < 0) | 136 | if (symbol__init(&session->header.env) < 0) |
137 | return -1; | 137 | return -1; |
138 | 138 | ||
139 | printf("# PID, TID, IP, ADDR, LOCAL WEIGHT, DSRC, SYMBOL\n"); | 139 | printf("# PID, TID, IP, ADDR, LOCAL WEIGHT, DSRC, SYMBOL\n"); |
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index ca0251e8470d..4db670d4b8da 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
@@ -908,7 +908,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) | |||
908 | usage_with_options(record_usage, record_options); | 908 | usage_with_options(record_usage, record_options); |
909 | } | 909 | } |
910 | 910 | ||
911 | symbol__init(); | 911 | symbol__init(NULL); |
912 | 912 | ||
913 | if (symbol_conf.kptr_restrict) | 913 | if (symbol_conf.kptr_restrict) |
914 | pr_warning( | 914 | pr_warning( |
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 041e93da13e4..3da59a87ec7c 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
@@ -730,7 +730,7 @@ repeat: | |||
730 | has_br_stack = perf_header__has_feat(&session->header, | 730 | has_br_stack = perf_header__has_feat(&session->header, |
731 | HEADER_BRANCH_STACK); | 731 | HEADER_BRANCH_STACK); |
732 | 732 | ||
733 | if (branch_mode == -1 && has_br_stack) { | 733 | if ((branch_mode == -1 && has_br_stack) || branch_mode == 1) { |
734 | sort__mode = SORT_MODE__BRANCH; | 734 | sort__mode = SORT_MODE__BRANCH; |
735 | symbol_conf.cumulate_callchain = false; | 735 | symbol_conf.cumulate_callchain = false; |
736 | } | 736 | } |
@@ -798,7 +798,7 @@ repeat: | |||
798 | } | 798 | } |
799 | } | 799 | } |
800 | 800 | ||
801 | if (symbol__init() < 0) | 801 | if (symbol__init(&session->header.env) < 0) |
802 | goto error; | 802 | goto error; |
803 | 803 | ||
804 | if (argc) { | 804 | if (argc) { |
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 7c16aeb6b675..f5874a27b346 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c | |||
@@ -1462,6 +1462,8 @@ static int perf_sched__read_events(struct perf_sched *sched, | |||
1462 | return -1; | 1462 | return -1; |
1463 | } | 1463 | } |
1464 | 1464 | ||
1465 | symbol__init(&session->header.env); | ||
1466 | |||
1465 | if (perf_session__set_tracepoints_handlers(session, handlers)) | 1467 | if (perf_session__set_tracepoints_handlers(session, handlers)) |
1466 | goto out_delete; | 1468 | goto out_delete; |
1467 | 1469 | ||
@@ -1747,7 +1749,6 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1747 | if (!strcmp(argv[0], "script")) | 1749 | if (!strcmp(argv[0], "script")) |
1748 | return cmd_script(argc, argv, prefix); | 1750 | return cmd_script(argc, argv, prefix); |
1749 | 1751 | ||
1750 | symbol__init(); | ||
1751 | if (!strncmp(argv[0], "rec", 3)) { | 1752 | if (!strncmp(argv[0], "rec", 3)) { |
1752 | return __cmd_record(argc, argv); | 1753 | return __cmd_record(argc, argv); |
1753 | } else if (!strncmp(argv[0], "lat", 3)) { | 1754 | } else if (!strncmp(argv[0], "lat", 3)) { |
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 868c17d09762..c1b7029884b1 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c | |||
@@ -184,10 +184,6 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel, | |||
184 | if (perf_evsel__check_stype(evsel, PERF_SAMPLE_IP, "IP", | 184 | if (perf_evsel__check_stype(evsel, PERF_SAMPLE_IP, "IP", |
185 | PERF_OUTPUT_IP)) | 185 | PERF_OUTPUT_IP)) |
186 | return -EINVAL; | 186 | return -EINVAL; |
187 | |||
188 | if (!no_callchain && | ||
189 | !(attr->sample_type & PERF_SAMPLE_CALLCHAIN)) | ||
190 | symbol_conf.use_callchain = false; | ||
191 | } | 187 | } |
192 | 188 | ||
193 | if (PRINT_FIELD(ADDR) && | 189 | if (PRINT_FIELD(ADDR) && |
@@ -290,6 +286,19 @@ static int perf_session__check_output_opt(struct perf_session *session) | |||
290 | set_print_ip_opts(&evsel->attr); | 286 | set_print_ip_opts(&evsel->attr); |
291 | } | 287 | } |
292 | 288 | ||
289 | if (!no_callchain) { | ||
290 | bool use_callchain = false; | ||
291 | |||
292 | evlist__for_each(session->evlist, evsel) { | ||
293 | if (evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN) { | ||
294 | use_callchain = true; | ||
295 | break; | ||
296 | } | ||
297 | } | ||
298 | if (!use_callchain) | ||
299 | symbol_conf.use_callchain = false; | ||
300 | } | ||
301 | |||
293 | /* | 302 | /* |
294 | * set default for tracepoints to print symbols only | 303 | * set default for tracepoints to print symbols only |
295 | * if callchains are present | 304 | * if callchains are present |
@@ -1471,12 +1480,13 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1471 | bool show_full_info = false; | 1480 | bool show_full_info = false; |
1472 | bool header = false; | 1481 | bool header = false; |
1473 | bool header_only = false; | 1482 | bool header_only = false; |
1483 | bool script_started = false; | ||
1474 | char *rec_script_path = NULL; | 1484 | char *rec_script_path = NULL; |
1475 | char *rep_script_path = NULL; | 1485 | char *rep_script_path = NULL; |
1476 | struct perf_session *session; | 1486 | struct perf_session *session; |
1477 | char *script_path = NULL; | 1487 | char *script_path = NULL; |
1478 | const char **__argv; | 1488 | const char **__argv; |
1479 | int i, j, err; | 1489 | int i, j, err = 0; |
1480 | struct perf_script script = { | 1490 | struct perf_script script = { |
1481 | .tool = { | 1491 | .tool = { |
1482 | .sample = process_sample_event, | 1492 | .sample = process_sample_event, |
@@ -1718,8 +1728,6 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1718 | exit(-1); | 1728 | exit(-1); |
1719 | } | 1729 | } |
1720 | 1730 | ||
1721 | if (symbol__init() < 0) | ||
1722 | return -1; | ||
1723 | if (!script_name) | 1731 | if (!script_name) |
1724 | setup_pager(); | 1732 | setup_pager(); |
1725 | 1733 | ||
@@ -1730,14 +1738,18 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1730 | if (header || header_only) { | 1738 | if (header || header_only) { |
1731 | perf_session__fprintf_info(session, stdout, show_full_info); | 1739 | perf_session__fprintf_info(session, stdout, show_full_info); |
1732 | if (header_only) | 1740 | if (header_only) |
1733 | return 0; | 1741 | goto out_delete; |
1734 | } | 1742 | } |
1735 | 1743 | ||
1744 | if (symbol__init(&session->header.env) < 0) | ||
1745 | goto out_delete; | ||
1746 | |||
1736 | script.session = session; | 1747 | script.session = session; |
1737 | 1748 | ||
1738 | if (cpu_list) { | 1749 | if (cpu_list) { |
1739 | if (perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap)) | 1750 | err = perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap); |
1740 | return -1; | 1751 | if (err < 0) |
1752 | goto out_delete; | ||
1741 | } | 1753 | } |
1742 | 1754 | ||
1743 | if (!no_callchain) | 1755 | if (!no_callchain) |
@@ -1752,53 +1764,60 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1752 | if (output_set_by_user()) { | 1764 | if (output_set_by_user()) { |
1753 | fprintf(stderr, | 1765 | fprintf(stderr, |
1754 | "custom fields not supported for generated scripts"); | 1766 | "custom fields not supported for generated scripts"); |
1755 | return -1; | 1767 | err = -EINVAL; |
1768 | goto out_delete; | ||
1756 | } | 1769 | } |
1757 | 1770 | ||
1758 | input = open(file.path, O_RDONLY); /* input_name */ | 1771 | input = open(file.path, O_RDONLY); /* input_name */ |
1759 | if (input < 0) { | 1772 | if (input < 0) { |
1773 | err = -errno; | ||
1760 | perror("failed to open file"); | 1774 | perror("failed to open file"); |
1761 | return -1; | 1775 | goto out_delete; |
1762 | } | 1776 | } |
1763 | 1777 | ||
1764 | err = fstat(input, &perf_stat); | 1778 | err = fstat(input, &perf_stat); |
1765 | if (err < 0) { | 1779 | if (err < 0) { |
1766 | perror("failed to stat file"); | 1780 | perror("failed to stat file"); |
1767 | return -1; | 1781 | goto out_delete; |
1768 | } | 1782 | } |
1769 | 1783 | ||
1770 | if (!perf_stat.st_size) { | 1784 | if (!perf_stat.st_size) { |
1771 | fprintf(stderr, "zero-sized file, nothing to do!\n"); | 1785 | fprintf(stderr, "zero-sized file, nothing to do!\n"); |
1772 | return 0; | 1786 | goto out_delete; |
1773 | } | 1787 | } |
1774 | 1788 | ||
1775 | scripting_ops = script_spec__lookup(generate_script_lang); | 1789 | scripting_ops = script_spec__lookup(generate_script_lang); |
1776 | if (!scripting_ops) { | 1790 | if (!scripting_ops) { |
1777 | fprintf(stderr, "invalid language specifier"); | 1791 | fprintf(stderr, "invalid language specifier"); |
1778 | return -1; | 1792 | err = -ENOENT; |
1793 | goto out_delete; | ||
1779 | } | 1794 | } |
1780 | 1795 | ||
1781 | err = scripting_ops->generate_script(session->tevent.pevent, | 1796 | err = scripting_ops->generate_script(session->tevent.pevent, |
1782 | "perf-script"); | 1797 | "perf-script"); |
1783 | goto out; | 1798 | goto out_delete; |
1784 | } | 1799 | } |
1785 | 1800 | ||
1786 | if (script_name) { | 1801 | if (script_name) { |
1787 | err = scripting_ops->start_script(script_name, argc, argv); | 1802 | err = scripting_ops->start_script(script_name, argc, argv); |
1788 | if (err) | 1803 | if (err) |
1789 | goto out; | 1804 | goto out_delete; |
1790 | pr_debug("perf script started with script %s\n\n", script_name); | 1805 | pr_debug("perf script started with script %s\n\n", script_name); |
1806 | script_started = true; | ||
1791 | } | 1807 | } |
1792 | 1808 | ||
1793 | 1809 | ||
1794 | err = perf_session__check_output_opt(session); | 1810 | err = perf_session__check_output_opt(session); |
1795 | if (err < 0) | 1811 | if (err < 0) |
1796 | goto out; | 1812 | goto out_delete; |
1797 | 1813 | ||
1798 | err = __cmd_script(&script); | 1814 | err = __cmd_script(&script); |
1799 | 1815 | ||
1816 | out_delete: | ||
1800 | perf_session__delete(session); | 1817 | perf_session__delete(session); |
1801 | cleanup_scripting(); | 1818 | |
1819 | if (script_started) | ||
1820 | cleanup_scripting(); | ||
1802 | out: | 1821 | out: |
1803 | return err; | 1822 | return err; |
1804 | } | 1823 | } |
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index 912e3b5bb22b..48eea6cd2f5b 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c | |||
@@ -1607,6 +1607,8 @@ static int __cmd_timechart(struct timechart *tchart, const char *output_name) | |||
1607 | if (session == NULL) | 1607 | if (session == NULL) |
1608 | return -ENOMEM; | 1608 | return -ENOMEM; |
1609 | 1609 | ||
1610 | symbol__init(&session->header.env); | ||
1611 | |||
1610 | (void)perf_header__process_sections(&session->header, | 1612 | (void)perf_header__process_sections(&session->header, |
1611 | perf_data_file__fd(session->file), | 1613 | perf_data_file__fd(session->file), |
1612 | tchart, | 1614 | tchart, |
@@ -1982,8 +1984,6 @@ int cmd_timechart(int argc, const char **argv, | |||
1982 | return -1; | 1984 | return -1; |
1983 | } | 1985 | } |
1984 | 1986 | ||
1985 | symbol__init(); | ||
1986 | |||
1987 | if (argc && !strncmp(argv[0], "rec", 3)) { | 1987 | if (argc && !strncmp(argv[0], "rec", 3)) { |
1988 | argc = parse_options(argc, argv, record_options, record_usage, | 1988 | argc = parse_options(argc, argv, record_options, record_usage, |
1989 | PARSE_OPT_STOP_AT_NON_OPTION); | 1989 | PARSE_OPT_STOP_AT_NON_OPTION); |
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index bde216b2071c..87a6615a40fa 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
@@ -276,11 +276,17 @@ static void perf_top__print_sym_table(struct perf_top *top) | |||
276 | return; | 276 | return; |
277 | } | 277 | } |
278 | 278 | ||
279 | if (top->zero) { | ||
280 | hists__delete_entries(&top->sym_evsel->hists); | ||
281 | } else { | ||
282 | hists__decay_entries(&top->sym_evsel->hists, | ||
283 | top->hide_user_symbols, | ||
284 | top->hide_kernel_symbols); | ||
285 | } | ||
286 | |||
279 | hists__collapse_resort(&top->sym_evsel->hists, NULL); | 287 | hists__collapse_resort(&top->sym_evsel->hists, NULL); |
280 | hists__output_resort(&top->sym_evsel->hists); | 288 | hists__output_resort(&top->sym_evsel->hists); |
281 | hists__decay_entries(&top->sym_evsel->hists, | 289 | |
282 | top->hide_user_symbols, | ||
283 | top->hide_kernel_symbols); | ||
284 | hists__output_recalc_col_len(&top->sym_evsel->hists, | 290 | hists__output_recalc_col_len(&top->sym_evsel->hists, |
285 | top->print_entries - printed); | 291 | top->print_entries - printed); |
286 | putchar('\n'); | 292 | putchar('\n'); |
@@ -542,11 +548,16 @@ static void perf_top__sort_new_samples(void *arg) | |||
542 | if (t->evlist->selected != NULL) | 548 | if (t->evlist->selected != NULL) |
543 | t->sym_evsel = t->evlist->selected; | 549 | t->sym_evsel = t->evlist->selected; |
544 | 550 | ||
551 | if (t->zero) { | ||
552 | hists__delete_entries(&t->sym_evsel->hists); | ||
553 | } else { | ||
554 | hists__decay_entries(&t->sym_evsel->hists, | ||
555 | t->hide_user_symbols, | ||
556 | t->hide_kernel_symbols); | ||
557 | } | ||
558 | |||
545 | hists__collapse_resort(&t->sym_evsel->hists, NULL); | 559 | hists__collapse_resort(&t->sym_evsel->hists, NULL); |
546 | hists__output_resort(&t->sym_evsel->hists); | 560 | hists__output_resort(&t->sym_evsel->hists); |
547 | hists__decay_entries(&t->sym_evsel->hists, | ||
548 | t->hide_user_symbols, | ||
549 | t->hide_kernel_symbols); | ||
550 | } | 561 | } |
551 | 562 | ||
552 | static void *display_thread_tui(void *arg) | 563 | static void *display_thread_tui(void *arg) |
@@ -577,23 +588,32 @@ static void *display_thread_tui(void *arg) | |||
577 | return NULL; | 588 | return NULL; |
578 | } | 589 | } |
579 | 590 | ||
591 | static void display_sig(int sig __maybe_unused) | ||
592 | { | ||
593 | done = 1; | ||
594 | } | ||
595 | |||
596 | static void display_setup_sig(void) | ||
597 | { | ||
598 | signal(SIGSEGV, display_sig); | ||
599 | signal(SIGFPE, display_sig); | ||
600 | signal(SIGINT, display_sig); | ||
601 | signal(SIGQUIT, display_sig); | ||
602 | signal(SIGTERM, display_sig); | ||
603 | } | ||
604 | |||
580 | static void *display_thread(void *arg) | 605 | static void *display_thread(void *arg) |
581 | { | 606 | { |
582 | struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; | 607 | struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; |
583 | struct termios tc, save; | 608 | struct termios save; |
584 | struct perf_top *top = arg; | 609 | struct perf_top *top = arg; |
585 | int delay_msecs, c; | 610 | int delay_msecs, c; |
586 | 611 | ||
587 | tcgetattr(0, &save); | 612 | display_setup_sig(); |
588 | tc = save; | ||
589 | tc.c_lflag &= ~(ICANON | ECHO); | ||
590 | tc.c_cc[VMIN] = 0; | ||
591 | tc.c_cc[VTIME] = 0; | ||
592 | |||
593 | pthread__unblock_sigwinch(); | 613 | pthread__unblock_sigwinch(); |
594 | repeat: | 614 | repeat: |
595 | delay_msecs = top->delay_secs * 1000; | 615 | delay_msecs = top->delay_secs * 1000; |
596 | tcsetattr(0, TCSANOW, &tc); | 616 | set_term_quiet_input(&save); |
597 | /* trash return*/ | 617 | /* trash return*/ |
598 | getc(stdin); | 618 | getc(stdin); |
599 | 619 | ||
@@ -620,13 +640,16 @@ repeat: | |||
620 | } | 640 | } |
621 | } | 641 | } |
622 | 642 | ||
643 | tcsetattr(0, TCSAFLUSH, &save); | ||
623 | return NULL; | 644 | return NULL; |
624 | } | 645 | } |
625 | 646 | ||
626 | static int symbol_filter(struct map *map __maybe_unused, struct symbol *sym) | 647 | static int symbol_filter(struct map *map, struct symbol *sym) |
627 | { | 648 | { |
628 | const char *name = sym->name; | 649 | const char *name = sym->name; |
629 | 650 | ||
651 | if (!map->dso->kernel) | ||
652 | return 0; | ||
630 | /* | 653 | /* |
631 | * ppc64 uses function descriptors and appends a '.' to the | 654 | * ppc64 uses function descriptors and appends a '.' to the |
632 | * start of every instruction address. Remove it. | 655 | * start of every instruction address. Remove it. |
@@ -963,7 +986,7 @@ static int __cmd_top(struct perf_top *top) | |||
963 | param.sched_priority = top->realtime_prio; | 986 | param.sched_priority = top->realtime_prio; |
964 | if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { | 987 | if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { |
965 | ui__error("Could not set realtime priority.\n"); | 988 | ui__error("Could not set realtime priority.\n"); |
966 | goto out_delete; | 989 | goto out_join; |
967 | } | 990 | } |
968 | } | 991 | } |
969 | 992 | ||
@@ -977,6 +1000,8 @@ static int __cmd_top(struct perf_top *top) | |||
977 | } | 1000 | } |
978 | 1001 | ||
979 | ret = 0; | 1002 | ret = 0; |
1003 | out_join: | ||
1004 | pthread_join(thread, NULL); | ||
980 | out_delete: | 1005 | out_delete: |
981 | perf_session__delete(top->session); | 1006 | perf_session__delete(top->session); |
982 | top->session = NULL; | 1007 | top->session = NULL; |
@@ -1220,7 +1245,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1220 | symbol_conf.priv_size = sizeof(struct annotation); | 1245 | symbol_conf.priv_size = sizeof(struct annotation); |
1221 | 1246 | ||
1222 | symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL); | 1247 | symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL); |
1223 | if (symbol__init() < 0) | 1248 | if (symbol__init(NULL) < 0) |
1224 | return -1; | 1249 | return -1; |
1225 | 1250 | ||
1226 | sort__setup_elide(stdout); | 1251 | sort__setup_elide(stdout); |
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 36ae51d61be2..d080b9cf0354 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c | |||
@@ -402,6 +402,31 @@ static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size, | |||
402 | 402 | ||
403 | #define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags | 403 | #define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags |
404 | 404 | ||
405 | static size_t syscall_arg__scnprintf_mremap_flags(char *bf, size_t size, | ||
406 | struct syscall_arg *arg) | ||
407 | { | ||
408 | int printed = 0, flags = arg->val; | ||
409 | |||
410 | #define P_MREMAP_FLAG(n) \ | ||
411 | if (flags & MREMAP_##n) { \ | ||
412 | printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \ | ||
413 | flags &= ~MREMAP_##n; \ | ||
414 | } | ||
415 | |||
416 | P_MREMAP_FLAG(MAYMOVE); | ||
417 | #ifdef MREMAP_FIXED | ||
418 | P_MREMAP_FLAG(FIXED); | ||
419 | #endif | ||
420 | #undef P_MREMAP_FLAG | ||
421 | |||
422 | if (flags) | ||
423 | printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags); | ||
424 | |||
425 | return printed; | ||
426 | } | ||
427 | |||
428 | #define SCA_MREMAP_FLAGS syscall_arg__scnprintf_mremap_flags | ||
429 | |||
405 | static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size, | 430 | static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size, |
406 | struct syscall_arg *arg) | 431 | struct syscall_arg *arg) |
407 | { | 432 | { |
@@ -1004,6 +1029,7 @@ static struct syscall_fmt { | |||
1004 | [2] = SCA_MMAP_PROT, /* prot */ }, }, | 1029 | [2] = SCA_MMAP_PROT, /* prot */ }, }, |
1005 | { .name = "mremap", .hexret = true, | 1030 | { .name = "mremap", .hexret = true, |
1006 | .arg_scnprintf = { [0] = SCA_HEX, /* addr */ | 1031 | .arg_scnprintf = { [0] = SCA_HEX, /* addr */ |
1032 | [3] = SCA_MREMAP_FLAGS, /* flags */ | ||
1007 | [4] = SCA_HEX, /* new_addr */ }, }, | 1033 | [4] = SCA_HEX, /* new_addr */ }, }, |
1008 | { .name = "munlock", .errmsg = true, | 1034 | { .name = "munlock", .errmsg = true, |
1009 | .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, }, | 1035 | .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, }, |
@@ -1385,7 +1411,7 @@ static int trace__tool_process(struct perf_tool *tool, | |||
1385 | 1411 | ||
1386 | static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist) | 1412 | static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist) |
1387 | { | 1413 | { |
1388 | int err = symbol__init(); | 1414 | int err = symbol__init(NULL); |
1389 | 1415 | ||
1390 | if (err) | 1416 | if (err) |
1391 | return err; | 1417 | return err; |
@@ -2215,13 +2241,13 @@ static int trace__replay(struct trace *trace) | |||
2215 | /* add tid to output */ | 2241 | /* add tid to output */ |
2216 | trace->multiple_threads = true; | 2242 | trace->multiple_threads = true; |
2217 | 2243 | ||
2218 | if (symbol__init() < 0) | ||
2219 | return -1; | ||
2220 | |||
2221 | session = perf_session__new(&file, false, &trace->tool); | 2244 | session = perf_session__new(&file, false, &trace->tool); |
2222 | if (session == NULL) | 2245 | if (session == NULL) |
2223 | return -ENOMEM; | 2246 | return -ENOMEM; |
2224 | 2247 | ||
2248 | if (symbol__init(&session->header.env) < 0) | ||
2249 | goto out; | ||
2250 | |||
2225 | trace->host = &session->machines.host; | 2251 | trace->host = &session->machines.host; |
2226 | 2252 | ||
2227 | err = perf_session__set_tracepoints_handlers(session, handlers); | 2253 | err = perf_session__set_tracepoints_handlers(session, handlers); |
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index 6f8b01bc6033..c6796d22423a 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c | |||
@@ -297,7 +297,7 @@ int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused) | |||
297 | symbol_conf.sort_by_name = true; | 297 | symbol_conf.sort_by_name = true; |
298 | symbol_conf.try_vmlinux_path = true; | 298 | symbol_conf.try_vmlinux_path = true; |
299 | 299 | ||
300 | if (symbol__init() < 0) | 300 | if (symbol__init(NULL) < 0) |
301 | return -1; | 301 | return -1; |
302 | 302 | ||
303 | if (skip != NULL) | 303 | if (skip != NULL) |
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 045c1e16ac59..4892480e8298 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include "../../util/pstack.h" | 10 | #include "../../util/pstack.h" |
11 | #include "../../util/sort.h" | 11 | #include "../../util/sort.h" |
12 | #include "../../util/util.h" | 12 | #include "../../util/util.h" |
13 | #include "../../util/top.h" | ||
13 | #include "../../arch/common.h" | 14 | #include "../../arch/common.h" |
14 | 15 | ||
15 | #include "../browser.h" | 16 | #include "../browser.h" |
@@ -228,8 +229,10 @@ static void callchain_node__init_have_children(struct callchain_node *node) | |||
228 | { | 229 | { |
229 | struct callchain_list *chain; | 230 | struct callchain_list *chain; |
230 | 231 | ||
231 | list_for_each_entry(chain, &node->val, list) | 232 | if (!list_empty(&node->val)) { |
233 | chain = list_entry(node->val.prev, struct callchain_list, list); | ||
232 | chain->ms.has_children = !RB_EMPTY_ROOT(&node->rb_root); | 234 | chain->ms.has_children = !RB_EMPTY_ROOT(&node->rb_root); |
235 | } | ||
233 | 236 | ||
234 | callchain_node__init_have_children_rb_tree(node); | 237 | callchain_node__init_have_children_rb_tree(node); |
235 | } | 238 | } |
@@ -1530,6 +1533,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, | |||
1530 | "P Print histograms to perf.hist.N\n" | 1533 | "P Print histograms to perf.hist.N\n" |
1531 | "t Zoom into current Thread\n" | 1534 | "t Zoom into current Thread\n" |
1532 | "V Verbose (DSO names in callchains, etc)\n" | 1535 | "V Verbose (DSO names in callchains, etc)\n" |
1536 | "z Toggle zeroing of samples\n" | ||
1533 | "/ Filter symbol by name"; | 1537 | "/ Filter symbol by name"; |
1534 | 1538 | ||
1535 | if (browser == NULL) | 1539 | if (browser == NULL) |
@@ -1630,6 +1634,13 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, | |||
1630 | case 'F': | 1634 | case 'F': |
1631 | symbol_conf.filter_relative ^= 1; | 1635 | symbol_conf.filter_relative ^= 1; |
1632 | continue; | 1636 | continue; |
1637 | case 'z': | ||
1638 | if (!is_report_browser(hbt)) { | ||
1639 | struct perf_top *top = hbt->arg; | ||
1640 | |||
1641 | top->zero = !top->zero; | ||
1642 | } | ||
1643 | continue; | ||
1633 | case K_F1: | 1644 | case K_F1: |
1634 | case 'h': | 1645 | case 'h': |
1635 | case '?': | 1646 | case '?': |
diff --git a/tools/perf/util/cloexec.c b/tools/perf/util/cloexec.c index 5073c01af618..4945aa56a017 100644 --- a/tools/perf/util/cloexec.c +++ b/tools/perf/util/cloexec.c | |||
@@ -1,3 +1,4 @@ | |||
1 | #include <sched.h> | ||
1 | #include "util.h" | 2 | #include "util.h" |
2 | #include "../perf.h" | 3 | #include "../perf.h" |
3 | #include "cloexec.h" | 4 | #include "cloexec.h" |
@@ -11,13 +12,27 @@ static int perf_flag_probe(void) | |||
11 | struct perf_event_attr attr = { | 12 | struct perf_event_attr attr = { |
12 | .type = PERF_TYPE_SOFTWARE, | 13 | .type = PERF_TYPE_SOFTWARE, |
13 | .config = PERF_COUNT_SW_CPU_CLOCK, | 14 | .config = PERF_COUNT_SW_CPU_CLOCK, |
15 | .exclude_kernel = 1, | ||
14 | }; | 16 | }; |
15 | int fd; | 17 | int fd; |
16 | int err; | 18 | int err; |
19 | int cpu; | ||
20 | pid_t pid = -1; | ||
17 | 21 | ||
18 | /* check cloexec flag */ | 22 | cpu = sched_getcpu(); |
19 | fd = sys_perf_event_open(&attr, 0, -1, -1, | 23 | if (cpu < 0) |
20 | PERF_FLAG_FD_CLOEXEC); | 24 | cpu = 0; |
25 | |||
26 | while (1) { | ||
27 | /* check cloexec flag */ | ||
28 | fd = sys_perf_event_open(&attr, pid, cpu, -1, | ||
29 | PERF_FLAG_FD_CLOEXEC); | ||
30 | if (fd < 0 && pid == -1 && errno == EACCES) { | ||
31 | pid = 0; | ||
32 | continue; | ||
33 | } | ||
34 | break; | ||
35 | } | ||
21 | err = errno; | 36 | err = errno; |
22 | 37 | ||
23 | if (fd >= 0) { | 38 | if (fd >= 0) { |
@@ -30,7 +45,7 @@ static int perf_flag_probe(void) | |||
30 | err, strerror(err)); | 45 | err, strerror(err)); |
31 | 46 | ||
32 | /* not supported, confirm error related to PERF_FLAG_FD_CLOEXEC */ | 47 | /* not supported, confirm error related to PERF_FLAG_FD_CLOEXEC */ |
33 | fd = sys_perf_event_open(&attr, 0, -1, -1, 0); | 48 | fd = sys_perf_event_open(&attr, pid, cpu, -1, 0); |
34 | err = errno; | 49 | err = errno; |
35 | 50 | ||
36 | if (WARN_ONCE(fd < 0 && err != EBUSY, | 51 | if (WARN_ONCE(fd < 0 && err != EBUSY, |
diff --git a/tools/perf/util/comm.c b/tools/perf/util/comm.c index f9e777629e21..b2bb59df65e1 100644 --- a/tools/perf/util/comm.c +++ b/tools/perf/util/comm.c | |||
@@ -74,7 +74,7 @@ static struct comm_str *comm_str__findnew(const char *str, struct rb_root *root) | |||
74 | return new; | 74 | return new; |
75 | } | 75 | } |
76 | 76 | ||
77 | struct comm *comm__new(const char *str, u64 timestamp) | 77 | struct comm *comm__new(const char *str, u64 timestamp, bool exec) |
78 | { | 78 | { |
79 | struct comm *comm = zalloc(sizeof(*comm)); | 79 | struct comm *comm = zalloc(sizeof(*comm)); |
80 | 80 | ||
@@ -82,6 +82,7 @@ struct comm *comm__new(const char *str, u64 timestamp) | |||
82 | return NULL; | 82 | return NULL; |
83 | 83 | ||
84 | comm->start = timestamp; | 84 | comm->start = timestamp; |
85 | comm->exec = exec; | ||
85 | 86 | ||
86 | comm->comm_str = comm_str__findnew(str, &comm_str_root); | 87 | comm->comm_str = comm_str__findnew(str, &comm_str_root); |
87 | if (!comm->comm_str) { | 88 | if (!comm->comm_str) { |
@@ -94,7 +95,7 @@ struct comm *comm__new(const char *str, u64 timestamp) | |||
94 | return comm; | 95 | return comm; |
95 | } | 96 | } |
96 | 97 | ||
97 | int comm__override(struct comm *comm, const char *str, u64 timestamp) | 98 | int comm__override(struct comm *comm, const char *str, u64 timestamp, bool exec) |
98 | { | 99 | { |
99 | struct comm_str *new, *old = comm->comm_str; | 100 | struct comm_str *new, *old = comm->comm_str; |
100 | 101 | ||
@@ -106,6 +107,8 @@ int comm__override(struct comm *comm, const char *str, u64 timestamp) | |||
106 | comm_str__put(old); | 107 | comm_str__put(old); |
107 | comm->comm_str = new; | 108 | comm->comm_str = new; |
108 | comm->start = timestamp; | 109 | comm->start = timestamp; |
110 | if (exec) | ||
111 | comm->exec = true; | ||
109 | 112 | ||
110 | return 0; | 113 | return 0; |
111 | } | 114 | } |
diff --git a/tools/perf/util/comm.h b/tools/perf/util/comm.h index fac5bd51befc..51c10ab257f8 100644 --- a/tools/perf/util/comm.h +++ b/tools/perf/util/comm.h | |||
@@ -11,11 +11,13 @@ struct comm { | |||
11 | struct comm_str *comm_str; | 11 | struct comm_str *comm_str; |
12 | u64 start; | 12 | u64 start; |
13 | struct list_head list; | 13 | struct list_head list; |
14 | bool exec; | ||
14 | }; | 15 | }; |
15 | 16 | ||
16 | void comm__free(struct comm *comm); | 17 | void comm__free(struct comm *comm); |
17 | struct comm *comm__new(const char *str, u64 timestamp); | 18 | struct comm *comm__new(const char *str, u64 timestamp, bool exec); |
18 | const char *comm__str(const struct comm *comm); | 19 | const char *comm__str(const struct comm *comm); |
19 | int comm__override(struct comm *comm, const char *str, u64 timestamp); | 20 | int comm__override(struct comm *comm, const char *str, u64 timestamp, |
21 | bool exec); | ||
20 | 22 | ||
21 | #endif /* __PERF_COMM_H */ | 23 | #endif /* __PERF_COMM_H */ |
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index 94d6976180da..7eb7107731ec 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h | |||
@@ -156,6 +156,8 @@ struct perf_sample { | |||
156 | u32 cpu; | 156 | u32 cpu; |
157 | u32 raw_size; | 157 | u32 raw_size; |
158 | u64 data_src; | 158 | u64 data_src; |
159 | u32 flags; | ||
160 | u16 insn_len; | ||
159 | void *raw_data; | 161 | void *raw_data; |
160 | struct ip_callchain *callchain; | 162 | struct ip_callchain *callchain; |
161 | struct branch_stack *branch_stack; | 163 | struct branch_stack *branch_stack; |
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 3b366c085021..5dcd28c79c6e 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c | |||
@@ -122,6 +122,7 @@ void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry) | |||
122 | { | 122 | { |
123 | list_add_tail(&entry->node, &evlist->entries); | 123 | list_add_tail(&entry->node, &evlist->entries); |
124 | entry->idx = evlist->nr_entries; | 124 | entry->idx = evlist->nr_entries; |
125 | entry->tracking = !entry->idx; | ||
125 | 126 | ||
126 | if (!evlist->nr_entries++) | 127 | if (!evlist->nr_entries++) |
127 | perf_evlist__set_id_pos(evlist); | 128 | perf_evlist__set_id_pos(evlist); |
@@ -265,17 +266,27 @@ int perf_evlist__add_newtp(struct perf_evlist *evlist, | |||
265 | return 0; | 266 | return 0; |
266 | } | 267 | } |
267 | 268 | ||
269 | static int perf_evlist__nr_threads(struct perf_evlist *evlist, | ||
270 | struct perf_evsel *evsel) | ||
271 | { | ||
272 | if (evsel->system_wide) | ||
273 | return 1; | ||
274 | else | ||
275 | return thread_map__nr(evlist->threads); | ||
276 | } | ||
277 | |||
268 | void perf_evlist__disable(struct perf_evlist *evlist) | 278 | void perf_evlist__disable(struct perf_evlist *evlist) |
269 | { | 279 | { |
270 | int cpu, thread; | 280 | int cpu, thread; |
271 | struct perf_evsel *pos; | 281 | struct perf_evsel *pos; |
272 | int nr_cpus = cpu_map__nr(evlist->cpus); | 282 | int nr_cpus = cpu_map__nr(evlist->cpus); |
273 | int nr_threads = thread_map__nr(evlist->threads); | 283 | int nr_threads; |
274 | 284 | ||
275 | for (cpu = 0; cpu < nr_cpus; cpu++) { | 285 | for (cpu = 0; cpu < nr_cpus; cpu++) { |
276 | evlist__for_each(evlist, pos) { | 286 | evlist__for_each(evlist, pos) { |
277 | if (!perf_evsel__is_group_leader(pos) || !pos->fd) | 287 | if (!perf_evsel__is_group_leader(pos) || !pos->fd) |
278 | continue; | 288 | continue; |
289 | nr_threads = perf_evlist__nr_threads(evlist, pos); | ||
279 | for (thread = 0; thread < nr_threads; thread++) | 290 | for (thread = 0; thread < nr_threads; thread++) |
280 | ioctl(FD(pos, cpu, thread), | 291 | ioctl(FD(pos, cpu, thread), |
281 | PERF_EVENT_IOC_DISABLE, 0); | 292 | PERF_EVENT_IOC_DISABLE, 0); |
@@ -288,12 +299,13 @@ void perf_evlist__enable(struct perf_evlist *evlist) | |||
288 | int cpu, thread; | 299 | int cpu, thread; |
289 | struct perf_evsel *pos; | 300 | struct perf_evsel *pos; |
290 | int nr_cpus = cpu_map__nr(evlist->cpus); | 301 | int nr_cpus = cpu_map__nr(evlist->cpus); |
291 | int nr_threads = thread_map__nr(evlist->threads); | 302 | int nr_threads; |
292 | 303 | ||
293 | for (cpu = 0; cpu < nr_cpus; cpu++) { | 304 | for (cpu = 0; cpu < nr_cpus; cpu++) { |
294 | evlist__for_each(evlist, pos) { | 305 | evlist__for_each(evlist, pos) { |
295 | if (!perf_evsel__is_group_leader(pos) || !pos->fd) | 306 | if (!perf_evsel__is_group_leader(pos) || !pos->fd) |
296 | continue; | 307 | continue; |
308 | nr_threads = perf_evlist__nr_threads(evlist, pos); | ||
297 | for (thread = 0; thread < nr_threads; thread++) | 309 | for (thread = 0; thread < nr_threads; thread++) |
298 | ioctl(FD(pos, cpu, thread), | 310 | ioctl(FD(pos, cpu, thread), |
299 | PERF_EVENT_IOC_ENABLE, 0); | 311 | PERF_EVENT_IOC_ENABLE, 0); |
@@ -305,12 +317,14 @@ int perf_evlist__disable_event(struct perf_evlist *evlist, | |||
305 | struct perf_evsel *evsel) | 317 | struct perf_evsel *evsel) |
306 | { | 318 | { |
307 | int cpu, thread, err; | 319 | int cpu, thread, err; |
320 | int nr_cpus = cpu_map__nr(evlist->cpus); | ||
321 | int nr_threads = perf_evlist__nr_threads(evlist, evsel); | ||
308 | 322 | ||
309 | if (!evsel->fd) | 323 | if (!evsel->fd) |
310 | return 0; | 324 | return 0; |
311 | 325 | ||
312 | for (cpu = 0; cpu < evlist->cpus->nr; cpu++) { | 326 | for (cpu = 0; cpu < nr_cpus; cpu++) { |
313 | for (thread = 0; thread < evlist->threads->nr; thread++) { | 327 | for (thread = 0; thread < nr_threads; thread++) { |
314 | err = ioctl(FD(evsel, cpu, thread), | 328 | err = ioctl(FD(evsel, cpu, thread), |
315 | PERF_EVENT_IOC_DISABLE, 0); | 329 | PERF_EVENT_IOC_DISABLE, 0); |
316 | if (err) | 330 | if (err) |
@@ -324,12 +338,14 @@ int perf_evlist__enable_event(struct perf_evlist *evlist, | |||
324 | struct perf_evsel *evsel) | 338 | struct perf_evsel *evsel) |
325 | { | 339 | { |
326 | int cpu, thread, err; | 340 | int cpu, thread, err; |
341 | int nr_cpus = cpu_map__nr(evlist->cpus); | ||
342 | int nr_threads = perf_evlist__nr_threads(evlist, evsel); | ||
327 | 343 | ||
328 | if (!evsel->fd) | 344 | if (!evsel->fd) |
329 | return -EINVAL; | 345 | return -EINVAL; |
330 | 346 | ||
331 | for (cpu = 0; cpu < evlist->cpus->nr; cpu++) { | 347 | for (cpu = 0; cpu < nr_cpus; cpu++) { |
332 | for (thread = 0; thread < evlist->threads->nr; thread++) { | 348 | for (thread = 0; thread < nr_threads; thread++) { |
333 | err = ioctl(FD(evsel, cpu, thread), | 349 | err = ioctl(FD(evsel, cpu, thread), |
334 | PERF_EVENT_IOC_ENABLE, 0); | 350 | PERF_EVENT_IOC_ENABLE, 0); |
335 | if (err) | 351 | if (err) |
@@ -339,11 +355,67 @@ int perf_evlist__enable_event(struct perf_evlist *evlist, | |||
339 | return 0; | 355 | return 0; |
340 | } | 356 | } |
341 | 357 | ||
358 | static int perf_evlist__enable_event_cpu(struct perf_evlist *evlist, | ||
359 | struct perf_evsel *evsel, int cpu) | ||
360 | { | ||
361 | int thread, err; | ||
362 | int nr_threads = perf_evlist__nr_threads(evlist, evsel); | ||
363 | |||
364 | if (!evsel->fd) | ||
365 | return -EINVAL; | ||
366 | |||
367 | for (thread = 0; thread < nr_threads; thread++) { | ||
368 | err = ioctl(FD(evsel, cpu, thread), | ||
369 | PERF_EVENT_IOC_ENABLE, 0); | ||
370 | if (err) | ||
371 | return err; | ||
372 | } | ||
373 | return 0; | ||
374 | } | ||
375 | |||
376 | static int perf_evlist__enable_event_thread(struct perf_evlist *evlist, | ||
377 | struct perf_evsel *evsel, | ||
378 | int thread) | ||
379 | { | ||
380 | int cpu, err; | ||
381 | int nr_cpus = cpu_map__nr(evlist->cpus); | ||
382 | |||
383 | if (!evsel->fd) | ||
384 | return -EINVAL; | ||
385 | |||
386 | for (cpu = 0; cpu < nr_cpus; cpu++) { | ||
387 | err = ioctl(FD(evsel, cpu, thread), PERF_EVENT_IOC_ENABLE, 0); | ||
388 | if (err) | ||
389 | return err; | ||
390 | } | ||
391 | return 0; | ||
392 | } | ||
393 | |||
394 | int perf_evlist__enable_event_idx(struct perf_evlist *evlist, | ||
395 | struct perf_evsel *evsel, int idx) | ||
396 | { | ||
397 | bool per_cpu_mmaps = !cpu_map__empty(evlist->cpus); | ||
398 | |||
399 | if (per_cpu_mmaps) | ||
400 | return perf_evlist__enable_event_cpu(evlist, evsel, idx); | ||
401 | else | ||
402 | return perf_evlist__enable_event_thread(evlist, evsel, idx); | ||
403 | } | ||
404 | |||
342 | static int perf_evlist__alloc_pollfd(struct perf_evlist *evlist) | 405 | static int perf_evlist__alloc_pollfd(struct perf_evlist *evlist) |
343 | { | 406 | { |
344 | int nr_cpus = cpu_map__nr(evlist->cpus); | 407 | int nr_cpus = cpu_map__nr(evlist->cpus); |
345 | int nr_threads = thread_map__nr(evlist->threads); | 408 | int nr_threads = thread_map__nr(evlist->threads); |
346 | int nfds = nr_cpus * nr_threads * evlist->nr_entries; | 409 | int nfds = 0; |
410 | struct perf_evsel *evsel; | ||
411 | |||
412 | list_for_each_entry(evsel, &evlist->entries, node) { | ||
413 | if (evsel->system_wide) | ||
414 | nfds += nr_cpus; | ||
415 | else | ||
416 | nfds += nr_cpus * nr_threads; | ||
417 | } | ||
418 | |||
347 | evlist->pollfd = malloc(sizeof(struct pollfd) * nfds); | 419 | evlist->pollfd = malloc(sizeof(struct pollfd) * nfds); |
348 | return evlist->pollfd != NULL ? 0 : -ENOMEM; | 420 | return evlist->pollfd != NULL ? 0 : -ENOMEM; |
349 | } | 421 | } |
@@ -636,7 +708,12 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx, | |||
636 | struct perf_evsel *evsel; | 708 | struct perf_evsel *evsel; |
637 | 709 | ||
638 | evlist__for_each(evlist, evsel) { | 710 | evlist__for_each(evlist, evsel) { |
639 | int fd = FD(evsel, cpu, thread); | 711 | int fd; |
712 | |||
713 | if (evsel->system_wide && thread) | ||
714 | continue; | ||
715 | |||
716 | fd = FD(evsel, cpu, thread); | ||
640 | 717 | ||
641 | if (*output == -1) { | 718 | if (*output == -1) { |
642 | *output = fd; | 719 | *output = fd; |
@@ -1266,3 +1343,19 @@ void perf_evlist__to_front(struct perf_evlist *evlist, | |||
1266 | 1343 | ||
1267 | list_splice(&move, &evlist->entries); | 1344 | list_splice(&move, &evlist->entries); |
1268 | } | 1345 | } |
1346 | |||
1347 | void perf_evlist__set_tracking_event(struct perf_evlist *evlist, | ||
1348 | struct perf_evsel *tracking_evsel) | ||
1349 | { | ||
1350 | struct perf_evsel *evsel; | ||
1351 | |||
1352 | if (tracking_evsel->tracking) | ||
1353 | return; | ||
1354 | |||
1355 | evlist__for_each(evlist, evsel) { | ||
1356 | if (evsel != tracking_evsel) | ||
1357 | evsel->tracking = false; | ||
1358 | } | ||
1359 | |||
1360 | tracking_evsel->tracking = true; | ||
1361 | } | ||
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index f5173cd63693..106de53a6a74 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h | |||
@@ -122,6 +122,8 @@ int perf_evlist__disable_event(struct perf_evlist *evlist, | |||
122 | struct perf_evsel *evsel); | 122 | struct perf_evsel *evsel); |
123 | int perf_evlist__enable_event(struct perf_evlist *evlist, | 123 | int perf_evlist__enable_event(struct perf_evlist *evlist, |
124 | struct perf_evsel *evsel); | 124 | struct perf_evsel *evsel); |
125 | int perf_evlist__enable_event_idx(struct perf_evlist *evlist, | ||
126 | struct perf_evsel *evsel, int idx); | ||
125 | 127 | ||
126 | void perf_evlist__set_selected(struct perf_evlist *evlist, | 128 | void perf_evlist__set_selected(struct perf_evlist *evlist, |
127 | struct perf_evsel *evsel); | 129 | struct perf_evsel *evsel); |
@@ -262,4 +264,7 @@ void perf_evlist__to_front(struct perf_evlist *evlist, | |||
262 | #define evlist__for_each_safe(evlist, tmp, evsel) \ | 264 | #define evlist__for_each_safe(evlist, tmp, evsel) \ |
263 | __evlist__for_each_safe(&(evlist)->entries, tmp, evsel) | 265 | __evlist__for_each_safe(&(evlist)->entries, tmp, evsel) |
264 | 266 | ||
267 | void perf_evlist__set_tracking_event(struct perf_evlist *evlist, | ||
268 | struct perf_evsel *tracking_evsel); | ||
269 | |||
265 | #endif /* __PERF_EVLIST_H */ | 270 | #endif /* __PERF_EVLIST_H */ |
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 0c8919decac8..01ce14c3575e 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
@@ -162,6 +162,7 @@ void perf_evsel__init(struct perf_evsel *evsel, | |||
162 | struct perf_event_attr *attr, int idx) | 162 | struct perf_event_attr *attr, int idx) |
163 | { | 163 | { |
164 | evsel->idx = idx; | 164 | evsel->idx = idx; |
165 | evsel->tracking = !idx; | ||
165 | evsel->attr = *attr; | 166 | evsel->attr = *attr; |
166 | evsel->leader = evsel; | 167 | evsel->leader = evsel; |
167 | evsel->unit = ""; | 168 | evsel->unit = ""; |
@@ -561,7 +562,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts) | |||
561 | { | 562 | { |
562 | struct perf_evsel *leader = evsel->leader; | 563 | struct perf_evsel *leader = evsel->leader; |
563 | struct perf_event_attr *attr = &evsel->attr; | 564 | struct perf_event_attr *attr = &evsel->attr; |
564 | int track = !evsel->idx; /* only the first counter needs these */ | 565 | int track = evsel->tracking; |
565 | bool per_cpu = opts->target.default_per_cpu && !opts->target.per_thread; | 566 | bool per_cpu = opts->target.default_per_cpu && !opts->target.per_thread; |
566 | 567 | ||
567 | attr->sample_id_all = perf_missing_features.sample_id_all ? 0 : 1; | 568 | attr->sample_id_all = perf_missing_features.sample_id_all ? 0 : 1; |
@@ -695,6 +696,10 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts) | |||
695 | int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) | 696 | int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) |
696 | { | 697 | { |
697 | int cpu, thread; | 698 | int cpu, thread; |
699 | |||
700 | if (evsel->system_wide) | ||
701 | nthreads = 1; | ||
702 | |||
698 | evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int)); | 703 | evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int)); |
699 | 704 | ||
700 | if (evsel->fd) { | 705 | if (evsel->fd) { |
@@ -713,6 +718,9 @@ static int perf_evsel__run_ioctl(struct perf_evsel *evsel, int ncpus, int nthrea | |||
713 | { | 718 | { |
714 | int cpu, thread; | 719 | int cpu, thread; |
715 | 720 | ||
721 | if (evsel->system_wide) | ||
722 | nthreads = 1; | ||
723 | |||
716 | for (cpu = 0; cpu < ncpus; cpu++) { | 724 | for (cpu = 0; cpu < ncpus; cpu++) { |
717 | for (thread = 0; thread < nthreads; thread++) { | 725 | for (thread = 0; thread < nthreads; thread++) { |
718 | int fd = FD(evsel, cpu, thread), | 726 | int fd = FD(evsel, cpu, thread), |
@@ -743,6 +751,9 @@ int perf_evsel__enable(struct perf_evsel *evsel, int ncpus, int nthreads) | |||
743 | 751 | ||
744 | int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads) | 752 | int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads) |
745 | { | 753 | { |
754 | if (evsel->system_wide) | ||
755 | nthreads = 1; | ||
756 | |||
746 | evsel->sample_id = xyarray__new(ncpus, nthreads, sizeof(struct perf_sample_id)); | 757 | evsel->sample_id = xyarray__new(ncpus, nthreads, sizeof(struct perf_sample_id)); |
747 | if (evsel->sample_id == NULL) | 758 | if (evsel->sample_id == NULL) |
748 | return -ENOMEM; | 759 | return -ENOMEM; |
@@ -787,6 +798,9 @@ void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads) | |||
787 | { | 798 | { |
788 | int cpu, thread; | 799 | int cpu, thread; |
789 | 800 | ||
801 | if (evsel->system_wide) | ||
802 | nthreads = 1; | ||
803 | |||
790 | for (cpu = 0; cpu < ncpus; cpu++) | 804 | for (cpu = 0; cpu < ncpus; cpu++) |
791 | for (thread = 0; thread < nthreads; ++thread) { | 805 | for (thread = 0; thread < nthreads; ++thread) { |
792 | close(FD(evsel, cpu, thread)); | 806 | close(FD(evsel, cpu, thread)); |
@@ -875,6 +889,9 @@ int __perf_evsel__read(struct perf_evsel *evsel, | |||
875 | int cpu, thread; | 889 | int cpu, thread; |
876 | struct perf_counts_values *aggr = &evsel->counts->aggr, count; | 890 | struct perf_counts_values *aggr = &evsel->counts->aggr, count; |
877 | 891 | ||
892 | if (evsel->system_wide) | ||
893 | nthreads = 1; | ||
894 | |||
878 | aggr->val = aggr->ena = aggr->run = 0; | 895 | aggr->val = aggr->ena = aggr->run = 0; |
879 | 896 | ||
880 | for (cpu = 0; cpu < ncpus; cpu++) { | 897 | for (cpu = 0; cpu < ncpus; cpu++) { |
@@ -997,13 +1014,18 @@ static size_t perf_event_attr__fprintf(struct perf_event_attr *attr, FILE *fp) | |||
997 | static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, | 1014 | static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, |
998 | struct thread_map *threads) | 1015 | struct thread_map *threads) |
999 | { | 1016 | { |
1000 | int cpu, thread; | 1017 | int cpu, thread, nthreads; |
1001 | unsigned long flags = PERF_FLAG_FD_CLOEXEC; | 1018 | unsigned long flags = PERF_FLAG_FD_CLOEXEC; |
1002 | int pid = -1, err; | 1019 | int pid = -1, err; |
1003 | enum { NO_CHANGE, SET_TO_MAX, INCREASED_MAX } set_rlimit = NO_CHANGE; | 1020 | enum { NO_CHANGE, SET_TO_MAX, INCREASED_MAX } set_rlimit = NO_CHANGE; |
1004 | 1021 | ||
1022 | if (evsel->system_wide) | ||
1023 | nthreads = 1; | ||
1024 | else | ||
1025 | nthreads = threads->nr; | ||
1026 | |||
1005 | if (evsel->fd == NULL && | 1027 | if (evsel->fd == NULL && |
1006 | perf_evsel__alloc_fd(evsel, cpus->nr, threads->nr) < 0) | 1028 | perf_evsel__alloc_fd(evsel, cpus->nr, nthreads) < 0) |
1007 | return -ENOMEM; | 1029 | return -ENOMEM; |
1008 | 1030 | ||
1009 | if (evsel->cgrp) { | 1031 | if (evsel->cgrp) { |
@@ -1027,10 +1049,10 @@ retry_sample_id: | |||
1027 | 1049 | ||
1028 | for (cpu = 0; cpu < cpus->nr; cpu++) { | 1050 | for (cpu = 0; cpu < cpus->nr; cpu++) { |
1029 | 1051 | ||
1030 | for (thread = 0; thread < threads->nr; thread++) { | 1052 | for (thread = 0; thread < nthreads; thread++) { |
1031 | int group_fd; | 1053 | int group_fd; |
1032 | 1054 | ||
1033 | if (!evsel->cgrp) | 1055 | if (!evsel->cgrp && !evsel->system_wide) |
1034 | pid = threads->map[thread]; | 1056 | pid = threads->map[thread]; |
1035 | 1057 | ||
1036 | group_fd = get_group_fd(evsel, cpu, thread); | 1058 | group_fd = get_group_fd(evsel, cpu, thread); |
@@ -1103,7 +1125,7 @@ out_close: | |||
1103 | close(FD(evsel, cpu, thread)); | 1125 | close(FD(evsel, cpu, thread)); |
1104 | FD(evsel, cpu, thread) = -1; | 1126 | FD(evsel, cpu, thread) = -1; |
1105 | } | 1127 | } |
1106 | thread = threads->nr; | 1128 | thread = nthreads; |
1107 | } while (--cpu >= 0); | 1129 | } while (--cpu >= 0); |
1108 | return err; | 1130 | return err; |
1109 | } | 1131 | } |
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index d7f93ce0ebc1..7bc314be6a7b 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h | |||
@@ -85,6 +85,8 @@ struct perf_evsel { | |||
85 | bool needs_swap; | 85 | bool needs_swap; |
86 | bool no_aux_samples; | 86 | bool no_aux_samples; |
87 | bool immediate; | 87 | bool immediate; |
88 | bool system_wide; | ||
89 | bool tracking; | ||
88 | /* parse modifier helper */ | 90 | /* parse modifier helper */ |
89 | int exclude_GH; | 91 | int exclude_GH; |
90 | int nr_members; | 92 | int nr_members; |
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 30df6187ee02..86569fa3651d 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c | |||
@@ -277,6 +277,28 @@ void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel) | |||
277 | } | 277 | } |
278 | } | 278 | } |
279 | 279 | ||
280 | void hists__delete_entries(struct hists *hists) | ||
281 | { | ||
282 | struct rb_node *next = rb_first(&hists->entries); | ||
283 | struct hist_entry *n; | ||
284 | |||
285 | while (next) { | ||
286 | n = rb_entry(next, struct hist_entry, rb_node); | ||
287 | next = rb_next(&n->rb_node); | ||
288 | |||
289 | rb_erase(&n->rb_node, &hists->entries); | ||
290 | |||
291 | if (sort__need_collapse) | ||
292 | rb_erase(&n->rb_node_in, &hists->entries_collapsed); | ||
293 | |||
294 | --hists->nr_entries; | ||
295 | if (!n->filtered) | ||
296 | --hists->nr_non_filtered_entries; | ||
297 | |||
298 | hist_entry__free(n); | ||
299 | } | ||
300 | } | ||
301 | |||
280 | /* | 302 | /* |
281 | * histogram, sorted on item, collects periods | 303 | * histogram, sorted on item, collects periods |
282 | */ | 304 | */ |
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 95405a8fbd95..8c9c70e18cbb 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h | |||
@@ -152,6 +152,7 @@ void hists__output_resort(struct hists *hists); | |||
152 | void hists__collapse_resort(struct hists *hists, struct ui_progress *prog); | 152 | void hists__collapse_resort(struct hists *hists, struct ui_progress *prog); |
153 | 153 | ||
154 | void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel); | 154 | void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel); |
155 | void hists__delete_entries(struct hists *hists); | ||
155 | void hists__output_recalc_col_len(struct hists *hists, int max_rows); | 156 | void hists__output_recalc_col_len(struct hists *hists, int max_rows); |
156 | 157 | ||
157 | u64 hists__total_period(struct hists *hists); | 158 | u64 hists__total_period(struct hists *hists); |
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 16bba9fff2c8..b093b93607fb 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c | |||
@@ -31,6 +31,7 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid) | |||
31 | 31 | ||
32 | machine->symbol_filter = NULL; | 32 | machine->symbol_filter = NULL; |
33 | machine->id_hdr_size = 0; | 33 | machine->id_hdr_size = 0; |
34 | machine->comm_exec = false; | ||
34 | 35 | ||
35 | machine->root_dir = strdup(root_dir); | 36 | machine->root_dir = strdup(root_dir); |
36 | if (machine->root_dir == NULL) | 37 | if (machine->root_dir == NULL) |
@@ -179,6 +180,19 @@ void machines__set_symbol_filter(struct machines *machines, | |||
179 | } | 180 | } |
180 | } | 181 | } |
181 | 182 | ||
183 | void machines__set_comm_exec(struct machines *machines, bool comm_exec) | ||
184 | { | ||
185 | struct rb_node *nd; | ||
186 | |||
187 | machines->host.comm_exec = comm_exec; | ||
188 | |||
189 | for (nd = rb_first(&machines->guests); nd; nd = rb_next(nd)) { | ||
190 | struct machine *machine = rb_entry(nd, struct machine, rb_node); | ||
191 | |||
192 | machine->comm_exec = comm_exec; | ||
193 | } | ||
194 | } | ||
195 | |||
182 | struct machine *machines__find(struct machines *machines, pid_t pid) | 196 | struct machine *machines__find(struct machines *machines, pid_t pid) |
183 | { | 197 | { |
184 | struct rb_node **p = &machines->guests.rb_node; | 198 | struct rb_node **p = &machines->guests.rb_node; |
@@ -398,17 +412,31 @@ struct thread *machine__find_thread(struct machine *machine, pid_t pid, | |||
398 | return __machine__findnew_thread(machine, pid, tid, false); | 412 | return __machine__findnew_thread(machine, pid, tid, false); |
399 | } | 413 | } |
400 | 414 | ||
415 | struct comm *machine__thread_exec_comm(struct machine *machine, | ||
416 | struct thread *thread) | ||
417 | { | ||
418 | if (machine->comm_exec) | ||
419 | return thread__exec_comm(thread); | ||
420 | else | ||
421 | return thread__comm(thread); | ||
422 | } | ||
423 | |||
401 | int machine__process_comm_event(struct machine *machine, union perf_event *event, | 424 | int machine__process_comm_event(struct machine *machine, union perf_event *event, |
402 | struct perf_sample *sample) | 425 | struct perf_sample *sample) |
403 | { | 426 | { |
404 | struct thread *thread = machine__findnew_thread(machine, | 427 | struct thread *thread = machine__findnew_thread(machine, |
405 | event->comm.pid, | 428 | event->comm.pid, |
406 | event->comm.tid); | 429 | event->comm.tid); |
430 | bool exec = event->header.misc & PERF_RECORD_MISC_COMM_EXEC; | ||
431 | |||
432 | if (exec) | ||
433 | machine->comm_exec = true; | ||
407 | 434 | ||
408 | if (dump_trace) | 435 | if (dump_trace) |
409 | perf_event__fprintf_comm(event, stdout); | 436 | perf_event__fprintf_comm(event, stdout); |
410 | 437 | ||
411 | if (thread == NULL || thread__set_comm(thread, event->comm.comm, sample->time)) { | 438 | if (thread == NULL || |
439 | __thread__set_comm(thread, event->comm.comm, sample->time, exec)) { | ||
412 | dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n"); | 440 | dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n"); |
413 | return -1; | 441 | return -1; |
414 | } | 442 | } |
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h index b972824e6294..61216e028319 100644 --- a/tools/perf/util/machine.h +++ b/tools/perf/util/machine.h | |||
@@ -26,6 +26,7 @@ struct machine { | |||
26 | struct rb_node rb_node; | 26 | struct rb_node rb_node; |
27 | pid_t pid; | 27 | pid_t pid; |
28 | u16 id_hdr_size; | 28 | u16 id_hdr_size; |
29 | bool comm_exec; | ||
29 | char *root_dir; | 30 | char *root_dir; |
30 | struct rb_root threads; | 31 | struct rb_root threads; |
31 | struct list_head dead_threads; | 32 | struct list_head dead_threads; |
@@ -47,6 +48,8 @@ struct map *machine__kernel_map(struct machine *machine, enum map_type type) | |||
47 | 48 | ||
48 | struct thread *machine__find_thread(struct machine *machine, pid_t pid, | 49 | struct thread *machine__find_thread(struct machine *machine, pid_t pid, |
49 | pid_t tid); | 50 | pid_t tid); |
51 | struct comm *machine__thread_exec_comm(struct machine *machine, | ||
52 | struct thread *thread); | ||
50 | 53 | ||
51 | int machine__process_comm_event(struct machine *machine, union perf_event *event, | 54 | int machine__process_comm_event(struct machine *machine, union perf_event *event, |
52 | struct perf_sample *sample); | 55 | struct perf_sample *sample); |
@@ -88,6 +91,7 @@ char *machine__mmap_name(struct machine *machine, char *bf, size_t size); | |||
88 | 91 | ||
89 | void machines__set_symbol_filter(struct machines *machines, | 92 | void machines__set_symbol_filter(struct machines *machines, |
90 | symbol_filter_t symbol_filter); | 93 | symbol_filter_t symbol_filter); |
94 | void machines__set_comm_exec(struct machines *machines, bool comm_exec); | ||
91 | 95 | ||
92 | struct machine *machine__new_host(void); | 96 | struct machine *machine__new_host(void); |
93 | int machine__init(struct machine *machine, const char *root_dir, pid_t pid); | 97 | int machine__init(struct machine *machine, const char *root_dir, pid_t pid); |
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 9a0a1839a377..784ea42ad8cb 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c | |||
@@ -79,7 +79,7 @@ static int init_symbol_maps(bool user_only) | |||
79 | int ret; | 79 | int ret; |
80 | 80 | ||
81 | symbol_conf.sort_by_name = true; | 81 | symbol_conf.sort_by_name = true; |
82 | ret = symbol__init(); | 82 | ret = symbol__init(NULL); |
83 | if (ret < 0) { | 83 | if (ret < 0) { |
84 | pr_debug("Failed to init symbol map.\n"); | 84 | pr_debug("Failed to init symbol map.\n"); |
85 | goto out; | 85 | goto out; |
@@ -1780,10 +1780,11 @@ static void clear_probe_trace_event(struct probe_trace_event *tev) | |||
1780 | memset(tev, 0, sizeof(*tev)); | 1780 | memset(tev, 0, sizeof(*tev)); |
1781 | } | 1781 | } |
1782 | 1782 | ||
1783 | static void print_warn_msg(const char *file, bool is_kprobe) | 1783 | static void print_open_warning(int err, bool is_kprobe) |
1784 | { | 1784 | { |
1785 | char sbuf[128]; | ||
1785 | 1786 | ||
1786 | if (errno == ENOENT) { | 1787 | if (err == -ENOENT) { |
1787 | const char *config; | 1788 | const char *config; |
1788 | 1789 | ||
1789 | if (!is_kprobe) | 1790 | if (!is_kprobe) |
@@ -1791,25 +1792,43 @@ static void print_warn_msg(const char *file, bool is_kprobe) | |||
1791 | else | 1792 | else |
1792 | config = "CONFIG_KPROBE_EVENTS"; | 1793 | config = "CONFIG_KPROBE_EVENTS"; |
1793 | 1794 | ||
1794 | pr_warning("%s file does not exist - please rebuild kernel" | 1795 | pr_warning("%cprobe_events file does not exist" |
1795 | " with %s.\n", file, config); | 1796 | " - please rebuild kernel with %s.\n", |
1796 | } else | 1797 | is_kprobe ? 'k' : 'u', config); |
1797 | pr_warning("Failed to open %s file: %s\n", file, | 1798 | } else if (err == -ENOTSUP) |
1798 | strerror(errno)); | 1799 | pr_warning("Debugfs is not mounted.\n"); |
1800 | else | ||
1801 | pr_warning("Failed to open %cprobe_events: %s\n", | ||
1802 | is_kprobe ? 'k' : 'u', | ||
1803 | strerror_r(-err, sbuf, sizeof(sbuf))); | ||
1799 | } | 1804 | } |
1800 | 1805 | ||
1801 | static int open_probe_events(const char *trace_file, bool readwrite, | 1806 | static void print_both_open_warning(int kerr, int uerr) |
1802 | bool is_kprobe) | 1807 | { |
1808 | /* Both kprobes and uprobes are disabled, warn it. */ | ||
1809 | if (kerr == -ENOTSUP && uerr == -ENOTSUP) | ||
1810 | pr_warning("Debugfs is not mounted.\n"); | ||
1811 | else if (kerr == -ENOENT && uerr == -ENOENT) | ||
1812 | pr_warning("Please rebuild kernel with CONFIG_KPROBE_EVENTS " | ||
1813 | "or/and CONFIG_UPROBE_EVENTS.\n"); | ||
1814 | else { | ||
1815 | char sbuf[128]; | ||
1816 | pr_warning("Failed to open kprobe events: %s.\n", | ||
1817 | strerror_r(-kerr, sbuf, sizeof(sbuf))); | ||
1818 | pr_warning("Failed to open uprobe events: %s.\n", | ||
1819 | strerror_r(-uerr, sbuf, sizeof(sbuf))); | ||
1820 | } | ||
1821 | } | ||
1822 | |||
1823 | static int open_probe_events(const char *trace_file, bool readwrite) | ||
1803 | { | 1824 | { |
1804 | char buf[PATH_MAX]; | 1825 | char buf[PATH_MAX]; |
1805 | const char *__debugfs; | 1826 | const char *__debugfs; |
1806 | int ret; | 1827 | int ret; |
1807 | 1828 | ||
1808 | __debugfs = debugfs_find_mountpoint(); | 1829 | __debugfs = debugfs_find_mountpoint(); |
1809 | if (__debugfs == NULL) { | 1830 | if (__debugfs == NULL) |
1810 | pr_warning("Debugfs is not mounted.\n"); | 1831 | return -ENOTSUP; |
1811 | return -ENOENT; | ||
1812 | } | ||
1813 | 1832 | ||
1814 | ret = e_snprintf(buf, PATH_MAX, "%s/%s", __debugfs, trace_file); | 1833 | ret = e_snprintf(buf, PATH_MAX, "%s/%s", __debugfs, trace_file); |
1815 | if (ret >= 0) { | 1834 | if (ret >= 0) { |
@@ -1820,19 +1839,19 @@ static int open_probe_events(const char *trace_file, bool readwrite, | |||
1820 | ret = open(buf, O_RDONLY, 0); | 1839 | ret = open(buf, O_RDONLY, 0); |
1821 | 1840 | ||
1822 | if (ret < 0) | 1841 | if (ret < 0) |
1823 | print_warn_msg(buf, is_kprobe); | 1842 | ret = -errno; |
1824 | } | 1843 | } |
1825 | return ret; | 1844 | return ret; |
1826 | } | 1845 | } |
1827 | 1846 | ||
1828 | static int open_kprobe_events(bool readwrite) | 1847 | static int open_kprobe_events(bool readwrite) |
1829 | { | 1848 | { |
1830 | return open_probe_events("tracing/kprobe_events", readwrite, true); | 1849 | return open_probe_events("tracing/kprobe_events", readwrite); |
1831 | } | 1850 | } |
1832 | 1851 | ||
1833 | static int open_uprobe_events(bool readwrite) | 1852 | static int open_uprobe_events(bool readwrite) |
1834 | { | 1853 | { |
1835 | return open_probe_events("tracing/uprobe_events", readwrite, false); | 1854 | return open_probe_events("tracing/uprobe_events", readwrite); |
1836 | } | 1855 | } |
1837 | 1856 | ||
1838 | /* Get raw string list of current kprobe_events or uprobe_events */ | 1857 | /* Get raw string list of current kprobe_events or uprobe_events */ |
@@ -1940,27 +1959,34 @@ static int __show_perf_probe_events(int fd, bool is_kprobe) | |||
1940 | /* List up current perf-probe events */ | 1959 | /* List up current perf-probe events */ |
1941 | int show_perf_probe_events(void) | 1960 | int show_perf_probe_events(void) |
1942 | { | 1961 | { |
1943 | int fd, ret; | 1962 | int kp_fd, up_fd, ret; |
1944 | 1963 | ||
1945 | setup_pager(); | 1964 | setup_pager(); |
1946 | fd = open_kprobe_events(false); | ||
1947 | |||
1948 | if (fd < 0) | ||
1949 | return fd; | ||
1950 | 1965 | ||
1951 | ret = init_symbol_maps(false); | 1966 | ret = init_symbol_maps(false); |
1952 | if (ret < 0) | 1967 | if (ret < 0) |
1953 | return ret; | 1968 | return ret; |
1954 | 1969 | ||
1955 | ret = __show_perf_probe_events(fd, true); | 1970 | kp_fd = open_kprobe_events(false); |
1956 | close(fd); | 1971 | if (kp_fd >= 0) { |
1972 | ret = __show_perf_probe_events(kp_fd, true); | ||
1973 | close(kp_fd); | ||
1974 | if (ret < 0) | ||
1975 | goto out; | ||
1976 | } | ||
1957 | 1977 | ||
1958 | fd = open_uprobe_events(false); | 1978 | up_fd = open_uprobe_events(false); |
1959 | if (fd >= 0) { | 1979 | if (kp_fd < 0 && up_fd < 0) { |
1960 | ret = __show_perf_probe_events(fd, false); | 1980 | print_both_open_warning(kp_fd, up_fd); |
1961 | close(fd); | 1981 | ret = kp_fd; |
1982 | goto out; | ||
1962 | } | 1983 | } |
1963 | 1984 | ||
1985 | if (up_fd >= 0) { | ||
1986 | ret = __show_perf_probe_events(up_fd, false); | ||
1987 | close(up_fd); | ||
1988 | } | ||
1989 | out: | ||
1964 | exit_symbol_maps(); | 1990 | exit_symbol_maps(); |
1965 | return ret; | 1991 | return ret; |
1966 | } | 1992 | } |
@@ -2075,8 +2101,11 @@ static int __add_probe_trace_events(struct perf_probe_event *pev, | |||
2075 | else | 2101 | else |
2076 | fd = open_kprobe_events(true); | 2102 | fd = open_kprobe_events(true); |
2077 | 2103 | ||
2078 | if (fd < 0) | 2104 | if (fd < 0) { |
2105 | print_open_warning(fd, !pev->uprobes); | ||
2079 | return fd; | 2106 | return fd; |
2107 | } | ||
2108 | |||
2080 | /* Get current event names */ | 2109 | /* Get current event names */ |
2081 | namelist = get_probe_trace_event_names(fd, false); | 2110 | namelist = get_probe_trace_event_names(fd, false); |
2082 | if (!namelist) { | 2111 | if (!namelist) { |
@@ -2449,15 +2478,18 @@ int del_perf_probe_events(struct strlist *dellist) | |||
2449 | 2478 | ||
2450 | /* Get current event names */ | 2479 | /* Get current event names */ |
2451 | kfd = open_kprobe_events(true); | 2480 | kfd = open_kprobe_events(true); |
2452 | if (kfd < 0) | 2481 | if (kfd >= 0) |
2453 | return kfd; | 2482 | namelist = get_probe_trace_event_names(kfd, true); |
2454 | 2483 | ||
2455 | namelist = get_probe_trace_event_names(kfd, true); | ||
2456 | ufd = open_uprobe_events(true); | 2484 | ufd = open_uprobe_events(true); |
2457 | |||
2458 | if (ufd >= 0) | 2485 | if (ufd >= 0) |
2459 | unamelist = get_probe_trace_event_names(ufd, true); | 2486 | unamelist = get_probe_trace_event_names(ufd, true); |
2460 | 2487 | ||
2488 | if (kfd < 0 && ufd < 0) { | ||
2489 | print_both_open_warning(kfd, ufd); | ||
2490 | goto error; | ||
2491 | } | ||
2492 | |||
2461 | if (namelist == NULL && unamelist == NULL) | 2493 | if (namelist == NULL && unamelist == NULL) |
2462 | goto error; | 2494 | goto error; |
2463 | 2495 | ||
diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c index fe8079edbdc1..cf69325b985f 100644 --- a/tools/perf/util/record.c +++ b/tools/perf/util/record.c | |||
@@ -14,6 +14,7 @@ static int perf_do_probe_api(setup_probe_fn_t fn, int cpu, const char *str) | |||
14 | struct perf_evsel *evsel; | 14 | struct perf_evsel *evsel; |
15 | unsigned long flags = perf_event_open_cloexec_flag(); | 15 | unsigned long flags = perf_event_open_cloexec_flag(); |
16 | int err = -EAGAIN, fd; | 16 | int err = -EAGAIN, fd; |
17 | static pid_t pid = -1; | ||
17 | 18 | ||
18 | evlist = perf_evlist__new(); | 19 | evlist = perf_evlist__new(); |
19 | if (!evlist) | 20 | if (!evlist) |
@@ -24,14 +25,22 @@ static int perf_do_probe_api(setup_probe_fn_t fn, int cpu, const char *str) | |||
24 | 25 | ||
25 | evsel = perf_evlist__first(evlist); | 26 | evsel = perf_evlist__first(evlist); |
26 | 27 | ||
27 | fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, flags); | 28 | while (1) { |
28 | if (fd < 0) | 29 | fd = sys_perf_event_open(&evsel->attr, pid, cpu, -1, flags); |
29 | goto out_delete; | 30 | if (fd < 0) { |
31 | if (pid == -1 && errno == EACCES) { | ||
32 | pid = 0; | ||
33 | continue; | ||
34 | } | ||
35 | goto out_delete; | ||
36 | } | ||
37 | break; | ||
38 | } | ||
30 | close(fd); | 39 | close(fd); |
31 | 40 | ||
32 | fn(evsel); | 41 | fn(evsel); |
33 | 42 | ||
34 | fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, flags); | 43 | fd = sys_perf_event_open(&evsel->attr, pid, cpu, -1, flags); |
35 | if (fd < 0) { | 44 | if (fd < 0) { |
36 | if (errno == EINVAL) | 45 | if (errno == EINVAL) |
37 | err = -EINVAL; | 46 | err = -EINVAL; |
@@ -47,7 +56,7 @@ out_delete: | |||
47 | 56 | ||
48 | static bool perf_probe_api(setup_probe_fn_t fn) | 57 | static bool perf_probe_api(setup_probe_fn_t fn) |
49 | { | 58 | { |
50 | const char *try[] = {"cycles:u", "instructions:u", "cpu-clock", NULL}; | 59 | const char *try[] = {"cycles:u", "instructions:u", "cpu-clock:u", NULL}; |
51 | struct cpu_map *cpus; | 60 | struct cpu_map *cpus; |
52 | int cpu, ret, i = 0; | 61 | int cpu, ret, i = 0; |
53 | 62 | ||
@@ -106,7 +115,7 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts) | |||
106 | 115 | ||
107 | evlist__for_each(evlist, evsel) { | 116 | evlist__for_each(evlist, evsel) { |
108 | perf_evsel__config(evsel, opts); | 117 | perf_evsel__config(evsel, opts); |
109 | if (!evsel->idx && use_comm_exec) | 118 | if (evsel->tracking && use_comm_exec) |
110 | evsel->attr.comm_exec = 1; | 119 | evsel->attr.comm_exec = 1; |
111 | } | 120 | } |
112 | 121 | ||
@@ -201,6 +210,7 @@ bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str) | |||
201 | struct perf_evsel *evsel; | 210 | struct perf_evsel *evsel; |
202 | int err, fd, cpu; | 211 | int err, fd, cpu; |
203 | bool ret = false; | 212 | bool ret = false; |
213 | pid_t pid = -1; | ||
204 | 214 | ||
205 | temp_evlist = perf_evlist__new(); | 215 | temp_evlist = perf_evlist__new(); |
206 | if (!temp_evlist) | 216 | if (!temp_evlist) |
@@ -221,12 +231,20 @@ bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str) | |||
221 | cpu = evlist->cpus->map[0]; | 231 | cpu = evlist->cpus->map[0]; |
222 | } | 232 | } |
223 | 233 | ||
224 | fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, | 234 | while (1) { |
225 | perf_event_open_cloexec_flag()); | 235 | fd = sys_perf_event_open(&evsel->attr, pid, cpu, -1, |
226 | if (fd >= 0) { | 236 | perf_event_open_cloexec_flag()); |
227 | close(fd); | 237 | if (fd < 0) { |
228 | ret = true; | 238 | if (pid == -1 && errno == EACCES) { |
239 | pid = 0; | ||
240 | continue; | ||
241 | } | ||
242 | goto out_delete; | ||
243 | } | ||
244 | break; | ||
229 | } | 245 | } |
246 | close(fd); | ||
247 | ret = true; | ||
230 | 248 | ||
231 | out_delete: | 249 | out_delete: |
232 | perf_evlist__delete(temp_evlist); | 250 | perf_evlist__delete(temp_evlist); |
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index cbce2545da45..26e5f14239ed 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c | |||
@@ -73,6 +73,35 @@ static void pydict_set_item_string_decref(PyObject *dict, const char *key, PyObj | |||
73 | Py_DECREF(val); | 73 | Py_DECREF(val); |
74 | } | 74 | } |
75 | 75 | ||
76 | static PyObject *get_handler(const char *handler_name) | ||
77 | { | ||
78 | PyObject *handler; | ||
79 | |||
80 | handler = PyDict_GetItemString(main_dict, handler_name); | ||
81 | if (handler && !PyCallable_Check(handler)) | ||
82 | return NULL; | ||
83 | return handler; | ||
84 | } | ||
85 | |||
86 | static void call_object(PyObject *handler, PyObject *args, const char *die_msg) | ||
87 | { | ||
88 | PyObject *retval; | ||
89 | |||
90 | retval = PyObject_CallObject(handler, args); | ||
91 | if (retval == NULL) | ||
92 | handler_call_die(die_msg); | ||
93 | Py_DECREF(retval); | ||
94 | } | ||
95 | |||
96 | static void try_call_object(const char *handler_name, PyObject *args) | ||
97 | { | ||
98 | PyObject *handler; | ||
99 | |||
100 | handler = get_handler(handler_name); | ||
101 | if (handler) | ||
102 | call_object(handler, args, handler_name); | ||
103 | } | ||
104 | |||
76 | static void define_value(enum print_arg_type field_type, | 105 | static void define_value(enum print_arg_type field_type, |
77 | const char *ev_name, | 106 | const char *ev_name, |
78 | const char *field_name, | 107 | const char *field_name, |
@@ -80,7 +109,7 @@ static void define_value(enum print_arg_type field_type, | |||
80 | const char *field_str) | 109 | const char *field_str) |
81 | { | 110 | { |
82 | const char *handler_name = "define_flag_value"; | 111 | const char *handler_name = "define_flag_value"; |
83 | PyObject *handler, *t, *retval; | 112 | PyObject *t; |
84 | unsigned long long value; | 113 | unsigned long long value; |
85 | unsigned n = 0; | 114 | unsigned n = 0; |
86 | 115 | ||
@@ -98,13 +127,7 @@ static void define_value(enum print_arg_type field_type, | |||
98 | PyTuple_SetItem(t, n++, PyInt_FromLong(value)); | 127 | PyTuple_SetItem(t, n++, PyInt_FromLong(value)); |
99 | PyTuple_SetItem(t, n++, PyString_FromString(field_str)); | 128 | PyTuple_SetItem(t, n++, PyString_FromString(field_str)); |
100 | 129 | ||
101 | handler = PyDict_GetItemString(main_dict, handler_name); | 130 | try_call_object(handler_name, t); |
102 | if (handler && PyCallable_Check(handler)) { | ||
103 | retval = PyObject_CallObject(handler, t); | ||
104 | if (retval == NULL) | ||
105 | handler_call_die(handler_name); | ||
106 | Py_DECREF(retval); | ||
107 | } | ||
108 | 131 | ||
109 | Py_DECREF(t); | 132 | Py_DECREF(t); |
110 | } | 133 | } |
@@ -127,7 +150,7 @@ static void define_field(enum print_arg_type field_type, | |||
127 | const char *delim) | 150 | const char *delim) |
128 | { | 151 | { |
129 | const char *handler_name = "define_flag_field"; | 152 | const char *handler_name = "define_flag_field"; |
130 | PyObject *handler, *t, *retval; | 153 | PyObject *t; |
131 | unsigned n = 0; | 154 | unsigned n = 0; |
132 | 155 | ||
133 | if (field_type == PRINT_SYMBOL) | 156 | if (field_type == PRINT_SYMBOL) |
@@ -145,13 +168,7 @@ static void define_field(enum print_arg_type field_type, | |||
145 | if (field_type == PRINT_FLAGS) | 168 | if (field_type == PRINT_FLAGS) |
146 | PyTuple_SetItem(t, n++, PyString_FromString(delim)); | 169 | PyTuple_SetItem(t, n++, PyString_FromString(delim)); |
147 | 170 | ||
148 | handler = PyDict_GetItemString(main_dict, handler_name); | 171 | try_call_object(handler_name, t); |
149 | if (handler && PyCallable_Check(handler)) { | ||
150 | retval = PyObject_CallObject(handler, t); | ||
151 | if (retval == NULL) | ||
152 | handler_call_die(handler_name); | ||
153 | Py_DECREF(retval); | ||
154 | } | ||
155 | 172 | ||
156 | Py_DECREF(t); | 173 | Py_DECREF(t); |
157 | } | 174 | } |
@@ -362,7 +379,7 @@ static void python_process_tracepoint(struct perf_sample *sample, | |||
362 | struct thread *thread, | 379 | struct thread *thread, |
363 | struct addr_location *al) | 380 | struct addr_location *al) |
364 | { | 381 | { |
365 | PyObject *handler, *retval, *context, *t, *obj, *callchain; | 382 | PyObject *handler, *context, *t, *obj, *callchain; |
366 | PyObject *dict = NULL; | 383 | PyObject *dict = NULL; |
367 | static char handler_name[256]; | 384 | static char handler_name[256]; |
368 | struct format_field *field; | 385 | struct format_field *field; |
@@ -387,9 +404,7 @@ static void python_process_tracepoint(struct perf_sample *sample, | |||
387 | 404 | ||
388 | sprintf(handler_name, "%s__%s", event->system, event->name); | 405 | sprintf(handler_name, "%s__%s", event->system, event->name); |
389 | 406 | ||
390 | handler = PyDict_GetItemString(main_dict, handler_name); | 407 | handler = get_handler(handler_name); |
391 | if (handler && !PyCallable_Check(handler)) | ||
392 | handler = NULL; | ||
393 | if (!handler) { | 408 | if (!handler) { |
394 | dict = PyDict_New(); | 409 | dict = PyDict_New(); |
395 | if (!dict) | 410 | if (!dict) |
@@ -450,19 +465,9 @@ static void python_process_tracepoint(struct perf_sample *sample, | |||
450 | Py_FatalError("error resizing Python tuple"); | 465 | Py_FatalError("error resizing Python tuple"); |
451 | 466 | ||
452 | if (handler) { | 467 | if (handler) { |
453 | retval = PyObject_CallObject(handler, t); | 468 | call_object(handler, t, handler_name); |
454 | if (retval == NULL) | ||
455 | handler_call_die(handler_name); | ||
456 | Py_DECREF(retval); | ||
457 | } else { | 469 | } else { |
458 | handler = PyDict_GetItemString(main_dict, "trace_unhandled"); | 470 | try_call_object("trace_unhandled", t); |
459 | if (handler && PyCallable_Check(handler)) { | ||
460 | |||
461 | retval = PyObject_CallObject(handler, t); | ||
462 | if (retval == NULL) | ||
463 | handler_call_die("trace_unhandled"); | ||
464 | Py_DECREF(retval); | ||
465 | } | ||
466 | Py_DECREF(dict); | 471 | Py_DECREF(dict); |
467 | } | 472 | } |
468 | 473 | ||
@@ -474,7 +479,7 @@ static void python_process_general_event(struct perf_sample *sample, | |||
474 | struct thread *thread, | 479 | struct thread *thread, |
475 | struct addr_location *al) | 480 | struct addr_location *al) |
476 | { | 481 | { |
477 | PyObject *handler, *retval, *t, *dict, *callchain, *dict_sample; | 482 | PyObject *handler, *t, *dict, *callchain, *dict_sample; |
478 | static char handler_name[64]; | 483 | static char handler_name[64]; |
479 | unsigned n = 0; | 484 | unsigned n = 0; |
480 | 485 | ||
@@ -496,8 +501,8 @@ static void python_process_general_event(struct perf_sample *sample, | |||
496 | 501 | ||
497 | snprintf(handler_name, sizeof(handler_name), "%s", "process_event"); | 502 | snprintf(handler_name, sizeof(handler_name), "%s", "process_event"); |
498 | 503 | ||
499 | handler = PyDict_GetItemString(main_dict, handler_name); | 504 | handler = get_handler(handler_name); |
500 | if (!handler || !PyCallable_Check(handler)) | 505 | if (!handler) |
501 | goto exit; | 506 | goto exit; |
502 | 507 | ||
503 | pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel))); | 508 | pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel))); |
@@ -539,10 +544,7 @@ static void python_process_general_event(struct perf_sample *sample, | |||
539 | if (_PyTuple_Resize(&t, n) == -1) | 544 | if (_PyTuple_Resize(&t, n) == -1) |
540 | Py_FatalError("error resizing Python tuple"); | 545 | Py_FatalError("error resizing Python tuple"); |
541 | 546 | ||
542 | retval = PyObject_CallObject(handler, t); | 547 | call_object(handler, t, handler_name); |
543 | if (retval == NULL) | ||
544 | handler_call_die(handler_name); | ||
545 | Py_DECREF(retval); | ||
546 | exit: | 548 | exit: |
547 | Py_DECREF(dict); | 549 | Py_DECREF(dict); |
548 | Py_DECREF(t); | 550 | Py_DECREF(t); |
@@ -566,36 +568,24 @@ static void python_process_event(union perf_event *event __maybe_unused, | |||
566 | 568 | ||
567 | static int run_start_sub(void) | 569 | static int run_start_sub(void) |
568 | { | 570 | { |
569 | PyObject *handler, *retval; | ||
570 | int err = 0; | ||
571 | |||
572 | main_module = PyImport_AddModule("__main__"); | 571 | main_module = PyImport_AddModule("__main__"); |
573 | if (main_module == NULL) | 572 | if (main_module == NULL) |
574 | return -1; | 573 | return -1; |
575 | Py_INCREF(main_module); | 574 | Py_INCREF(main_module); |
576 | 575 | ||
577 | main_dict = PyModule_GetDict(main_module); | 576 | main_dict = PyModule_GetDict(main_module); |
578 | if (main_dict == NULL) { | 577 | if (main_dict == NULL) |
579 | err = -1; | ||
580 | goto error; | 578 | goto error; |
581 | } | ||
582 | Py_INCREF(main_dict); | 579 | Py_INCREF(main_dict); |
583 | 580 | ||
584 | handler = PyDict_GetItemString(main_dict, "trace_begin"); | 581 | try_call_object("trace_begin", NULL); |
585 | if (handler == NULL || !PyCallable_Check(handler)) | ||
586 | goto out; | ||
587 | 582 | ||
588 | retval = PyObject_CallObject(handler, NULL); | 583 | return 0; |
589 | if (retval == NULL) | ||
590 | handler_call_die("trace_begin"); | ||
591 | 584 | ||
592 | Py_DECREF(retval); | ||
593 | return err; | ||
594 | error: | 585 | error: |
595 | Py_XDECREF(main_dict); | 586 | Py_XDECREF(main_dict); |
596 | Py_XDECREF(main_module); | 587 | Py_XDECREF(main_module); |
597 | out: | 588 | return -1; |
598 | return err; | ||
599 | } | 589 | } |
600 | 590 | ||
601 | /* | 591 | /* |
@@ -654,23 +644,13 @@ error: | |||
654 | */ | 644 | */ |
655 | static int python_stop_script(void) | 645 | static int python_stop_script(void) |
656 | { | 646 | { |
657 | PyObject *handler, *retval; | 647 | try_call_object("trace_end", NULL); |
658 | int err = 0; | ||
659 | 648 | ||
660 | handler = PyDict_GetItemString(main_dict, "trace_end"); | ||
661 | if (handler == NULL || !PyCallable_Check(handler)) | ||
662 | goto out; | ||
663 | |||
664 | retval = PyObject_CallObject(handler, NULL); | ||
665 | if (retval == NULL) | ||
666 | handler_call_die("trace_end"); | ||
667 | Py_DECREF(retval); | ||
668 | out: | ||
669 | Py_XDECREF(main_dict); | 649 | Py_XDECREF(main_dict); |
670 | Py_XDECREF(main_module); | 650 | Py_XDECREF(main_module); |
671 | Py_Finalize(); | 651 | Py_Finalize(); |
672 | 652 | ||
673 | return err; | 653 | return 0; |
674 | } | 654 | } |
675 | 655 | ||
676 | static int python_generate_script(struct pevent *pevent, const char *outfile) | 656 | static int python_generate_script(struct pevent *pevent, const char *outfile) |
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 7e27f1eb260c..6d2d50dea1d8 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
@@ -67,6 +67,25 @@ static void perf_session__destroy_kernel_maps(struct perf_session *session) | |||
67 | machines__destroy_kernel_maps(&session->machines); | 67 | machines__destroy_kernel_maps(&session->machines); |
68 | } | 68 | } |
69 | 69 | ||
70 | static bool perf_session__has_comm_exec(struct perf_session *session) | ||
71 | { | ||
72 | struct perf_evsel *evsel; | ||
73 | |||
74 | evlist__for_each(session->evlist, evsel) { | ||
75 | if (evsel->attr.comm_exec) | ||
76 | return true; | ||
77 | } | ||
78 | |||
79 | return false; | ||
80 | } | ||
81 | |||
82 | static void perf_session__set_comm_exec(struct perf_session *session) | ||
83 | { | ||
84 | bool comm_exec = perf_session__has_comm_exec(session); | ||
85 | |||
86 | machines__set_comm_exec(&session->machines, comm_exec); | ||
87 | } | ||
88 | |||
70 | struct perf_session *perf_session__new(struct perf_data_file *file, | 89 | struct perf_session *perf_session__new(struct perf_data_file *file, |
71 | bool repipe, struct perf_tool *tool) | 90 | bool repipe, struct perf_tool *tool) |
72 | { | 91 | { |
@@ -90,6 +109,7 @@ struct perf_session *perf_session__new(struct perf_data_file *file, | |||
90 | goto out_close; | 109 | goto out_close; |
91 | 110 | ||
92 | perf_session__set_id_hdr_size(session); | 111 | perf_session__set_id_hdr_size(session); |
112 | perf_session__set_comm_exec(session); | ||
93 | } | 113 | } |
94 | } | 114 | } |
95 | 115 | ||
@@ -866,8 +886,10 @@ static s64 perf_session__process_user_event(struct perf_session *session, | |||
866 | switch (event->header.type) { | 886 | switch (event->header.type) { |
867 | case PERF_RECORD_HEADER_ATTR: | 887 | case PERF_RECORD_HEADER_ATTR: |
868 | err = tool->attr(tool, event, &session->evlist); | 888 | err = tool->attr(tool, event, &session->evlist); |
869 | if (err == 0) | 889 | if (err == 0) { |
870 | perf_session__set_id_hdr_size(session); | 890 | perf_session__set_id_hdr_size(session); |
891 | perf_session__set_comm_exec(session); | ||
892 | } | ||
871 | return err; | 893 | return err; |
872 | case PERF_RECORD_HEADER_EVENT_TYPE: | 894 | case PERF_RECORD_HEADER_EVENT_TYPE: |
873 | /* | 895 | /* |
@@ -897,6 +919,61 @@ static void event_swap(union perf_event *event, bool sample_id_all) | |||
897 | swap(event, sample_id_all); | 919 | swap(event, sample_id_all); |
898 | } | 920 | } |
899 | 921 | ||
922 | int perf_session__peek_event(struct perf_session *session, off_t file_offset, | ||
923 | void *buf, size_t buf_sz, | ||
924 | union perf_event **event_ptr, | ||
925 | struct perf_sample *sample) | ||
926 | { | ||
927 | union perf_event *event; | ||
928 | size_t hdr_sz, rest; | ||
929 | int fd; | ||
930 | |||
931 | if (session->one_mmap && !session->header.needs_swap) { | ||
932 | event = file_offset - session->one_mmap_offset + | ||
933 | session->one_mmap_addr; | ||
934 | goto out_parse_sample; | ||
935 | } | ||
936 | |||
937 | if (perf_data_file__is_pipe(session->file)) | ||
938 | return -1; | ||
939 | |||
940 | fd = perf_data_file__fd(session->file); | ||
941 | hdr_sz = sizeof(struct perf_event_header); | ||
942 | |||
943 | if (buf_sz < hdr_sz) | ||
944 | return -1; | ||
945 | |||
946 | if (lseek(fd, file_offset, SEEK_SET) == (off_t)-1 || | ||
947 | readn(fd, &buf, hdr_sz) != (ssize_t)hdr_sz) | ||
948 | return -1; | ||
949 | |||
950 | event = (union perf_event *)buf; | ||
951 | |||
952 | if (session->header.needs_swap) | ||
953 | perf_event_header__bswap(&event->header); | ||
954 | |||
955 | if (event->header.size < hdr_sz) | ||
956 | return -1; | ||
957 | |||
958 | rest = event->header.size - hdr_sz; | ||
959 | |||
960 | if (readn(fd, &buf, rest) != (ssize_t)rest) | ||
961 | return -1; | ||
962 | |||
963 | if (session->header.needs_swap) | ||
964 | event_swap(event, perf_evlist__sample_id_all(session->evlist)); | ||
965 | |||
966 | out_parse_sample: | ||
967 | |||
968 | if (sample && event->header.type < PERF_RECORD_USER_TYPE_START && | ||
969 | perf_evlist__parse_sample(session->evlist, event, sample)) | ||
970 | return -1; | ||
971 | |||
972 | *event_ptr = event; | ||
973 | |||
974 | return 0; | ||
975 | } | ||
976 | |||
900 | static s64 perf_session__process_event(struct perf_session *session, | 977 | static s64 perf_session__process_event(struct perf_session *session, |
901 | union perf_event *event, | 978 | union perf_event *event, |
902 | struct perf_tool *tool, | 979 | struct perf_tool *tool, |
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 0630e658f8be..8dd41cad2d59 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h | |||
@@ -45,6 +45,11 @@ void perf_session__delete(struct perf_session *session); | |||
45 | 45 | ||
46 | void perf_event_header__bswap(struct perf_event_header *hdr); | 46 | void perf_event_header__bswap(struct perf_event_header *hdr); |
47 | 47 | ||
48 | int perf_session__peek_event(struct perf_session *session, off_t file_offset, | ||
49 | void *buf, size_t buf_sz, | ||
50 | union perf_event **event_ptr, | ||
51 | struct perf_sample *sample); | ||
52 | |||
48 | int __perf_session__process_events(struct perf_session *session, | 53 | int __perf_session__process_events(struct perf_session *session, |
49 | u64 data_offset, u64 data_size, u64 size, | 54 | u64 data_offset, u64 data_size, u64 size, |
50 | struct perf_tool *tool); | 55 | struct perf_tool *tool); |
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index d75349979e65..9fb5e9e9f161 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c | |||
@@ -736,7 +736,7 @@ int dso__load_sym(struct dso *dso, struct map *map, | |||
736 | if (symstrs == NULL) | 736 | if (symstrs == NULL) |
737 | goto out_elf_end; | 737 | goto out_elf_end; |
738 | 738 | ||
739 | sec_strndx = elf_getscn(elf, ehdr.e_shstrndx); | 739 | sec_strndx = elf_getscn(runtime_ss->elf, runtime_ss->ehdr.e_shstrndx); |
740 | if (sec_strndx == NULL) | 740 | if (sec_strndx == NULL) |
741 | goto out_elf_end; | 741 | goto out_elf_end; |
742 | 742 | ||
@@ -939,8 +939,11 @@ new_symbol: | |||
939 | * to it... | 939 | * to it... |
940 | */ | 940 | */ |
941 | if (symbol_conf.demangle) { | 941 | if (symbol_conf.demangle) { |
942 | demangled = bfd_demangle(NULL, elf_name, | 942 | int demangle_flags = DMGL_NO_OPTS; |
943 | DMGL_PARAMS | DMGL_ANSI); | 943 | if (verbose) |
944 | demangle_flags = DMGL_PARAMS | DMGL_ANSI; | ||
945 | |||
946 | demangled = bfd_demangle(NULL, elf_name, demangle_flags); | ||
944 | if (demangled != NULL) | 947 | if (demangled != NULL) |
945 | elf_name = demangled; | 948 | elf_name = demangled; |
946 | } | 949 | } |
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index f134ec138934..ac098a3c2a31 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include "machine.h" | 15 | #include "machine.h" |
16 | #include "symbol.h" | 16 | #include "symbol.h" |
17 | #include "strlist.h" | 17 | #include "strlist.h" |
18 | #include "header.h" | ||
18 | 19 | ||
19 | #include <elf.h> | 20 | #include <elf.h> |
20 | #include <limits.h> | 21 | #include <limits.h> |
@@ -523,10 +524,15 @@ struct process_kallsyms_args { | |||
523 | struct dso *dso; | 524 | struct dso *dso; |
524 | }; | 525 | }; |
525 | 526 | ||
527 | /* | ||
528 | * These are symbols in the kernel image, so make sure that | ||
529 | * sym is from a kernel DSO. | ||
530 | */ | ||
526 | bool symbol__is_idle(struct symbol *sym) | 531 | bool symbol__is_idle(struct symbol *sym) |
527 | { | 532 | { |
528 | const char * const idle_symbols[] = { | 533 | const char * const idle_symbols[] = { |
529 | "cpu_idle", | 534 | "cpu_idle", |
535 | "cpu_startup_entry", | ||
530 | "intel_idle", | 536 | "intel_idle", |
531 | "default_idle", | 537 | "default_idle", |
532 | "native_safe_halt", | 538 | "native_safe_halt", |
@@ -1744,10 +1750,11 @@ static void vmlinux_path__exit(void) | |||
1744 | zfree(&vmlinux_path); | 1750 | zfree(&vmlinux_path); |
1745 | } | 1751 | } |
1746 | 1752 | ||
1747 | static int vmlinux_path__init(void) | 1753 | static int vmlinux_path__init(struct perf_session_env *env) |
1748 | { | 1754 | { |
1749 | struct utsname uts; | 1755 | struct utsname uts; |
1750 | char bf[PATH_MAX]; | 1756 | char bf[PATH_MAX]; |
1757 | char *kernel_version; | ||
1751 | 1758 | ||
1752 | vmlinux_path = malloc(sizeof(char *) * 5); | 1759 | vmlinux_path = malloc(sizeof(char *) * 5); |
1753 | if (vmlinux_path == NULL) | 1760 | if (vmlinux_path == NULL) |
@@ -1762,25 +1769,31 @@ static int vmlinux_path__init(void) | |||
1762 | goto out_fail; | 1769 | goto out_fail; |
1763 | ++vmlinux_path__nr_entries; | 1770 | ++vmlinux_path__nr_entries; |
1764 | 1771 | ||
1765 | /* only try running kernel version if no symfs was given */ | 1772 | /* only try kernel version if no symfs was given */ |
1766 | if (symbol_conf.symfs[0] != 0) | 1773 | if (symbol_conf.symfs[0] != 0) |
1767 | return 0; | 1774 | return 0; |
1768 | 1775 | ||
1769 | if (uname(&uts) < 0) | 1776 | if (env) { |
1770 | return -1; | 1777 | kernel_version = env->os_release; |
1778 | } else { | ||
1779 | if (uname(&uts) < 0) | ||
1780 | goto out_fail; | ||
1781 | |||
1782 | kernel_version = uts.release; | ||
1783 | } | ||
1771 | 1784 | ||
1772 | snprintf(bf, sizeof(bf), "/boot/vmlinux-%s", uts.release); | 1785 | snprintf(bf, sizeof(bf), "/boot/vmlinux-%s", kernel_version); |
1773 | vmlinux_path[vmlinux_path__nr_entries] = strdup(bf); | 1786 | vmlinux_path[vmlinux_path__nr_entries] = strdup(bf); |
1774 | if (vmlinux_path[vmlinux_path__nr_entries] == NULL) | 1787 | if (vmlinux_path[vmlinux_path__nr_entries] == NULL) |
1775 | goto out_fail; | 1788 | goto out_fail; |
1776 | ++vmlinux_path__nr_entries; | 1789 | ++vmlinux_path__nr_entries; |
1777 | snprintf(bf, sizeof(bf), "/lib/modules/%s/build/vmlinux", uts.release); | 1790 | snprintf(bf, sizeof(bf), "/lib/modules/%s/build/vmlinux", kernel_version); |
1778 | vmlinux_path[vmlinux_path__nr_entries] = strdup(bf); | 1791 | vmlinux_path[vmlinux_path__nr_entries] = strdup(bf); |
1779 | if (vmlinux_path[vmlinux_path__nr_entries] == NULL) | 1792 | if (vmlinux_path[vmlinux_path__nr_entries] == NULL) |
1780 | goto out_fail; | 1793 | goto out_fail; |
1781 | ++vmlinux_path__nr_entries; | 1794 | ++vmlinux_path__nr_entries; |
1782 | snprintf(bf, sizeof(bf), "/usr/lib/debug/lib/modules/%s/vmlinux", | 1795 | snprintf(bf, sizeof(bf), "/usr/lib/debug/lib/modules/%s/vmlinux", |
1783 | uts.release); | 1796 | kernel_version); |
1784 | vmlinux_path[vmlinux_path__nr_entries] = strdup(bf); | 1797 | vmlinux_path[vmlinux_path__nr_entries] = strdup(bf); |
1785 | if (vmlinux_path[vmlinux_path__nr_entries] == NULL) | 1798 | if (vmlinux_path[vmlinux_path__nr_entries] == NULL) |
1786 | goto out_fail; | 1799 | goto out_fail; |
@@ -1826,7 +1839,7 @@ static bool symbol__read_kptr_restrict(void) | |||
1826 | return value; | 1839 | return value; |
1827 | } | 1840 | } |
1828 | 1841 | ||
1829 | int symbol__init(void) | 1842 | int symbol__init(struct perf_session_env *env) |
1830 | { | 1843 | { |
1831 | const char *symfs; | 1844 | const char *symfs; |
1832 | 1845 | ||
@@ -1841,7 +1854,7 @@ int symbol__init(void) | |||
1841 | symbol_conf.priv_size += (sizeof(struct symbol_name_rb_node) - | 1854 | symbol_conf.priv_size += (sizeof(struct symbol_name_rb_node) - |
1842 | sizeof(struct symbol)); | 1855 | sizeof(struct symbol)); |
1843 | 1856 | ||
1844 | if (symbol_conf.try_vmlinux_path && vmlinux_path__init() < 0) | 1857 | if (symbol_conf.try_vmlinux_path && vmlinux_path__init(env) < 0) |
1845 | return -1; | 1858 | return -1; |
1846 | 1859 | ||
1847 | if (symbol_conf.field_sep && *symbol_conf.field_sep == '.') { | 1860 | if (symbol_conf.field_sep && *symbol_conf.field_sep == '.') { |
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 196b29104276..3f95ea0357e3 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h | |||
@@ -60,6 +60,7 @@ extern Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, | |||
60 | #endif | 60 | #endif |
61 | 61 | ||
62 | #ifndef DMGL_PARAMS | 62 | #ifndef DMGL_PARAMS |
63 | #define DMGL_NO_OPTS 0 /* For readability... */ | ||
63 | #define DMGL_PARAMS (1 << 0) /* Include function args */ | 64 | #define DMGL_PARAMS (1 << 0) /* Include function args */ |
64 | #define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */ | 65 | #define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */ |
65 | #endif | 66 | #endif |
@@ -262,7 +263,8 @@ int modules__parse(const char *filename, void *arg, | |||
262 | int filename__read_debuglink(const char *filename, char *debuglink, | 263 | int filename__read_debuglink(const char *filename, char *debuglink, |
263 | size_t size); | 264 | size_t size); |
264 | 265 | ||
265 | int symbol__init(void); | 266 | struct perf_session_env; |
267 | int symbol__init(struct perf_session_env *env); | ||
266 | void symbol__exit(void); | 268 | void symbol__exit(void); |
267 | void symbol__elf_init(void); | 269 | void symbol__elf_init(void); |
268 | struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name); | 270 | struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name); |
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index 12c7a253a63c..a9df7f2c6dc9 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c | |||
@@ -42,7 +42,7 @@ struct thread *thread__new(pid_t pid, pid_t tid) | |||
42 | goto err_thread; | 42 | goto err_thread; |
43 | 43 | ||
44 | snprintf(comm_str, 32, ":%d", tid); | 44 | snprintf(comm_str, 32, ":%d", tid); |
45 | comm = comm__new(comm_str, 0); | 45 | comm = comm__new(comm_str, 0, false); |
46 | free(comm_str); | 46 | free(comm_str); |
47 | if (!comm) | 47 | if (!comm) |
48 | goto err_thread; | 48 | goto err_thread; |
@@ -81,19 +81,33 @@ struct comm *thread__comm(const struct thread *thread) | |||
81 | return list_first_entry(&thread->comm_list, struct comm, list); | 81 | return list_first_entry(&thread->comm_list, struct comm, list); |
82 | } | 82 | } |
83 | 83 | ||
84 | struct comm *thread__exec_comm(const struct thread *thread) | ||
85 | { | ||
86 | struct comm *comm, *last = NULL; | ||
87 | |||
88 | list_for_each_entry(comm, &thread->comm_list, list) { | ||
89 | if (comm->exec) | ||
90 | return comm; | ||
91 | last = comm; | ||
92 | } | ||
93 | |||
94 | return last; | ||
95 | } | ||
96 | |||
84 | /* CHECKME: time should always be 0 if event aren't ordered */ | 97 | /* CHECKME: time should always be 0 if event aren't ordered */ |
85 | int thread__set_comm(struct thread *thread, const char *str, u64 timestamp) | 98 | int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp, |
99 | bool exec) | ||
86 | { | 100 | { |
87 | struct comm *new, *curr = thread__comm(thread); | 101 | struct comm *new, *curr = thread__comm(thread); |
88 | int err; | 102 | int err; |
89 | 103 | ||
90 | /* Override latest entry if it had no specific time coverage */ | 104 | /* Override latest entry if it had no specific time coverage */ |
91 | if (!curr->start) { | 105 | if (!curr->start && !curr->exec) { |
92 | err = comm__override(curr, str, timestamp); | 106 | err = comm__override(curr, str, timestamp, exec); |
93 | if (err) | 107 | if (err) |
94 | return err; | 108 | return err; |
95 | } else { | 109 | } else { |
96 | new = comm__new(str, timestamp); | 110 | new = comm__new(str, timestamp, exec); |
97 | if (!new) | 111 | if (!new) |
98 | return -ENOMEM; | 112 | return -ENOMEM; |
99 | list_add(&new->list, &thread->comm_list); | 113 | list_add(&new->list, &thread->comm_list); |
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h index 716b7723cce2..8c75fa774706 100644 --- a/tools/perf/util/thread.h +++ b/tools/perf/util/thread.h | |||
@@ -38,9 +38,17 @@ static inline void thread__exited(struct thread *thread) | |||
38 | thread->dead = true; | 38 | thread->dead = true; |
39 | } | 39 | } |
40 | 40 | ||
41 | int thread__set_comm(struct thread *thread, const char *comm, u64 timestamp); | 41 | int __thread__set_comm(struct thread *thread, const char *comm, u64 timestamp, |
42 | bool exec); | ||
43 | static inline int thread__set_comm(struct thread *thread, const char *comm, | ||
44 | u64 timestamp) | ||
45 | { | ||
46 | return __thread__set_comm(thread, comm, timestamp, false); | ||
47 | } | ||
48 | |||
42 | int thread__comm_len(struct thread *thread); | 49 | int thread__comm_len(struct thread *thread); |
43 | struct comm *thread__comm(const struct thread *thread); | 50 | struct comm *thread__comm(const struct thread *thread); |
51 | struct comm *thread__exec_comm(const struct thread *thread); | ||
44 | const char *thread__comm_str(const struct thread *thread); | 52 | const char *thread__comm_str(const struct thread *thread); |
45 | void thread__insert_map(struct thread *thread, struct map *map); | 53 | void thread__insert_map(struct thread *thread, struct map *map); |
46 | int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp); | 54 | int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp); |
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c index b82a93cb1694..25822bdf7bbf 100644 --- a/tools/perf/util/util.c +++ b/tools/perf/util/util.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <limits.h> | 13 | #include <limits.h> |
14 | #include <byteswap.h> | 14 | #include <byteswap.h> |
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | #include <unistd.h> | ||
16 | 17 | ||
17 | /* | 18 | /* |
18 | * XXX We need to find a better place for these things... | 19 | * XXX We need to find a better place for these things... |
@@ -282,6 +283,18 @@ void get_term_dimensions(struct winsize *ws) | |||
282 | ws->ws_col = 80; | 283 | ws->ws_col = 80; |
283 | } | 284 | } |
284 | 285 | ||
286 | void set_term_quiet_input(struct termios *old) | ||
287 | { | ||
288 | struct termios tc; | ||
289 | |||
290 | tcgetattr(0, old); | ||
291 | tc = *old; | ||
292 | tc.c_lflag &= ~(ICANON | ECHO); | ||
293 | tc.c_cc[VMIN] = 0; | ||
294 | tc.c_cc[VTIME] = 0; | ||
295 | tcsetattr(0, TCSANOW, &tc); | ||
296 | } | ||
297 | |||
285 | static void set_tracing_events_path(const char *mountpoint) | 298 | static void set_tracing_events_path(const char *mountpoint) |
286 | { | 299 | { |
287 | snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s", | 300 | snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s", |
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index 03a1ea2266b8..d6a79b1fb28c 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h | |||
@@ -75,6 +75,7 @@ | |||
75 | #include <api/fs/debugfs.h> | 75 | #include <api/fs/debugfs.h> |
76 | #include <termios.h> | 76 | #include <termios.h> |
77 | #include <linux/bitops.h> | 77 | #include <linux/bitops.h> |
78 | #include <termios.h> | ||
78 | 79 | ||
79 | extern const char *graph_line; | 80 | extern const char *graph_line; |
80 | extern const char *graph_dotted_line; | 81 | extern const char *graph_dotted_line; |
@@ -308,6 +309,7 @@ extern unsigned int page_size; | |||
308 | extern int cacheline_size; | 309 | extern int cacheline_size; |
309 | 310 | ||
310 | void get_term_dimensions(struct winsize *ws); | 311 | void get_term_dimensions(struct winsize *ws); |
312 | void set_term_quiet_input(struct termios *old); | ||
311 | 313 | ||
312 | struct parse_tag { | 314 | struct parse_tag { |
313 | char tag; | 315 | char tag; |