diff options
author | Ingo Molnar <mingo@kernel.org> | 2012-09-13 17:11:19 +0200 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2012-09-13 17:11:19 +0200 |
commit | be267be8b191d5fac9f65a29e047470f364315eb (patch) | |
tree | 80cdb3f7c1d53fc6209fac2d57ff9a4052e2750e | |
parent | d5cb2aef4fda355fbafe8db4f425b73ea94d2019 (diff) | |
parent | 9ec3f4e437ede2f3b5087d412abe16a0219b3b99 (diff) | |
download | op-kernel-dev-be267be8b191d5fac9f65a29e047470f364315eb.zip op-kernel-dev-be267be8b191d5fac9f65a29e047470f364315eb.tar.gz |
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:
* Remove die()/exit() calls from several tools.
* Add missing perf_regs.h file to MANIFEST
* Clean up and improve 'perf sched' performance by elliminating lots of
needless calls to libtraceevent.
* More patches to make perf build on Android, from Irina Tirdea
* Resolve vdso callchains, from Jiri Olsa
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
92 files changed, 1518 insertions, 1231 deletions
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index f4190b5..2c54cdd 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c @@ -1824,7 +1824,7 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok) } static enum event_type -process_entry(struct event_format *event __unused, struct print_arg *arg, +process_entry(struct event_format *event __maybe_unused, struct print_arg *arg, char **tok) { enum event_type type; @@ -2458,7 +2458,8 @@ process_paren(struct event_format *event, struct print_arg *arg, char **tok) static enum event_type -process_str(struct event_format *event __unused, struct print_arg *arg, char **tok) +process_str(struct event_format *event __maybe_unused, struct print_arg *arg, + char **tok) { enum event_type type; char *token; @@ -3653,7 +3654,8 @@ static void free_args(struct print_arg *args) } static char * -get_bprint_format(void *data, int size __unused, struct event_format *event) +get_bprint_format(void *data, int size __maybe_unused, + struct event_format *event) { struct pevent *pevent = event->pevent; unsigned long long addr; diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index 3318963..a4bbe24 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -24,8 +24,8 @@ #include <stdarg.h> #include <regex.h> -#ifndef __unused -#define __unused __attribute__ ((unused)) +#ifndef __maybe_unused +#define __maybe_unused __attribute__((unused)) #endif /* ----------------------- trace_seq ----------------------- */ diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST index b4b572e..0518079 100644 --- a/tools/perf/MANIFEST +++ b/tools/perf/MANIFEST @@ -10,6 +10,7 @@ include/linux/stringify.h lib/rbtree.c include/linux/swab.h arch/*/include/asm/unistd*.h +arch/*/include/asm/perf_regs.h arch/*/lib/memcpy*.S arch/*/lib/memset*.S include/linux/poison.h diff --git a/tools/perf/Makefile b/tools/perf/Makefile index e4b2e8f..209774b 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -264,6 +264,7 @@ LIB_H += util/include/linux/ctype.h LIB_H += util/include/linux/kernel.h LIB_H += util/include/linux/list.h LIB_H += util/include/linux/export.h +LIB_H += util/include/linux/magic.h LIB_H += util/include/linux/poison.h LIB_H += util/include/linux/prefetch.h LIB_H += util/include/linux/rbtree.h @@ -336,6 +337,7 @@ LIB_H += util/intlist.h LIB_H += util/perf_regs.h LIB_H += util/unwind.h LIB_H += ui/helpline.h +LIB_H += util/vdso.h LIB_OBJS += $(OUTPUT)util/abspath.o LIB_OBJS += $(OUTPUT)util/alias.o @@ -403,6 +405,7 @@ LIB_OBJS += $(OUTPUT)util/cgroup.o LIB_OBJS += $(OUTPUT)util/target.o LIB_OBJS += $(OUTPUT)util/rblist.o LIB_OBJS += $(OUTPUT)util/intlist.o +LIB_OBJS += $(OUTPUT)util/vdso.o LIB_OBJS += $(OUTPUT)ui/helpline.o LIB_OBJS += $(OUTPUT)ui/hist.o diff --git a/tools/perf/bench/bench.h b/tools/perf/bench/bench.h index a09bece..8f89998 100644 --- a/tools/perf/bench/bench.h +++ b/tools/perf/bench/bench.h @@ -3,7 +3,8 @@ extern int bench_sched_messaging(int argc, const char **argv, const char *prefix); extern int bench_sched_pipe(int argc, const char **argv, const char *prefix); -extern int bench_mem_memcpy(int argc, const char **argv, const char *prefix __used); +extern int bench_mem_memcpy(int argc, const char **argv, + const char *prefix __maybe_unused); extern int bench_mem_memset(int argc, const char **argv, const char *prefix); #define BENCH_FORMAT_DEFAULT_STR "default" diff --git a/tools/perf/bench/mem-memcpy.c b/tools/perf/bench/mem-memcpy.c index 02dad5d..93c83e3 100644 --- a/tools/perf/bench/mem-memcpy.c +++ b/tools/perf/bench/mem-memcpy.c @@ -177,7 +177,7 @@ static double do_memcpy_gettimeofday(memcpy_t fn, size_t len, bool prefault) } while (0) int bench_mem_memcpy(int argc, const char **argv, - const char *prefix __used) + const char *prefix __maybe_unused) { int i; size_t len; diff --git a/tools/perf/bench/mem-memset.c b/tools/perf/bench/mem-memset.c index 350cc95..c6e4bc5 100644 --- a/tools/perf/bench/mem-memset.c +++ b/tools/perf/bench/mem-memset.c @@ -171,7 +171,7 @@ static double do_memset_gettimeofday(memset_t fn, size_t len, bool prefault) } while (0) int bench_mem_memset(int argc, const char **argv, - const char *prefix __used) + const char *prefix __maybe_unused) { int i; size_t len; diff --git a/tools/perf/bench/sched-messaging.c b/tools/perf/bench/sched-messaging.c index d1d1b30..cc1190a 100644 --- a/tools/perf/bench/sched-messaging.c +++ b/tools/perf/bench/sched-messaging.c @@ -267,7 +267,7 @@ static const char * const bench_sched_message_usage[] = { }; int bench_sched_messaging(int argc, const char **argv, - const char *prefix __used) + const char *prefix __maybe_unused) { unsigned int i, total_children; struct timeval start, stop, diff; diff --git a/tools/perf/bench/sched-pipe.c b/tools/perf/bench/sched-pipe.c index 15911e9..69cfba8 100644 --- a/tools/perf/bench/sched-pipe.c +++ b/tools/perf/bench/sched-pipe.c @@ -43,7 +43,7 @@ static const char * const bench_sched_pipe_usage[] = { }; int bench_sched_pipe(int argc, const char **argv, - const char *prefix __used) + const char *prefix __maybe_unused) { int pipe_1[2], pipe_2[2]; int m = 0, i; @@ -55,8 +55,8 @@ int bench_sched_pipe(int argc, const char **argv, * discarding returned value of read(), write() * causes error in building environment for perf */ - int __used ret, wait_stat; - pid_t pid, retpid __used; + int __maybe_unused ret, wait_stat; + pid_t pid, retpid __maybe_unused; argc = parse_options(argc, argv, options, bench_sched_pipe_usage, 0); diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 2f3f002..9ea3854 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -239,7 +239,7 @@ static const char * const annotate_usage[] = { NULL }; -int cmd_annotate(int argc, const char **argv, const char *prefix __used) +int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused) { struct perf_annotate annotate = { .tool = { diff --git a/tools/perf/builtin-bench.c b/tools/perf/builtin-bench.c index 1f31002..cae9a5f 100644 --- a/tools/perf/builtin-bench.c +++ b/tools/perf/builtin-bench.c @@ -173,7 +173,7 @@ static void all_subsystem(void) all_suite(&subsystems[i]); } -int cmd_bench(int argc, const char **argv, const char *prefix __used) +int cmd_bench(int argc, const char **argv, const char *prefix __maybe_unused) { int i, j, status = 0; diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c index 29ad20e..8365455 100644 --- a/tools/perf/builtin-buildid-cache.c +++ b/tools/perf/builtin-buildid-cache.c @@ -43,15 +43,16 @@ static int build_id_cache__add_file(const char *filename, const char *debugdir) } build_id__sprintf(build_id, sizeof(build_id), sbuild_id); - err = build_id_cache__add_s(sbuild_id, debugdir, filename, false); + err = build_id_cache__add_s(sbuild_id, debugdir, filename, + false, false); if (verbose) pr_info("Adding %s %s: %s\n", sbuild_id, filename, err ? "FAIL" : "Ok"); return err; } -static int build_id_cache__remove_file(const char *filename __used, - const char *debugdir __used) +static int build_id_cache__remove_file(const char *filename __maybe_unused, + const char *debugdir __maybe_unused) { u8 build_id[BUILD_ID_SIZE]; char sbuild_id[BUILD_ID_SIZE * 2 + 1]; @@ -119,7 +120,8 @@ static int __cmd_buildid_cache(void) return 0; } -int cmd_buildid_cache(int argc, const char **argv, const char *prefix __used) +int cmd_buildid_cache(int argc, const char **argv, + const char *prefix __maybe_unused) { argc = parse_options(argc, argv, buildid_cache_options, buildid_cache_usage, 0); diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c index 7d68428..1159fee 100644 --- a/tools/perf/builtin-buildid-list.c +++ b/tools/perf/builtin-buildid-list.c @@ -103,7 +103,8 @@ static int __cmd_buildid_list(void) return perf_session__list_build_ids(); } -int cmd_buildid_list(int argc, const char **argv, const char *prefix __used) +int cmd_buildid_list(int argc, const char **argv, + const char *prefix __maybe_unused) { argc = parse_options(argc, argv, options, buildid_list_usage, 0); setup_pager(); diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index c4c6d76..761f419 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -33,7 +33,7 @@ static int hists__add_entry(struct hists *self, return -ENOMEM; } -static int diff__process_sample_event(struct perf_tool *tool __used, +static int diff__process_sample_event(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct perf_evsel *evsel, @@ -242,7 +242,7 @@ static const struct option options[] = { OPT_END() }; -int cmd_diff(int argc, const char **argv, const char *prefix __used) +int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused) { sort_order = diff__default_sort_order; argc = parse_options(argc, argv, options, diff_usage, 0); diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c index 0dd5a05..1fb1641 100644 --- a/tools/perf/builtin-evlist.c +++ b/tools/perf/builtin-evlist.c @@ -113,7 +113,7 @@ static const char * const evlist_usage[] = { NULL }; -int cmd_evlist(int argc, const char **argv, const char *prefix __used) +int cmd_evlist(int argc, const char **argv, const char *prefix __maybe_unused) { struct perf_attr_details details = { .verbose = false, }; const char *input_name = NULL; diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c index f9daae5..25c8b94 100644 --- a/tools/perf/builtin-help.c +++ b/tools/perf/builtin-help.c @@ -426,7 +426,7 @@ static int show_html_page(const char *perf_cmd) return 0; } -int cmd_help(int argc, const char **argv, const char *prefix __used) +int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused) { const char *alias; int rc = 0; diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index 64d8ba2..1eaa661 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -17,9 +17,9 @@ static char const *input_name = "-"; static bool inject_build_ids; -static int perf_event__repipe_synth(struct perf_tool *tool __used, +static int perf_event__repipe_synth(struct perf_tool *tool __maybe_unused, union perf_event *event, - struct machine *machine __used) + struct machine *machine __maybe_unused) { uint32_t size; void *buf = event; @@ -40,7 +40,8 @@ static int perf_event__repipe_synth(struct perf_tool *tool __used, static int perf_event__repipe_op2_synth(struct perf_tool *tool, union perf_event *event, - struct perf_session *session __used) + struct perf_session *session + __maybe_unused) { return perf_event__repipe_synth(tool, event, NULL); } @@ -52,13 +53,14 @@ static int perf_event__repipe_event_type_synth(struct perf_tool *tool, } static int perf_event__repipe_tracing_data_synth(union perf_event *event, - struct perf_session *session __used) + struct perf_session *session + __maybe_unused) { return perf_event__repipe_synth(NULL, event, NULL); } static int perf_event__repipe_attr(union perf_event *event, - struct perf_evlist **pevlist __used) + struct perf_evlist **pevlist __maybe_unused) { int ret; ret = perf_event__process_attr(event, pevlist); @@ -70,7 +72,7 @@ static int perf_event__repipe_attr(union perf_event *event, static int perf_event__repipe(struct perf_tool *tool, union perf_event *event, - struct perf_sample *sample __used, + struct perf_sample *sample __maybe_unused, struct machine *machine) { return perf_event__repipe_synth(tool, event, machine); @@ -78,8 +80,8 @@ static int perf_event__repipe(struct perf_tool *tool, static int perf_event__repipe_sample(struct perf_tool *tool, union perf_event *event, - struct perf_sample *sample __used, - struct perf_evsel *evsel __used, + struct perf_sample *sample __maybe_unused, + struct perf_evsel *evsel __maybe_unused, struct machine *machine) { return perf_event__repipe_synth(tool, event, machine); @@ -163,7 +165,7 @@ static int dso__inject_build_id(struct dso *self, struct perf_tool *tool, static int perf_event__inject_buildid(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, - struct perf_evsel *evsel __used, + struct perf_evsel *evsel __maybe_unused, struct machine *machine) { struct addr_location al; @@ -224,7 +226,7 @@ struct perf_tool perf_inject = { extern volatile int session_done; -static void sig_handler(int sig __attribute__((__unused__))) +static void sig_handler(int sig __maybe_unused) { session_done = 1; } @@ -267,7 +269,7 @@ static const struct option options[] = { OPT_END() }; -int cmd_inject(int argc, const char **argv, const char *prefix __used) +int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) { argc = parse_options(argc, argv, options, report_usage, 0); diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index fc6607b..f5f8a6b7 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c @@ -58,41 +58,52 @@ static unsigned long nr_allocs, nr_cross_allocs; #define PATH_SYS_NODE "/sys/devices/system/node" -static void init_cpunode_map(void) +static int init_cpunode_map(void) { FILE *fp; - int i; + int i, err = -1; fp = fopen("/sys/devices/system/cpu/kernel_max", "r"); if (!fp) { max_cpu_num = 4096; - return; + return 0; + } + + if (fscanf(fp, "%d", &max_cpu_num) < 1) { + pr_err("Failed to read 'kernel_max' from sysfs"); + goto out_close; } - if (fscanf(fp, "%d", &max_cpu_num) < 1) - die("Failed to read 'kernel_max' from sysfs"); max_cpu_num++; cpunode_map = calloc(max_cpu_num, sizeof(int)); - if (!cpunode_map) - die("calloc"); + if (!cpunode_map) { + pr_err("%s: calloc failed\n", __func__); + goto out_close; + } + for (i = 0; i < max_cpu_num; i++) cpunode_map[i] = -1; + + err = 0; +out_close: fclose(fp); + return err; } -static void setup_cpunode_map(void) +static int setup_cpunode_map(void) { struct dirent *dent1, *dent2; DIR *dir1, *dir2; unsigned int cpu, mem; char buf[PATH_MAX]; - init_cpunode_map(); + if (init_cpunode_map()) + return -1; dir1 = opendir(PATH_SYS_NODE); if (!dir1) - return; + return -1; while ((dent1 = readdir(dir1)) != NULL) { if (dent1->d_type != DT_DIR || @@ -112,10 +123,11 @@ static void setup_cpunode_map(void) closedir(dir2); } closedir(dir1); + return 0; } -static void insert_alloc_stat(unsigned long call_site, unsigned long ptr, - int bytes_req, int bytes_alloc, int cpu) +static int insert_alloc_stat(unsigned long call_site, unsigned long ptr, + int bytes_req, int bytes_alloc, int cpu) { struct rb_node **node = &root_alloc_stat.rb_node; struct rb_node *parent = NULL; @@ -139,8 +151,10 @@ static void insert_alloc_stat(unsigned long call_site, unsigned long ptr, data->bytes_alloc += bytes_alloc; } else { data = malloc(sizeof(*data)); - if (!data) - die("malloc"); + if (!data) { + pr_err("%s: malloc failed\n", __func__); + return -1; + } data->ptr = ptr; data->pingpong = 0; data->hit = 1; @@ -152,9 +166,10 @@ static void insert_alloc_stat(unsigned long call_site, unsigned long ptr, } data->call_site = call_site; data->alloc_cpu = cpu; + return 0; } -static void insert_caller_stat(unsigned long call_site, +static int insert_caller_stat(unsigned long call_site, int bytes_req, int bytes_alloc) { struct rb_node **node = &root_caller_stat.rb_node; @@ -179,8 +194,10 @@ static void insert_caller_stat(unsigned long call_site, data->bytes_alloc += bytes_alloc; } else { data = malloc(sizeof(*data)); - if (!data) - die("malloc"); + if (!data) { + pr_err("%s: malloc failed\n", __func__); + return -1; + } data->call_site = call_site; data->pingpong = 0; data->hit = 1; @@ -190,11 +207,12 @@ static void insert_caller_stat(unsigned long call_site, rb_link_node(&data->node, parent, node); rb_insert_color(&data->node, &root_caller_stat); } + + return 0; } -static void perf_evsel__process_alloc_event(struct perf_evsel *evsel, - struct perf_sample *sample, - int node) +static int perf_evsel__process_alloc_event(struct perf_evsel *evsel, + struct perf_sample *sample, int node) { struct event_format *event = evsel->tp_format; void *data = sample->raw_data; @@ -209,8 +227,9 @@ static void perf_evsel__process_alloc_event(struct perf_evsel *evsel, bytes_req = raw_field_value(event, "bytes_req", data); bytes_alloc = raw_field_value(event, "bytes_alloc", data); - insert_alloc_stat(call_site, ptr, bytes_req, bytes_alloc, cpu); - insert_caller_stat(call_site, bytes_req, bytes_alloc); + if (insert_alloc_stat(call_site, ptr, bytes_req, bytes_alloc, cpu) || + insert_caller_stat(call_site, bytes_req, bytes_alloc)) + return -1; total_requested += bytes_req; total_allocated += bytes_alloc; @@ -222,6 +241,7 @@ static void perf_evsel__process_alloc_event(struct perf_evsel *evsel, nr_cross_allocs++; } nr_allocs++; + return 0; } static int ptr_cmp(struct alloc_stat *, struct alloc_stat *); @@ -252,8 +272,8 @@ static struct alloc_stat *search_alloc_stat(unsigned long ptr, return NULL; } -static void perf_evsel__process_free_event(struct perf_evsel *evsel, - struct perf_sample *sample) +static int perf_evsel__process_free_event(struct perf_evsel *evsel, + struct perf_sample *sample) { unsigned long ptr = raw_field_value(evsel->tp_format, "ptr", sample->raw_data); @@ -261,44 +281,46 @@ static void perf_evsel__process_free_event(struct perf_evsel *evsel, s_alloc = search_alloc_stat(ptr, 0, &root_alloc_stat, ptr_cmp); if (!s_alloc) - return; + return 0; if ((short)sample->cpu != s_alloc->alloc_cpu) { s_alloc->pingpong++; s_caller = search_alloc_stat(0, s_alloc->call_site, &root_caller_stat, callsite_cmp); - assert(s_caller); + if (!s_caller) + return -1; s_caller->pingpong++; } s_alloc->alloc_cpu = -1; + + return 0; } -static void perf_evsel__process_kmem_event(struct perf_evsel *evsel, - struct perf_sample *sample) +static int perf_evsel__process_kmem_event(struct perf_evsel *evsel, + struct perf_sample *sample) { struct event_format *event = evsel->tp_format; if (!strcmp(event->name, "kmalloc") || !strcmp(event->name, "kmem_cache_alloc")) { - perf_evsel__process_alloc_event(evsel, sample, 0); - return; + return perf_evsel__process_alloc_event(evsel, sample, 0); } if (!strcmp(event->name, "kmalloc_node") || !strcmp(event->name, "kmem_cache_alloc_node")) { - perf_evsel__process_alloc_event(evsel, sample, 1); - return; + return perf_evsel__process_alloc_event(evsel, sample, 1); } if (!strcmp(event->name, "kfree") || !strcmp(event->name, "kmem_cache_free")) { - perf_evsel__process_free_event(evsel, sample); - return; + return perf_evsel__process_free_event(evsel, sample); } + + return 0; } -static int process_sample_event(struct perf_tool *tool __used, +static int process_sample_event(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct perf_evsel *evsel, @@ -314,8 +336,7 @@ static int process_sample_event(struct perf_tool *tool __used, dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); - perf_evsel__process_kmem_event(evsel, sample); - return 0; + return perf_evsel__process_kmem_event(evsel, sample); } static struct perf_tool perf_kmem = { @@ -613,8 +634,10 @@ static int sort_dimension__add(const char *tok, struct list_head *list) for (i = 0; i < NUM_AVAIL_SORTS; i++) { if (!strcmp(avail_sorts[i]->name, tok)) { sort = malloc(sizeof(*sort)); - if (!sort) - die("malloc"); + if (!sort) { + pr_err("%s: malloc failed\n", __func__); + return -1; + } memcpy(sort, avail_sorts[i], sizeof(*sort)); list_add_tail(&sort->list, list); return 0; @@ -629,8 +652,10 @@ static int setup_sorting(struct list_head *sort_list, const char *arg) char *tok; char *str = strdup(arg); - if (!str) - die("strdup"); + if (!str) { + pr_err("%s: strdup failed\n", __func__); + return -1; + } while (true) { tok = strsep(&str, ","); @@ -647,8 +672,8 @@ static int setup_sorting(struct list_head *sort_list, const char *arg) return 0; } -static int parse_sort_opt(const struct option *opt __used, - const char *arg, int unset __used) +static int parse_sort_opt(const struct option *opt __maybe_unused, + const char *arg, int unset __maybe_unused) { if (!arg) return -1; @@ -661,22 +686,24 @@ static int parse_sort_opt(const struct option *opt __used, return 0; } -static int parse_caller_opt(const struct option *opt __used, - const char *arg __used, int unset __used) +static int parse_caller_opt(const struct option *opt __maybe_unused, + const char *arg __maybe_unused, + int unset __maybe_unused) { caller_flag = (alloc_flag + 1); return 0; } -static int parse_alloc_opt(const struct option *opt __used, - const char *arg __used, int unset __used) +static int parse_alloc_opt(const struct option *opt __maybe_unused, + const char *arg __maybe_unused, + int unset __maybe_unused) { alloc_flag = (caller_flag + 1); return 0; } -static int parse_line_opt(const struct option *opt __used, - const char *arg, int unset __used) +static int parse_line_opt(const struct option *opt __maybe_unused, + const char *arg, int unset __maybe_unused) { int lines; @@ -746,7 +773,7 @@ static int __cmd_record(int argc, const char **argv) return cmd_record(i, rec_argv, NULL); } -int cmd_kmem(int argc, const char **argv, const char *prefix __used) +int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused) { argc = parse_options(argc, argv, kmem_options, kmem_usage, 0); @@ -758,7 +785,8 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __used) if (!strncmp(argv[0], "rec", 3)) { return __cmd_record(argc, argv); } else if (!strcmp(argv[0], "stat")) { - setup_cpunode_map(); + if (setup_cpunode_map()) + return -1; if (list_empty(&caller_sort)) setup_sorting(&caller_sort, default_sort_order); diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index 9fc6e0f..4d2aa2c 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -102,7 +102,7 @@ static int __cmd_buildid_list(int argc, const char **argv) return cmd_buildid_list(i, rec_argv, NULL); } -int cmd_kvm(int argc, const char **argv, const char *prefix __used) +int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused) { perf_host = 0; perf_guest = 1; diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c index bdcff81..1948ece 100644 --- a/tools/perf/builtin-list.c +++ b/tools/perf/builtin-list.c @@ -14,7 +14,7 @@ #include "util/parse-events.h" #include "util/cache.h" -int cmd_list(int argc, const char **argv, const char *prefix __used) +int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused) { setup_pager(); diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c index 75153c8..a803520 100644 --- a/tools/perf/builtin-lock.c +++ b/tools/perf/builtin-lock.c @@ -870,7 +870,7 @@ static int dump_info(void) return rc; } -static int process_sample_event(struct perf_tool *tool __used, +static int process_sample_event(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct perf_evsel *evsel, @@ -1020,7 +1020,7 @@ static int __cmd_record(int argc, const char **argv) return cmd_record(i, rec_argv, NULL); } -int cmd_lock(int argc, const char **argv, const char *prefix __used) +int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused) { unsigned int i; int rc = 0; diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index e215ae6..118aa89 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c @@ -143,8 +143,8 @@ static int parse_probe_event_argv(int argc, const char **argv) return ret; } -static int opt_add_probe_event(const struct option *opt __used, - const char *str, int unset __used) +static int opt_add_probe_event(const struct option *opt __maybe_unused, + const char *str, int unset __maybe_unused) { if (str) { params.mod_events = true; @@ -153,8 +153,8 @@ static int opt_add_probe_event(const struct option *opt __used, return 0; } -static int opt_del_probe_event(const struct option *opt __used, - const char *str, int unset __used) +static int opt_del_probe_event(const struct option *opt __maybe_unused, + const char *str, int unset __maybe_unused) { if (str) { params.mod_events = true; @@ -166,7 +166,7 @@ static int opt_del_probe_event(const struct option *opt __used, } static int opt_set_target(const struct option *opt, const char *str, - int unset __used) + int unset __maybe_unused) { int ret = -ENOENT; @@ -188,8 +188,8 @@ static int opt_set_target(const struct option *opt, const char *str, } #ifdef DWARF_SUPPORT -static int opt_show_lines(const struct option *opt __used, - const char *str, int unset __used) +static int opt_show_lines(const struct option *opt __maybe_unused, + const char *str, int unset __maybe_unused) { int ret = 0; @@ -209,8 +209,8 @@ static int opt_show_lines(const struct option *opt __used, return ret; } -static int opt_show_vars(const struct option *opt __used, - const char *str, int unset __used) +static int opt_show_vars(const struct option *opt __maybe_unused, + const char *str, int unset __maybe_unused) { struct perf_probe_event *pev = ¶ms.events[params.nevents]; int ret; @@ -229,8 +229,8 @@ static int opt_show_vars(const struct option *opt __used, } #endif -static int opt_set_filter(const struct option *opt __used, - const char *str, int unset __used) +static int opt_set_filter(const struct option *opt __maybe_unused, + const char *str, int unset __maybe_unused) { const char *err; @@ -327,7 +327,7 @@ static const struct option options[] = { OPT_END() }; -int cmd_probe(int argc, const char **argv, const char *prefix __used) +int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) { int ret; diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 7b8b891..c643ed6 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -92,8 +92,8 @@ static int write_output(struct perf_record *rec, void *buf, size_t size) static int process_synthesized_event(struct perf_tool *tool, union perf_event *event, - struct perf_sample *sample __used, - struct machine *machine __used) + struct perf_sample *sample __maybe_unused, + struct machine *machine __maybe_unused) { struct perf_record *rec = container_of(tool, struct perf_record, tool); if (write_output(rec, event, event->header.size) < 0) @@ -159,7 +159,7 @@ static void sig_handler(int sig) signr = sig; } -static void perf_record__sig_exit(int exit_status __used, void *arg) +static void perf_record__sig_exit(int exit_status __maybe_unused, void *arg) { struct perf_record *rec = arg; int status; @@ -827,7 +827,7 @@ static int get_stack_size(char *str, unsigned long *_size) #endif /* !NO_LIBUNWIND_SUPPORT */ static int -parse_callchain_opt(const struct option *opt __used, const char *arg, +parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg, int unset) { struct perf_record *rec = (struct perf_record *)opt->value; @@ -1003,7 +1003,7 @@ const struct option record_options[] = { OPT_END() }; -int cmd_record(int argc, const char **argv, const char *prefix __used) +int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) { int err = -ENOMEM; struct perf_evsel *pos; diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 1f8d11b..97b2e63 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -223,9 +223,9 @@ static int process_sample_event(struct perf_tool *tool, static int process_read_event(struct perf_tool *tool, union perf_event *event, - struct perf_sample *sample __used, + struct perf_sample *sample __maybe_unused, struct perf_evsel *evsel, - struct machine *machine __used) + struct machine *machine __maybe_unused) { struct perf_report *rep = container_of(tool, struct perf_report, tool); @@ -287,7 +287,7 @@ static int perf_report__setup_sample_type(struct perf_report *rep) extern volatile int session_done; -static void sig_handler(int sig __used) +static void sig_handler(int sig __maybe_unused) { session_done = 1; } @@ -533,13 +533,14 @@ setup: } static int -parse_branch_mode(const struct option *opt __used, const char *str __used, int unset) +parse_branch_mode(const struct option *opt __maybe_unused, + const char *str __maybe_unused, int unset) { sort__branch_mode = !unset; return 0; } -int cmd_report(int argc, const char **argv, const char *prefix __used) +int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) { struct perf_session *session; struct stat st; diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index a25a023..af305f5 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -23,26 +23,12 @@ #include <pthread.h> #include <math.h> -static const char *input_name; - -static char default_sort_order[] = "avg, max, switch, runtime"; -static const char *sort_order = default_sort_order; - -static int profile_cpu = -1; - #define PR_SET_NAME 15 /* Set process name */ #define MAX_CPUS 4096 - -static u64 run_measurement_overhead; -static u64 sleep_measurement_overhead; - #define COMM_LEN 20 #define SYM_LEN 129 - #define MAX_PID 65536 -static unsigned long nr_tasks; - struct sched_atom; struct task_desc { @@ -80,44 +66,6 @@ struct sched_atom { struct task_desc *wakee; }; -static struct task_desc *pid_to_task[MAX_PID]; - -static struct task_desc **tasks; - -static pthread_mutex_t start_work_mutex = PTHREAD_MUTEX_INITIALIZER; -static u64 start_time; - -static pthread_mutex_t work_done_wait_mutex = PTHREAD_MUTEX_INITIALIZER; - -static unsigned long nr_run_events; -static unsigned long nr_sleep_events; -static unsigned long nr_wakeup_events; - -static unsigned long nr_sleep_corrections; -static unsigned long nr_run_events_optimized; - -static unsigned long targetless_wakeups; -static unsigned long multitarget_wakeups; - -static u64 cpu_usage; -static u64 runavg_cpu_usage; -static u64 parent_cpu_usage; -static u64 runavg_parent_cpu_usage; - -static unsigned long nr_runs; -static u64 sum_runtime; -static u64 sum_fluct; -static u64 run_avg; - -static unsigned int replay_repeat = 10; -static unsigned long nr_timestamps; -static unsigned long nr_unordered_timestamps; -static unsigned long nr_state_machine_bugs; -static unsigned long nr_context_switch_bugs; -static unsigned long nr_events; -static unsigned long nr_lost_chunks; -static unsigned long nr_lost_events; - #define TASK_STATE_TO_CHAR_STR "RSDTtZX" enum thread_state { @@ -149,11 +97,79 @@ struct work_atoms { typedef int (*sort_fn_t)(struct work_atoms *, struct work_atoms *); -static struct rb_root atom_root, sorted_atom_root; +struct perf_sched; -static u64 all_runtime; -static u64 all_count; +struct trace_sched_handler { + int (*switch_event)(struct perf_sched *sched, struct perf_evsel *evsel, + struct perf_sample *sample, struct machine *machine); + + int (*runtime_event)(struct perf_sched *sched, struct perf_evsel *evsel, + struct perf_sample *sample, struct machine *machine); + + int (*wakeup_event)(struct perf_sched *sched, struct perf_evsel *evsel, + struct perf_sample *sample, struct machine *machine); + + int (*fork_event)(struct perf_sched *sched, struct perf_evsel *evsel, + struct perf_sample *sample); + int (*migrate_task_event)(struct perf_sched *sched, + struct perf_evsel *evsel, + struct perf_sample *sample, + struct machine *machine); +}; + +struct perf_sched { + struct perf_tool tool; + const char *input_name; + const char *sort_order; + unsigned long nr_tasks; + struct task_desc *pid_to_task[MAX_PID]; + struct task_desc **tasks; + const struct trace_sched_handler *tp_handler; + pthread_mutex_t start_work_mutex; + pthread_mutex_t work_done_wait_mutex; + int profile_cpu; +/* + * Track the current task - that way we can know whether there's any + * weird events, such as a task being switched away that is not current. + */ + int max_cpu; + u32 curr_pid[MAX_CPUS]; + struct thread *curr_thread[MAX_CPUS]; + char next_shortname1; + char next_shortname2; + unsigned int replay_repeat; + unsigned long nr_run_events; + unsigned long nr_sleep_events; + unsigned long nr_wakeup_events; + unsigned long nr_sleep_corrections; + unsigned long nr_run_events_optimized; + unsigned long targetless_wakeups; + unsigned long multitarget_wakeups; + unsigned long nr_runs; + unsigned long nr_timestamps; + unsigned long nr_unordered_timestamps; + unsigned long nr_state_machine_bugs; + unsigned long nr_context_switch_bugs; + unsigned long nr_events; + unsigned long nr_lost_chunks; + unsigned long nr_lost_events; + u64 run_measurement_overhead; + u64 sleep_measurement_overhead; + u64 start_time; + u64 cpu_usage; + u64 runavg_cpu_usage; + u64 parent_cpu_usage; + u64 runavg_parent_cpu_usage; + u64 sum_runtime; + u64 sum_fluct; + u64 run_avg; + u64 all_runtime; + u64 all_count; + u64 cpu_last_switched[MAX_CPUS]; + struct rb_root atom_root, sorted_atom_root; + struct list_head sort_list, cmp_pid; +}; static u64 get_nsecs(void) { @@ -164,13 +180,13 @@ static u64 get_nsecs(void) return ts.tv_sec * 1000000000ULL + ts.tv_nsec; } -static void burn_nsecs(u64 nsecs) +static void burn_nsecs(struct perf_sched *sched, u64 nsecs) { u64 T0 = get_nsecs(), T1; do { T1 = get_nsecs(); - } while (T1 + run_measurement_overhead < T0 + nsecs); + } while (T1 + sched->run_measurement_overhead < T0 + nsecs); } static void sleep_nsecs(u64 nsecs) @@ -183,24 +199,24 @@ static void sleep_nsecs(u64 nsecs) nanosleep(&ts, NULL); } -static void calibrate_run_measurement_overhead(void) +static void calibrate_run_measurement_overhead(struct perf_sched *sched) { u64 T0, T1, delta, min_delta = 1000000000ULL; int i; for (i = 0; i < 10; i++) { T0 = get_nsecs(); - burn_nsecs(0); + burn_nsecs(sched, 0); T1 = get_nsecs(); delta = T1-T0; min_delta = min(min_delta, delta); } - run_measurement_overhead = min_delta; + sched->run_measurement_overhead = min_delta; printf("run measurement overhead: %" PRIu64 " nsecs\n", min_delta); } -static void calibrate_sleep_measurement_overhead(void) +static void calibrate_sleep_measurement_overhead(struct perf_sched *sched) { u64 T0, T1, delta, min_delta = 1000000000ULL; int i; @@ -213,7 +229,7 @@ static void calibrate_sleep_measurement_overhead(void) min_delta = min(min_delta, delta); } min_delta -= 10000; - sleep_measurement_overhead = min_delta; + sched->sleep_measurement_overhead = min_delta; printf("sleep measurement overhead: %" PRIu64 " nsecs\n", min_delta); } @@ -246,8 +262,8 @@ static struct sched_atom *last_event(struct task_desc *task) return task->atoms[task->nr_events - 1]; } -static void -add_sched_event_run(struct task_desc *task, u64 timestamp, u64 duration) +static void add_sched_event_run(struct perf_sched *sched, struct task_desc *task, + u64 timestamp, u64 duration) { struct sched_atom *event, *curr_event = last_event(task); @@ -256,7 +272,7 @@ add_sched_event_run(struct task_desc *task, u64 timestamp, u64 duration) * to it: */ if (curr_event && curr_event->type == SCHED_EVENT_RUN) { - nr_run_events_optimized++; + sched->nr_run_events_optimized++; curr_event->duration += duration; return; } @@ -266,12 +282,11 @@ add_sched_event_run(struct task_desc *task, u64 timestamp, u64 duration) event->type = SCHED_EVENT_RUN; event->duration = duration; - nr_run_events++; + sched->nr_run_events++; } -static void -add_sched_event_wakeup(struct task_desc *task, u64 timestamp, - struct task_desc *wakee) +static void add_sched_event_wakeup(struct perf_sched *sched, struct task_desc *task, + u64 timestamp, struct task_desc *wakee) { struct sched_atom *event, *wakee_event; @@ -281,11 +296,11 @@ add_sched_event_wakeup(struct task_desc *task, u64 timestamp, wakee_event = last_event(wakee); if (!wakee_event || wakee_event->type != SCHED_EVENT_SLEEP) { - targetless_wakeups++; + sched->targetless_wakeups++; return; } if (wakee_event->wait_sem) { - multitarget_wakeups++; + sched->multitarget_wakeups++; return; } @@ -294,89 +309,89 @@ add_sched_event_wakeup(struct task_desc *task, u64 timestamp, wakee_event->specific_wait = 1; event->wait_sem = wakee_event->wait_sem; - nr_wakeup_events++; + sched->nr_wakeup_events++; } -static void -add_sched_event_sleep(struct task_desc *task, u64 timestamp, - u64 task_state __used) +static void add_sched_event_sleep(struct perf_sched *sched, struct task_desc *task, + u64 timestamp, u64 task_state __maybe_unused) { struct sched_atom *event = get_new_event(task, timestamp); event->type = SCHED_EVENT_SLEEP; - nr_sleep_events++; + sched->nr_sleep_events++; } -static struct task_desc *register_pid(unsigned long pid, const char *comm) +static struct task_desc *register_pid(struct perf_sched *sched, + unsigned long pid, const char *comm) { struct task_desc *task; BUG_ON(pid >= MAX_PID); - task = pid_to_task[pid]; + task = sched->pid_to_task[pid]; if (task) return task; task = zalloc(sizeof(*task)); task->pid = pid; - task->nr = nr_tasks; + task->nr = sched->nr_tasks; strcpy(task->comm, comm); /* * every task starts in sleeping state - this gets ignored * if there's no wakeup pointing to this sleep state: */ - add_sched_event_sleep(task, 0, 0); + add_sched_event_sleep(sched, task, 0, 0); - pid_to_task[pid] = task; - nr_tasks++; - tasks = realloc(tasks, nr_tasks*sizeof(struct task_task *)); - BUG_ON(!tasks); - tasks[task->nr] = task; + sched->pid_to_task[pid] = task; + sched->nr_tasks++; + sched->tasks = realloc(sched->tasks, sched->nr_tasks * sizeof(struct task_task *)); + BUG_ON(!sched->tasks); + sched->tasks[task->nr] = task; if (verbose) - printf("registered task #%ld, PID %ld (%s)\n", nr_tasks, pid, comm); + printf("registered task #%ld, PID %ld (%s)\n", sched->nr_tasks, pid, comm); return task; } -static void print_task_traces(void) +static void print_task_traces(struct perf_sched *sched) { struct task_desc *task; unsigned long i; - for (i = 0; i < nr_tasks; i++) { - task = tasks[i]; + for (i = 0; i < sched->nr_tasks; i++) { + task = sched->tasks[i]; printf("task %6ld (%20s:%10ld), nr_events: %ld\n", task->nr, task->comm, task->pid, task->nr_events); } } -static void add_cross_task_wakeups(void) +static void add_cross_task_wakeups(struct perf_sched *sched) { struct task_desc *task1, *task2; unsigned long i, j; - for (i = 0; i < nr_tasks; i++) { - task1 = tasks[i]; + for (i = 0; i < sched->nr_tasks; i++) { + task1 = sched->tasks[i]; j = i + 1; - if (j == nr_tasks) + if (j == sched->nr_tasks) j = 0; - task2 = tasks[j]; - add_sched_event_wakeup(task1, 0, task2); + task2 = sched->tasks[j]; + add_sched_event_wakeup(sched, task1, 0, task2); } } -static void -process_sched_event(struct task_desc *this_task __used, struct sched_atom *atom) +static void perf_sched__process_event(struct perf_sched *sched, + struct sched_atom *atom) { int ret = 0; switch (atom->type) { case SCHED_EVENT_RUN: - burn_nsecs(atom->duration); + burn_nsecs(sched, atom->duration); break; case SCHED_EVENT_SLEEP: if (atom->wait_sem) @@ -423,8 +438,8 @@ static int self_open_counters(void) fd = sys_perf_event_open(&attr, 0, -1, -1, 0); if (fd < 0) - die("Error: sys_perf_event_open() syscall returned" - "with %d (%s)\n", fd, strerror(errno)); + pr_debug("Error: sys_perf_event_open() syscall returned" + "with %d (%s)\n", fd, strerror(errno)); return fd; } @@ -439,31 +454,41 @@ static u64 get_cpu_usage_nsec_self(int fd) return runtime; } +struct sched_thread_parms { + struct task_desc *task; + struct perf_sched *sched; +}; + static void *thread_func(void *ctx) { - struct task_desc *this_task = ctx; + struct sched_thread_parms *parms = ctx; + struct task_desc *this_task = parms->task; + struct perf_sched *sched = parms->sched; u64 cpu_usage_0, cpu_usage_1; unsigned long i, ret; char comm2[22]; int fd; + free(parms); + sprintf(comm2, ":%s", this_task->comm); prctl(PR_SET_NAME, comm2); fd = self_open_counters(); - + if (fd < 0) + return NULL; again: ret = sem_post(&this_task->ready_for_work); BUG_ON(ret); - ret = pthread_mutex_lock(&start_work_mutex); + ret = pthread_mutex_lock(&sched->start_work_mutex); BUG_ON(ret); - ret = pthread_mutex_unlock(&start_work_mutex); + ret = pthread_mutex_unlock(&sched->start_work_mutex); BUG_ON(ret); cpu_usage_0 = get_cpu_usage_nsec_self(fd); for (i = 0; i < this_task->nr_events; i++) { this_task->curr_event = i; - process_sched_event(this_task, this_task->atoms[i]); + perf_sched__process_event(sched, this_task->atoms[i]); } cpu_usage_1 = get_cpu_usage_nsec_self(fd); @@ -471,15 +496,15 @@ again: ret = sem_post(&this_task->work_done_sem); BUG_ON(ret); - ret = pthread_mutex_lock(&work_done_wait_mutex); + ret = pthread_mutex_lock(&sched->work_done_wait_mutex); BUG_ON(ret); - ret = pthread_mutex_unlock(&work_done_wait_mutex); + ret = pthread_mutex_unlock(&sched->work_done_wait_mutex); BUG_ON(ret); goto again; } -static void create_tasks(void) +static void create_tasks(struct perf_sched *sched) { struct task_desc *task; pthread_attr_t attr; @@ -491,128 +516,129 @@ static void create_tasks(void) err = pthread_attr_setstacksize(&attr, (size_t) max(16 * 1024, PTHREAD_STACK_MIN)); BUG_ON(err); - err = pthread_mutex_lock(&start_work_mutex); + err = pthread_mutex_lock(&sched->start_work_mutex); BUG_ON(err); - err = pthread_mutex_lock(&work_done_wait_mutex); + err = pthread_mutex_lock(&sched->work_done_wait_mutex); BUG_ON(err); - for (i = 0; i < nr_tasks; i++) { - task = tasks[i]; + for (i = 0; i < sched->nr_tasks; i++) { + struct sched_thread_parms *parms = malloc(sizeof(*parms)); + BUG_ON(parms == NULL); + parms->task = task = sched->tasks[i]; + parms->sched = sched; sem_init(&task->sleep_sem, 0, 0); sem_init(&task->ready_for_work, 0, 0); sem_init(&task->work_done_sem, 0, 0); task->curr_event = 0; - err = pthread_create(&task->thread, &attr, thread_func, task); + err = pthread_create(&task->thread, &attr, thread_func, parms); BUG_ON(err); } } -static void wait_for_tasks(void) +static void wait_for_tasks(struct perf_sched *sched) { u64 cpu_usage_0, cpu_usage_1; struct task_desc *task; unsigned long i, ret; - start_time = get_nsecs(); - cpu_usage = 0; - pthread_mutex_unlock(&work_done_wait_mutex); + sched->start_time = get_nsecs(); + sched->cpu_usage = 0; + pthread_mutex_unlock(&sched->work_done_wait_mutex); - for (i = 0; i < nr_tasks; i++) { - task = tasks[i]; + for (i = 0; i < sched->nr_tasks; i++) { + task = sched->tasks[i]; ret = sem_wait(&task->ready_for_work); BUG_ON(ret); sem_init(&task->ready_for_work, 0, 0); } - ret = pthread_mutex_lock(&work_done_wait_mutex); + ret = pthread_mutex_lock(&sched->work_done_wait_mutex); BUG_ON(ret); cpu_usage_0 = get_cpu_usage_nsec_parent(); - pthread_mutex_unlock(&start_work_mutex); + pthread_mutex_unlock(&sched->start_work_mutex); - for (i = 0; i < nr_tasks; i++) { - task = tasks[i]; + for (i = 0; i < sched->nr_tasks; i++) { + task = sched->tasks[i]; ret = sem_wait(&task->work_done_sem); BUG_ON(ret); sem_init(&task->work_done_sem, 0, 0); - cpu_usage += task->cpu_usage; + sched->cpu_usage += task->cpu_usage; task->cpu_usage = 0; } cpu_usage_1 = get_cpu_usage_nsec_parent(); - if (!runavg_cpu_usage) - runavg_cpu_usage = cpu_usage; - runavg_cpu_usage = (runavg_cpu_usage*9 + cpu_usage)/10; + if (!sched->runavg_cpu_usage) + sched->runavg_cpu_usage = sched->cpu_usage; + sched->runavg_cpu_usage = (sched->runavg_cpu_usage * 9 + sched->cpu_usage) / 10; - parent_cpu_usage = cpu_usage_1 - cpu_usage_0; - if (!runavg_parent_cpu_usage) - runavg_parent_cpu_usage = parent_cpu_usage; - runavg_parent_cpu_usage = (runavg_parent_cpu_usage*9 + - parent_cpu_usage)/10; + sched->parent_cpu_usage = cpu_usage_1 - cpu_usage_0; + if (!sched->runavg_parent_cpu_usage) + sched->runavg_parent_cpu_usage = sched->parent_cpu_usage; + sched->runavg_parent_cpu_usage = (sched->runavg_parent_cpu_usage * 9 + + sched->parent_cpu_usage)/10; - ret = pthread_mutex_lock(&start_work_mutex); + ret = pthread_mutex_lock(&sched->start_work_mutex); BUG_ON(ret); - for (i = 0; i < nr_tasks; i++) { - task = tasks[i]; + for (i = 0; i < sched->nr_tasks; i++) { + task = sched->tasks[i]; sem_init(&task->sleep_sem, 0, 0); task->curr_event = 0; } } -static void run_one_test(void) +static void run_one_test(struct perf_sched *sched) { u64 T0, T1, delta, avg_delta, fluct; T0 = get_nsecs(); - wait_for_tasks(); + wait_for_tasks(sched); T1 = get_nsecs(); delta = T1 - T0; - sum_runtime += delta; - nr_runs++; + sched->sum_runtime += delta; + sched->nr_runs++; - avg_delta = sum_runtime / nr_runs; + avg_delta = sched->sum_runtime / sched->nr_runs; if (delta < avg_delta) fluct = avg_delta - delta; else fluct = delta - avg_delta; - sum_fluct += fluct; - if (!run_avg) - run_avg = delta; - run_avg = (run_avg*9 + delta)/10; + sched->sum_fluct += fluct; + if (!sched->run_avg) + sched->run_avg = delta; + sched->run_avg = (sched->run_avg * 9 + delta) / 10; - printf("#%-3ld: %0.3f, ", - nr_runs, (double)delta/1000000.0); + printf("#%-3ld: %0.3f, ", sched->nr_runs, (double)delta / 1000000.0); - printf("ravg: %0.2f, ", - (double)run_avg/1e6); + printf("ravg: %0.2f, ", (double)sched->run_avg / 1e6); printf("cpu: %0.2f / %0.2f", - (double)cpu_usage/1e6, (double)runavg_cpu_usage/1e6); + (double)sched->cpu_usage / 1e6, (double)sched->runavg_cpu_usage / 1e6); #if 0 /* * rusage statistics done by the parent, these are less - * accurate than the sum_exec_runtime based statistics: + * accurate than the sched->sum_exec_runtime based statistics: */ printf(" [%0.2f / %0.2f]", - (double)parent_cpu_usage/1e6, - (double)runavg_parent_cpu_usage/1e6); + (double)sched->parent_cpu_usage/1e6, + (double)sched->runavg_parent_cpu_usage/1e6); #endif printf("\n"); - if (nr_sleep_corrections) - printf(" (%ld sleep corrections)\n", nr_sleep_corrections); - nr_sleep_corrections = 0; + if (sched->nr_sleep_corrections) + printf(" (%ld sleep corrections)\n", sched->nr_sleep_corrections); + sched->nr_sleep_corrections = 0; } -static void test_calibrations(void) +static void test_calibrations(struct perf_sched *sched) { u64 T0, T1; T0 = get_nsecs(); - burn_nsecs(1e6); + burn_nsecs(sched, 1e6); T1 = get_nsecs(); printf("the run test took %" PRIu64 " nsecs\n", T1 - T0); @@ -624,216 +650,92 @@ static void test_calibrations(void) printf("the sleep test took %" PRIu64 " nsecs\n", T1 - T0); } -#define FILL_FIELD(ptr, field, event, data) \ - ptr.field = (typeof(ptr.field)) raw_field_value(event, #field, data) - -#define FILL_ARRAY(ptr, array, event, data) \ -do { \ - void *__array = raw_field_ptr(event, #array, data); \ - memcpy(ptr.array, __array, sizeof(ptr.array)); \ -} while(0) - -#define FILL_COMMON_FIELDS(ptr, event, data) \ -do { \ - FILL_FIELD(ptr, common_type, event, data); \ - FILL_FIELD(ptr, common_flags, event, data); \ - FILL_FIELD(ptr, common_preempt_count, event, data); \ - FILL_FIELD(ptr, common_pid, event, data); \ - FILL_FIELD(ptr, common_tgid, event, data); \ -} while (0) - - - -struct trace_switch_event { - u32 size; - - u16 common_type; - u8 common_flags; - u8 common_preempt_count; - u32 common_pid; - u32 common_tgid; - - char prev_comm[16]; - u32 prev_pid; - u32 prev_prio; - u64 prev_state; - char next_comm[16]; - u32 next_pid; - u32 next_prio; -}; - -struct trace_runtime_event { - u32 size; - - u16 common_type; - u8 common_flags; - u8 common_preempt_count; - u32 common_pid; - u32 common_tgid; - - char comm[16]; - u32 pid; - u64 runtime; - u64 vruntime; -}; - -struct trace_wakeup_event { - u32 size; - - u16 common_type; - u8 common_flags; - u8 common_preempt_count; - u32 common_pid; - u32 common_tgid; - - char comm[16]; - u32 pid; - - u32 prio; - u32 success; - u32 cpu; -}; - -struct trace_fork_event { - u32 size; - - u16 common_type; - u8 common_flags; - u8 common_preempt_count; - u32 common_pid; - u32 common_tgid; - - char parent_comm[16]; - u32 parent_pid; - char child_comm[16]; - u32 child_pid; -}; - -struct trace_migrate_task_event { - u32 size; - - u16 common_type; - u8 common_flags; - u8 common_preempt_count; - u32 common_pid; - u32 common_tgid; - - char comm[16]; - u32 pid; - - u32 prio; - u32 cpu; -}; - -struct trace_sched_handler { - void (*switch_event)(struct trace_switch_event *, - struct machine *, - struct event_format *, - struct perf_sample *sample); - - void (*runtime_event)(struct trace_runtime_event *, - struct machine *, - struct perf_sample *sample); - - void (*wakeup_event)(struct trace_wakeup_event *, - struct machine *, - struct event_format *, - struct perf_sample *sample); - - void (*fork_event)(struct trace_fork_event *, - struct event_format *event); - - void (*migrate_task_event)(struct trace_migrate_task_event *, - struct machine *machine, - struct perf_sample *sample); -}; - - -static void -replay_wakeup_event(struct trace_wakeup_event *wakeup_event, - struct machine *machine __used, - struct event_format *event, struct perf_sample *sample) +static int +replay_wakeup_event(struct perf_sched *sched, + struct perf_evsel *evsel, struct perf_sample *sample, + struct machine *machine __maybe_unused) { + const char *comm = perf_evsel__strval(evsel, sample, "comm"); + const u32 pid = perf_evsel__intval(evsel, sample, "pid"); struct task_desc *waker, *wakee; if (verbose) { - printf("sched_wakeup event %p\n", event); + printf("sched_wakeup event %p\n", evsel); - printf(" ... pid %d woke up %s/%d\n", - wakeup_event->common_pid, - wakeup_event->comm, - wakeup_event->pid); + printf(" ... pid %d woke up %s/%d\n", sample->tid, comm, pid); } - waker = register_pid(wakeup_event->common_pid, "<unknown>"); - wakee = register_pid(wakeup_event->pid, wakeup_event->comm); + waker = register_pid(sched, sample->tid, "<unknown>"); + wakee = register_pid(sched, pid, comm); - add_sched_event_wakeup(waker, sample->time, wakee); + add_sched_event_wakeup(sched, waker, sample->time, wakee); + return 0; } -static u64 cpu_last_switched[MAX_CPUS]; - -static void -replay_switch_event(struct trace_switch_event *switch_event, - struct machine *machine __used, - struct event_format *event, - struct perf_sample *sample) +static int replay_switch_event(struct perf_sched *sched, + struct perf_evsel *evsel, + struct perf_sample *sample, + struct machine *machine __maybe_unused) { - struct task_desc *prev, __used *next; + const char *prev_comm = perf_evsel__strval(evsel, sample, "prev_comm"), + *next_comm = perf_evsel__strval(evsel, sample, "next_comm"); + const u32 prev_pid = perf_evsel__intval(evsel, sample, "prev_pid"), + next_pid = perf_evsel__intval(evsel, sample, "next_pid"); + const u64 prev_state = perf_evsel__intval(evsel, sample, "prev_state"); + struct task_desc *prev, __maybe_unused *next; u64 timestamp0, timestamp = sample->time; int cpu = sample->cpu; s64 delta; if (verbose) - printf("sched_switch event %p\n", event); + printf("sched_switch event %p\n", evsel); if (cpu >= MAX_CPUS || cpu < 0) - return; + return 0; - timestamp0 = cpu_last_switched[cpu]; + timestamp0 = sched->cpu_last_switched[cpu]; if (timestamp0) delta = timestamp - timestamp0; else delta = 0; - if (delta < 0) - die("hm, delta: %" PRIu64 " < 0 ?\n", delta); - - if (verbose) { - printf(" ... switch from %s/%d to %s/%d [ran %" PRIu64 " nsecs]\n", - switch_event->prev_comm, switch_event->prev_pid, - switch_event->next_comm, switch_event->next_pid, - delta); + if (delta < 0) { + pr_debug("hm, delta: %" PRIu64 " < 0 ?\n", delta); + return -1; } - prev = register_pid(switch_event->prev_pid, switch_event->prev_comm); - next = register_pid(switch_event->next_pid, switch_event->next_comm); + pr_debug(" ... switch from %s/%d to %s/%d [ran %" PRIu64 " nsecs]\n", + prev_comm, prev_pid, next_comm, next_pid, delta); - cpu_last_switched[cpu] = timestamp; + prev = register_pid(sched, prev_pid, prev_comm); + next = register_pid(sched, next_pid, next_comm); - add_sched_event_run(prev, timestamp, delta); - add_sched_event_sleep(prev, timestamp, switch_event->prev_state); -} + sched->cpu_last_switched[cpu] = timestamp; + add_sched_event_run(sched, prev, timestamp, delta); + add_sched_event_sleep(sched, prev, timestamp, prev_state); -static void -replay_fork_event(struct trace_fork_event *fork_event, - struct event_format *event) + return 0; +} + +static int replay_fork_event(struct perf_sched *sched, struct perf_evsel *evsel, + struct perf_sample *sample) { + const char *parent_comm = perf_evsel__strval(evsel, sample, "parent_comm"), + *child_comm = perf_evsel__strval(evsel, sample, "child_comm"); + const u32 parent_pid = perf_evsel__intval(evsel, sample, "parent_pid"), + child_pid = perf_evsel__intval(evsel, sample, "child_pid"); + if (verbose) { - printf("sched_fork event %p\n", event); - printf("... parent: %s/%d\n", fork_event->parent_comm, fork_event->parent_pid); - printf("... child: %s/%d\n", fork_event->child_comm, fork_event->child_pid); + printf("sched_fork event %p\n", evsel); + printf("... parent: %s/%d\n", parent_comm, parent_pid); + printf("... child: %s/%d\n", child_comm, child_pid); } - register_pid(fork_event->parent_pid, fork_event->parent_comm); - register_pid(fork_event->child_pid, fork_event->child_comm); -} -static struct trace_sched_handler replay_ops = { - .wakeup_event = replay_wakeup_event, - .switch_event = replay_switch_event, - .fork_event = replay_fork_event, -}; + register_pid(sched, parent_pid, parent_comm); + register_pid(sched, child_pid, child_comm); + return 0; +} struct sort_dimension { const char *name; @@ -841,8 +743,6 @@ struct sort_dimension { struct list_head list; }; -static LIST_HEAD(cmp_pid); - static int thread_lat_cmp(struct list_head *list, struct work_atoms *l, struct work_atoms *r) { @@ -911,40 +811,45 @@ __thread_latency_insert(struct rb_root *root, struct work_atoms *data, rb_insert_color(&data->node, root); } -static void thread_atoms_insert(struct thread *thread) +static int thread_atoms_insert(struct perf_sched *sched, struct thread *thread) { struct work_atoms *atoms = zalloc(sizeof(*atoms)); - if (!atoms) - die("No memory"); + if (!atoms) { + pr_err("No memory at %s\n", __func__); + return -1; + } atoms->thread = thread; INIT_LIST_HEAD(&atoms->work_list); - __thread_latency_insert(&atom_root, atoms, &cmp_pid); + __thread_latency_insert(&sched->atom_root, atoms, &sched->cmp_pid); + return 0; } -static void -latency_fork_event(struct trace_fork_event *fork_event __used, - struct event_format *event __used) +static int latency_fork_event(struct perf_sched *sched __maybe_unused, + struct perf_evsel *evsel __maybe_unused, + struct perf_sample *sample __maybe_unused) { /* should insert the newcomer */ + return 0; } -__used -static char sched_out_state(struct trace_switch_event *switch_event) +static char sched_out_state(u64 prev_state) { const char *str = TASK_STATE_TO_CHAR_STR; - return str[switch_event->prev_state]; + return str[prev_state]; } -static void +static int add_sched_out_event(struct work_atoms *atoms, char run_state, u64 timestamp) { struct work_atom *atom = zalloc(sizeof(*atom)); - if (!atom) - die("Non memory"); + if (!atom) { + pr_err("Non memory at %s", __func__); + return -1; + } atom->sched_out_time = timestamp; @@ -954,10 +859,12 @@ add_sched_out_event(struct work_atoms *atoms, } list_add_tail(&atom->list, &atoms->work_list); + return 0; } static void -add_runtime_event(struct work_atoms *atoms, u64 delta, u64 timestamp __used) +add_runtime_event(struct work_atoms *atoms, u64 delta, + u64 timestamp __maybe_unused) { struct work_atom *atom; @@ -1000,12 +907,14 @@ add_sched_in_event(struct work_atoms *atoms, u64 timestamp) atoms->nb_atoms++; } -static void -latency_switch_event(struct trace_switch_event *switch_event, - struct machine *machine, - struct event_format *event __used, - struct perf_sample *sample) +static int latency_switch_event(struct perf_sched *sched, + struct perf_evsel *evsel, + struct perf_sample *sample, + struct machine *machine) { + const u32 prev_pid = perf_evsel__intval(evsel, sample, "prev_pid"), + next_pid = perf_evsel__intval(evsel, sample, "next_pid"); + const u64 prev_state = perf_evsel__intval(evsel, sample, "prev_state"); struct work_atoms *out_events, *in_events; struct thread *sched_out, *sched_in; u64 timestamp0, timestamp = sample->time; @@ -1014,87 +923,112 @@ latency_switch_event(struct trace_switch_event *switch_event, BUG_ON(cpu >= MAX_CPUS || cpu < 0); - timestamp0 = cpu_last_switched[cpu]; - cpu_last_switched[cpu] = timestamp; + timestamp0 = sched->cpu_last_switched[cpu]; + sched->cpu_last_switched[cpu] = timestamp; if (timestamp0) delta = timestamp - timestamp0; else delta = 0; - if (delta < 0) - die("hm, delta: %" PRIu64 " < 0 ?\n", delta); - + if (delta < 0) { + pr_err("hm, delta: %" PRIu64 " < 0 ?\n", delta); + return -1; + } - sched_out = machine__findnew_thread(machine, switch_event->prev_pid); - sched_in = machine__findnew_thread(machine, switch_event->next_pid); + sched_out = machine__findnew_thread(machine, prev_pid); + sched_in = machine__findnew_thread(machine, next_pid); - out_events = thread_atoms_search(&atom_root, sched_out, &cmp_pid); + out_events = thread_atoms_search(&sched->atom_root, sched_out, &sched->cmp_pid); if (!out_events) { - thread_atoms_insert(sched_out); - out_events = thread_atoms_search(&atom_root, sched_out, &cmp_pid); - if (!out_events) - die("out-event: Internal tree error"); + if (thread_atoms_insert(sched, sched_out)) + return -1; + out_events = thread_atoms_search(&sched->atom_root, sched_out, &sched->cmp_pid); + if (!out_events) { + pr_err("out-event: Internal tree error"); + return -1; + } } - add_sched_out_event(out_events, sched_out_state(switch_event), timestamp); + if (add_sched_out_event(out_events, sched_out_state(prev_state), timestamp)) + return -1; - in_events = thread_atoms_search(&atom_root, sched_in, &cmp_pid); + in_events = thread_atoms_search(&sched->atom_root, sched_in, &sched->cmp_pid); if (!in_events) { - thread_atoms_insert(sched_in); - in_events = thread_atoms_search(&atom_root, sched_in, &cmp_pid); - if (!in_events) - die("in-event: Internal tree error"); + if (thread_atoms_insert(sched, sched_in)) + return -1; + in_events = thread_atoms_search(&sched->atom_root, sched_in, &sched->cmp_pid); + if (!in_events) { + pr_err("in-event: Internal tree error"); + return -1; + } /* * Take came in we have not heard about yet, * add in an initial atom in runnable state: */ - add_sched_out_event(in_events, 'R', timestamp); + if (add_sched_out_event(in_events, 'R', timestamp)) + return -1; } add_sched_in_event(in_events, timestamp); + + return 0; } -static void -latency_runtime_event(struct trace_runtime_event *runtime_event, - struct machine *machine, struct perf_sample *sample) +static int latency_runtime_event(struct perf_sched *sched, + struct perf_evsel *evsel, + struct perf_sample *sample, + struct machine *machine) { - struct thread *thread = machine__findnew_thread(machine, runtime_event->pid); - struct work_atoms *atoms = thread_atoms_search(&atom_root, thread, &cmp_pid); + const u32 pid = perf_evsel__intval(evsel, sample, "pid"); + const u64 runtime = perf_evsel__intval(evsel, sample, "runtime"); + struct thread *thread = machine__findnew_thread(machine, pid); + struct work_atoms *atoms = thread_atoms_search(&sched->atom_root, thread, &sched->cmp_pid); u64 timestamp = sample->time; int cpu = sample->cpu; BUG_ON(cpu >= MAX_CPUS || cpu < 0); if (!atoms) { - thread_atoms_insert(thread); - atoms = thread_atoms_search(&atom_root, thread, &cmp_pid); - if (!atoms) - die("in-event: Internal tree error"); - add_sched_out_event(atoms, 'R', timestamp); + if (thread_atoms_insert(sched, thread)) + return -1; + atoms = thread_atoms_search(&sched->atom_root, thread, &sched->cmp_pid); + if (!atoms) { + pr_debug("in-event: Internal tree error"); + return -1; + } + if (add_sched_out_event(atoms, 'R', timestamp)) + return -1; } - add_runtime_event(atoms, runtime_event->runtime, timestamp); + add_runtime_event(atoms, runtime, timestamp); + return 0; } -static void -latency_wakeup_event(struct trace_wakeup_event *wakeup_event, - struct machine *machine, struct event_format *event __used, - struct perf_sample *sample) +static int latency_wakeup_event(struct perf_sched *sched, + struct perf_evsel *evsel, + struct perf_sample *sample, + struct machine *machine) { + const u32 pid = perf_evsel__intval(evsel, sample, "pid"), + success = perf_evsel__intval(evsel, sample, "success"); struct work_atoms *atoms; struct work_atom *atom; struct thread *wakee; u64 timestamp = sample->time; /* Note for later, it may be interesting to observe the failing cases */ - if (!wakeup_event->success) - return; + if (!success) + return 0; - wakee = machine__findnew_thread(machine, wakeup_event->pid); - atoms = thread_atoms_search(&atom_root, wakee, &cmp_pid); + wakee = machine__findnew_thread(machine, pid); + atoms = thread_atoms_search(&sched->atom_root, wakee, &sched->cmp_pid); if (!atoms) { - thread_atoms_insert(wakee); - atoms = thread_atoms_search(&atom_root, wakee, &cmp_pid); - if (!atoms) - die("wakeup-event: Internal tree error"); - add_sched_out_event(atoms, 'S', timestamp); + if (thread_atoms_insert(sched, wakee)) + return -1; + atoms = thread_atoms_search(&sched->atom_root, wakee, &sched->cmp_pid); + if (!atoms) { + pr_debug("wakeup-event: Internal tree error"); + return -1; + } + if (add_sched_out_event(atoms, 'S', timestamp)) + return -1; } BUG_ON(list_empty(&atoms->work_list)); @@ -1106,23 +1040,26 @@ latency_wakeup_event(struct trace_wakeup_event *wakeup_event, * one CPU, or are only looking at only one, so don't * make useless noise. */ - if (profile_cpu == -1 && atom->state != THREAD_SLEEPING) - nr_state_machine_bugs++; + if (sched->profile_cpu == -1 && atom->state != THREAD_SLEEPING) + sched->nr_state_machine_bugs++; - nr_timestamps++; + sched->nr_timestamps++; if (atom->sched_out_time > timestamp) { - nr_unordered_timestamps++; - return; + sched->nr_unordered_timestamps++; + return 0; } atom->state = THREAD_WAIT_CPU; atom->wake_up_time = timestamp; + return 0; } -static void -latency_migrate_task_event(struct trace_migrate_task_event *migrate_task_event, - struct machine *machine, struct perf_sample *sample) +static int latency_migrate_task_event(struct perf_sched *sched, + struct perf_evsel *evsel, + struct perf_sample *sample, + struct machine *machine) { + const u32 pid = perf_evsel__intval(evsel, sample, "pid"); u64 timestamp = sample->time; struct work_atoms *atoms; struct work_atom *atom; @@ -1131,18 +1068,22 @@ latency_migrate_task_event(struct trace_migrate_task_event *migrate_task_event, /* * Only need to worry about migration when profiling one CPU. */ - if (profile_cpu == -1) - return; + if (sched->profile_cpu == -1) + return 0; - migrant = machine__findnew_thread(machine, migrate_task_event->pid); - atoms = thread_atoms_search(&atom_root, migrant, &cmp_pid); + migrant = machine__findnew_thread(machine, pid); + atoms = thread_atoms_search(&sched->atom_root, migrant, &sched->cmp_pid); if (!atoms) { - thread_atoms_insert(migrant); - register_pid(migrant->pid, migrant->comm); - atoms = thread_atoms_search(&atom_root, migrant, &cmp_pid); - if (!atoms) - die("migration-event: Internal tree error"); - add_sched_out_event(atoms, 'R', timestamp); + if (thread_atoms_insert(sched, migrant)) + return -1; + register_pid(sched, migrant->pid, migrant->comm); + atoms = thread_atoms_search(&sched->atom_root, migrant, &sched->cmp_pid); + if (!atoms) { + pr_debug("migration-event: Internal tree error"); + return -1; + } + if (add_sched_out_event(atoms, 'R', timestamp)) + return -1; } BUG_ON(list_empty(&atoms->work_list)); @@ -1150,21 +1091,15 @@ latency_migrate_task_event(struct trace_migrate_task_event *migrate_task_event, atom = list_entry(atoms->work_list.prev, struct work_atom, list); atom->sched_in_time = atom->sched_out_time = atom->wake_up_time = timestamp; - nr_timestamps++; + sched->nr_timestamps++; if (atom->sched_out_time > timestamp) - nr_unordered_timestamps++; -} + sched->nr_unordered_timestamps++; -static struct trace_sched_handler lat_ops = { - .wakeup_event = latency_wakeup_event, - .switch_event = latency_switch_event, - .runtime_event = latency_runtime_event, - .fork_event = latency_fork_event, - .migrate_task_event = latency_migrate_task_event, -}; + return 0; +} -static void output_lat_thread(struct work_atoms *work_list) +static void output_lat_thread(struct perf_sched *sched, struct work_atoms *work_list) { int i; int ret; @@ -1178,8 +1113,8 @@ static void output_lat_thread(struct work_atoms *work_list) if (!strcmp(work_list->thread->comm, "swapper")) return; - all_runtime += work_list->total_runtime; - all_count += work_list->nb_atoms; + sched->all_runtime += work_list->total_runtime; + sched->all_count += work_list->nb_atoms; ret = printf(" %s:%d ", work_list->thread->comm, work_list->thread->pid); @@ -1205,11 +1140,6 @@ static int pid_cmp(struct work_atoms *l, struct work_atoms *r) return 0; } -static struct sort_dimension pid_sort_dimension = { - .name = "pid", - .cmp = pid_cmp, -}; - static int avg_cmp(struct work_atoms *l, struct work_atoms *r) { u64 avgl, avgr; @@ -1231,11 +1161,6 @@ static int avg_cmp(struct work_atoms *l, struct work_atoms *r) return 0; } -static struct sort_dimension avg_sort_dimension = { - .name = "avg", - .cmp = avg_cmp, -}; - static int max_cmp(struct work_atoms *l, struct work_atoms *r) { if (l->max_lat < r->max_lat) @@ -1246,11 +1171,6 @@ static int max_cmp(struct work_atoms *l, struct work_atoms *r) return 0; } -static struct sort_dimension max_sort_dimension = { - .name = "max", - .cmp = max_cmp, -}; - static int switch_cmp(struct work_atoms *l, struct work_atoms *r) { if (l->nb_atoms < r->nb_atoms) @@ -1261,11 +1181,6 @@ static int switch_cmp(struct work_atoms *l, struct work_atoms *r) return 0; } -static struct sort_dimension switch_sort_dimension = { - .name = "switch", - .cmp = switch_cmp, -}; - static int runtime_cmp(struct work_atoms *l, struct work_atoms *r) { if (l->total_runtime < r->total_runtime) @@ -1276,28 +1191,38 @@ static int runtime_cmp(struct work_atoms *l, struct work_atoms *r) return 0; } -static struct sort_dimension runtime_sort_dimension = { - .name = "runtime", - .cmp = runtime_cmp, -}; - -static struct sort_dimension *available_sorts[] = { - &pid_sort_dimension, - &avg_sort_dimension, - &max_sort_dimension, - &switch_sort_dimension, - &runtime_sort_dimension, -}; - -#define NB_AVAILABLE_SORTS (int)(sizeof(available_sorts) / sizeof(struct sort_dimension *)) - -static LIST_HEAD(sort_list); - static int sort_dimension__add(const char *tok, struct list_head *list) { - int i; + size_t i; + static struct sort_dimension avg_sort_dimension = { + .name = "avg", + .cmp = avg_cmp, + }; + static struct sort_dimension max_sort_dimension = { + .name = "max", + .cmp = max_cmp, + }; + static struct sort_dimension pid_sort_dimension = { + .name = "pid", + .cmp = pid_cmp, + }; + static struct sort_dimension runtime_sort_dimension = { + .name = "runtime", + .cmp = runtime_cmp, + }; + static struct sort_dimension switch_sort_dimension = { + .name = "switch", + .cmp = switch_cmp, + }; + struct sort_dimension *available_sorts[] = { + &pid_sort_dimension, + &avg_sort_dimension, + &max_sort_dimension, + &switch_sort_dimension, + &runtime_sort_dimension, + }; - for (i = 0; i < NB_AVAILABLE_SORTS; i++) { + for (i = 0; i < ARRAY_SIZE(available_sorts); i++) { if (!strcmp(available_sorts[i]->name, tok)) { list_add_tail(&available_sorts[i]->list, list); @@ -1308,68 +1233,41 @@ static int sort_dimension__add(const char *tok, struct list_head *list) return -1; } -static void setup_sorting(void); - -static void sort_lat(void) +static void perf_sched__sort_lat(struct perf_sched *sched) { struct rb_node *node; for (;;) { struct work_atoms *data; - node = rb_first(&atom_root); + node = rb_first(&sched->atom_root); if (!node) break; - rb_erase(node, &atom_root); + rb_erase(node, &sched->atom_root); data = rb_entry(node, struct work_atoms, node); - __thread_latency_insert(&sorted_atom_root, data, &sort_list); + __thread_latency_insert(&sched->sorted_atom_root, data, &sched->sort_list); } } -static struct trace_sched_handler *trace_handler; - -static void -process_sched_wakeup_event(struct perf_tool *tool __used, - struct event_format *event, - struct perf_sample *sample, - struct machine *machine, - struct thread *thread __used) +static int process_sched_wakeup_event(struct perf_tool *tool, + struct perf_evsel *evsel, + struct perf_sample *sample, + struct machine *machine) { - void *data = sample->raw_data; - struct trace_wakeup_event wakeup_event; + struct perf_sched *sched = container_of(tool, struct perf_sched, tool); - FILL_COMMON_FIELDS(wakeup_event, event, data); + if (sched->tp_handler->wakeup_event) + return sched->tp_handler->wakeup_event(sched, evsel, sample, machine); - FILL_ARRAY(wakeup_event, comm, event, data); - FILL_FIELD(wakeup_event, pid, event, data); - FILL_FIELD(wakeup_event, prio, event, data); - FILL_FIELD(wakeup_event, success, event, data); - FILL_FIELD(wakeup_event, cpu, event, data); - - if (trace_handler->wakeup_event) - trace_handler->wakeup_event(&wakeup_event, machine, event, sample); + return 0; } -/* - * Track the current task - that way we can know whether there's any - * weird events, such as a task being switched away that is not current. - */ -static int max_cpu; - -static u32 curr_pid[MAX_CPUS] = { [0 ... MAX_CPUS-1] = -1 }; - -static struct thread *curr_thread[MAX_CPUS]; - -static char next_shortname1 = 'A'; -static char next_shortname2 = '0'; - -static void -map_switch_event(struct trace_switch_event *switch_event, - struct machine *machine, - struct event_format *event __used, - struct perf_sample *sample) +static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, + struct perf_sample *sample, struct machine *machine) { - struct thread *sched_out __used, *sched_in; + const u32 prev_pid = perf_evsel__intval(evsel, sample, "prev_pid"), + next_pid = perf_evsel__intval(evsel, sample, "next_pid"); + struct thread *sched_out __maybe_unused, *sched_in; int new_shortname; u64 timestamp0, timestamp = sample->time; s64 delta; @@ -1377,54 +1275,55 @@ map_switch_event(struct trace_switch_event *switch_event, BUG_ON(this_cpu >= MAX_CPUS || this_cpu < 0); - if (this_cpu > max_cpu) - max_cpu = this_cpu; + if (this_cpu > sched->max_cpu) + sched->max_cpu = this_cpu; - timestamp0 = cpu_last_switched[this_cpu]; - cpu_last_switched[this_cpu] = timestamp; + timestamp0 = sched->cpu_last_switched[this_cpu]; + sched->cpu_last_switched[this_cpu] = timestamp; if (timestamp0) delta = timestamp - timestamp0; else delta = 0; - if (delta < 0) - die("hm, delta: %" PRIu64 " < 0 ?\n", delta); - + if (delta < 0) { + pr_debug("hm, delta: %" PRIu64 " < 0 ?\n", delta); + return -1; + } - sched_out = machine__findnew_thread(machine, switch_event->prev_pid); - sched_in = machine__findnew_thread(machine, switch_event->next_pid); + sched_out = machine__findnew_thread(machine, prev_pid); + sched_in = machine__findnew_thread(machine, next_pid); - curr_thread[this_cpu] = sched_in; + sched->curr_thread[this_cpu] = sched_in; printf(" "); new_shortname = 0; if (!sched_in->shortname[0]) { - sched_in->shortname[0] = next_shortname1; - sched_in->shortname[1] = next_shortname2; + sched_in->shortname[0] = sched->next_shortname1; + sched_in->shortname[1] = sched->next_shortname2; - if (next_shortname1 < 'Z') { - next_shortname1++; + if (sched->next_shortname1 < 'Z') { + sched->next_shortname1++; } else { - next_shortname1='A'; - if (next_shortname2 < '9') { - next_shortname2++; + sched->next_shortname1='A'; + if (sched->next_shortname2 < '9') { + sched->next_shortname2++; } else { - next_shortname2='0'; + sched->next_shortname2='0'; } } new_shortname = 1; } - for (cpu = 0; cpu <= max_cpu; cpu++) { + for (cpu = 0; cpu <= sched->max_cpu; cpu++) { if (cpu != this_cpu) printf(" "); else printf("*"); - if (curr_thread[cpu]) { - if (curr_thread[cpu]->pid) - printf("%2s ", curr_thread[cpu]->shortname); + if (sched->curr_thread[cpu]) { + if (sched->curr_thread[cpu]->pid) + printf("%2s ", sched->curr_thread[cpu]->shortname); else printf(". "); } else @@ -1438,127 +1337,97 @@ map_switch_event(struct trace_switch_event *switch_event, } else { printf("\n"); } + + return 0; } -static void -process_sched_switch_event(struct perf_tool *tool __used, - struct event_format *event, - struct perf_sample *sample, - struct machine *machine, - struct thread *thread __used) +static int process_sched_switch_event(struct perf_tool *tool, + struct perf_evsel *evsel, + struct perf_sample *sample, + struct machine *machine) { - int this_cpu = sample->cpu; - void *data = sample->raw_data; - struct trace_switch_event switch_event; - - FILL_COMMON_FIELDS(switch_event, event, data); + struct perf_sched *sched = container_of(tool, struct perf_sched, tool); + int this_cpu = sample->cpu, err = 0; + u32 prev_pid = perf_evsel__intval(evsel, sample, "prev_pid"), + next_pid = perf_evsel__intval(evsel, sample, "next_pid"); - FILL_ARRAY(switch_event, prev_comm, event, data); - FILL_FIELD(switch_event, prev_pid, event, data); - FILL_FIELD(switch_event, prev_prio, event, data); - FILL_FIELD(switch_event, prev_state, event, data); - FILL_ARRAY(switch_event, next_comm, event, data); - FILL_FIELD(switch_event, next_pid, event, data); - FILL_FIELD(switch_event, next_prio, event, data); - - if (curr_pid[this_cpu] != (u32)-1) { + if (sched->curr_pid[this_cpu] != (u32)-1) { /* * Are we trying to switch away a PID that is * not current? */ - if (curr_pid[this_cpu] != switch_event.prev_pid) - nr_context_switch_bugs++; + if (sched->curr_pid[this_cpu] != prev_pid) + sched->nr_context_switch_bugs++; } - if (trace_handler->switch_event) - trace_handler->switch_event(&switch_event, machine, event, sample); - curr_pid[this_cpu] = switch_event.next_pid; + if (sched->tp_handler->switch_event) + err = sched->tp_handler->switch_event(sched, evsel, sample, machine); + + sched->curr_pid[this_cpu] = next_pid; + return err; } -static void -process_sched_runtime_event(struct perf_tool *tool __used, - struct event_format *event, - struct perf_sample *sample, - struct machine *machine, - struct thread *thread __used) +static int process_sched_runtime_event(struct perf_tool *tool, + struct perf_evsel *evsel, + struct perf_sample *sample, + struct machine *machine) { - void *data = sample->raw_data; - struct trace_runtime_event runtime_event; + struct perf_sched *sched = container_of(tool, struct perf_sched, tool); - FILL_ARRAY(runtime_event, comm, event, data); - FILL_FIELD(runtime_event, pid, event, data); - FILL_FIELD(runtime_event, runtime, event, data); - FILL_FIELD(runtime_event, vruntime, event, data); + if (sched->tp_handler->runtime_event) + return sched->tp_handler->runtime_event(sched, evsel, sample, machine); - if (trace_handler->runtime_event) - trace_handler->runtime_event(&runtime_event, machine, sample); + return 0; } -static void -process_sched_fork_event(struct perf_tool *tool __used, - struct event_format *event, - struct perf_sample *sample, - struct machine *machine __used, - struct thread *thread __used) +static int process_sched_fork_event(struct perf_tool *tool, + struct perf_evsel *evsel, + struct perf_sample *sample, + struct machine *machine __maybe_unused) { - void *data = sample->raw_data; - struct trace_fork_event fork_event; - - FILL_COMMON_FIELDS(fork_event, event, data); + struct perf_sched *sched = container_of(tool, struct perf_sched, tool); - FILL_ARRAY(fork_event, parent_comm, event, data); - FILL_FIELD(fork_event, parent_pid, event, data); - FILL_ARRAY(fork_event, child_comm, event, data); - FILL_FIELD(fork_event, child_pid, event, data); + if (sched->tp_handler->fork_event) + return sched->tp_handler->fork_event(sched, evsel, sample); - if (trace_handler->fork_event) - trace_handler->fork_event(&fork_event, event); + return 0; } -static void -process_sched_exit_event(struct perf_tool *tool __used, - struct event_format *event, - struct perf_sample *sample __used, - struct machine *machine __used, - struct thread *thread __used) +static int process_sched_exit_event(struct perf_tool *tool __maybe_unused, + struct perf_evsel *evsel, + struct perf_sample *sample __maybe_unused, + struct machine *machine __maybe_unused) { - if (verbose) - printf("sched_exit event %p\n", event); + pr_debug("sched_exit event %p\n", evsel); + return 0; } -static void -process_sched_migrate_task_event(struct perf_tool *tool __used, - struct event_format *event, - struct perf_sample *sample, - struct machine *machine, - struct thread *thread __used) +static int process_sched_migrate_task_event(struct perf_tool *tool, + struct perf_evsel *evsel, + struct perf_sample *sample, + struct machine *machine) { - void *data = sample->raw_data; - struct trace_migrate_task_event migrate_task_event; + struct perf_sched *sched = container_of(tool, struct perf_sched, tool); - FILL_COMMON_FIELDS(migrate_task_event, event, data); + if (sched->tp_handler->migrate_task_event) + return sched->tp_handler->migrate_task_event(sched, evsel, sample, machine); - FILL_ARRAY(migrate_task_event, comm, event, data); - FILL_FIELD(migrate_task_event, pid, event, data); - FILL_FIELD(migrate_task_event, prio, event, data); - FILL_FIELD(migrate_task_event, cpu, event, data); - - if (trace_handler->migrate_task_event) - trace_handler->migrate_task_event(&migrate_task_event, machine, sample); + return 0; } -typedef void (*tracepoint_handler)(struct perf_tool *tool, struct event_format *event, - struct perf_sample *sample, - struct machine *machine, - struct thread *thread); +typedef int (*tracepoint_handler)(struct perf_tool *tool, + struct perf_evsel *evsel, + struct perf_sample *sample, + struct machine *machine); -static int perf_sched__process_tracepoint_sample(struct perf_tool *tool __used, - union perf_event *event __used, +static int perf_sched__process_tracepoint_sample(struct perf_tool *tool __maybe_unused, + union perf_event *event __maybe_unused, struct perf_sample *sample, struct perf_evsel *evsel, struct machine *machine) { struct thread *thread = machine__findnew_thread(machine, sample->pid); + int err = 0; if (thread == NULL) { pr_debug("problem processing %s event, skipping it.\n", @@ -1571,23 +1440,15 @@ static int perf_sched__process_tracepoint_sample(struct perf_tool *tool __used, if (evsel->handler.func != NULL) { tracepoint_handler f = evsel->handler.func; - f(tool, evsel->tp_format, sample, machine, thread); + err = f(tool, evsel, sample, machine); } - return 0; + return err; } -static struct perf_tool perf_sched = { - .sample = perf_sched__process_tracepoint_sample, - .comm = perf_event__process_comm, - .lost = perf_event__process_lost, - .fork = perf_event__process_task, - .ordered_samples = true, -}; - -static void read_events(bool destroy, struct perf_session **psession) +static int perf_sched__read_events(struct perf_sched *sched, bool destroy, + struct perf_session **psession) { - int err = -EINVAL; const struct perf_evsel_str_handler handlers[] = { { "sched:sched_switch", process_sched_switch_event, }, { "sched:sched_stat_runtime", process_sched_runtime_event, }, @@ -1599,21 +1460,25 @@ static void read_events(bool destroy, struct perf_session **psession) }; struct perf_session *session; - session = perf_session__new(input_name, O_RDONLY, 0, false, &perf_sched); - if (session == NULL) - die("No Memory"); + session = perf_session__new(sched->input_name, O_RDONLY, 0, false, &sched->tool); + if (session == NULL) { + pr_debug("No Memory for session\n"); + return -1; + } - err = perf_session__set_tracepoints_handlers(session, handlers); - assert(err == 0); + if (perf_session__set_tracepoints_handlers(session, handlers)) + goto out_delete; if (perf_session__has_traces(session, "record -R")) { - err = perf_session__process_events(session, &perf_sched); - if (err) - die("Failed to process events, error %d", err); + int err = perf_session__process_events(session, &sched->tool); + if (err) { + pr_err("Failed to process events, error %d", err); + goto out_delete; + } - nr_events = session->hists.stats.nr_events[0]; - nr_lost_events = session->hists.stats.total_lost; - nr_lost_chunks = session->hists.stats.nr_events[PERF_RECORD_LOST]; + sched->nr_events = session->hists.stats.nr_events[0]; + sched->nr_lost_events = session->hists.stats.total_lost; + sched->nr_lost_chunks = session->hists.stats.nr_events[PERF_RECORD_LOST]; } if (destroy) @@ -1621,208 +1486,166 @@ static void read_events(bool destroy, struct perf_session **psession) if (psession) *psession = session; + + return 0; + +out_delete: + perf_session__delete(session); + return -1; } -static void print_bad_events(void) +static void print_bad_events(struct perf_sched *sched) { - if (nr_unordered_timestamps && nr_timestamps) { + if (sched->nr_unordered_timestamps && sched->nr_timestamps) { printf(" INFO: %.3f%% unordered timestamps (%ld out of %ld)\n", - (double)nr_unordered_timestamps/(double)nr_timestamps*100.0, - nr_unordered_timestamps, nr_timestamps); + (double)sched->nr_unordered_timestamps/(double)sched->nr_timestamps*100.0, + sched->nr_unordered_timestamps, sched->nr_timestamps); } - if (nr_lost_events && nr_events) { + if (sched->nr_lost_events && sched->nr_events) { printf(" INFO: %.3f%% lost events (%ld out of %ld, in %ld chunks)\n", - (double)nr_lost_events/(double)nr_events*100.0, - nr_lost_events, nr_events, nr_lost_chunks); + (double)sched->nr_lost_events/(double)sched->nr_events * 100.0, + sched->nr_lost_events, sched->nr_events, sched->nr_lost_chunks); } - if (nr_state_machine_bugs && nr_timestamps) { + if (sched->nr_state_machine_bugs && sched->nr_timestamps) { printf(" INFO: %.3f%% state machine bugs (%ld out of %ld)", - (double)nr_state_machine_bugs/(double)nr_timestamps*100.0, - nr_state_machine_bugs, nr_timestamps); - if (nr_lost_events) + (double)sched->nr_state_machine_bugs/(double)sched->nr_timestamps*100.0, + sched->nr_state_machine_bugs, sched->nr_timestamps); + if (sched->nr_lost_events) printf(" (due to lost events?)"); printf("\n"); } - if (nr_context_switch_bugs && nr_timestamps) { + if (sched->nr_context_switch_bugs && sched->nr_timestamps) { printf(" INFO: %.3f%% context switch bugs (%ld out of %ld)", - (double)nr_context_switch_bugs/(double)nr_timestamps*100.0, - nr_context_switch_bugs, nr_timestamps); - if (nr_lost_events) + (double)sched->nr_context_switch_bugs/(double)sched->nr_timestamps*100.0, + sched->nr_context_switch_bugs, sched->nr_timestamps); + if (sched->nr_lost_events) printf(" (due to lost events?)"); printf("\n"); } } -static void __cmd_lat(void) +static int perf_sched__lat(struct perf_sched *sched) { struct rb_node *next; struct perf_session *session; setup_pager(); - read_events(false, &session); - sort_lat(); + if (perf_sched__read_events(sched, false, &session)) + return -1; + perf_sched__sort_lat(sched); printf("\n ---------------------------------------------------------------------------------------------------------------\n"); printf(" Task | Runtime ms | Switches | Average delay ms | Maximum delay ms | Maximum delay at |\n"); printf(" ---------------------------------------------------------------------------------------------------------------\n"); - next = rb_first(&sorted_atom_root); + next = rb_first(&sched->sorted_atom_root); while (next) { struct work_atoms *work_list; work_list = rb_entry(next, struct work_atoms, node); - output_lat_thread(work_list); + output_lat_thread(sched, work_list); next = rb_next(next); } printf(" -----------------------------------------------------------------------------------------\n"); printf(" TOTAL: |%11.3f ms |%9" PRIu64 " |\n", - (double)all_runtime/1e6, all_count); + (double)sched->all_runtime / 1e6, sched->all_count); printf(" ---------------------------------------------------\n"); - print_bad_events(); + print_bad_events(sched); printf("\n"); perf_session__delete(session); + return 0; } -static struct trace_sched_handler map_ops = { - .wakeup_event = NULL, - .switch_event = map_switch_event, - .runtime_event = NULL, - .fork_event = NULL, -}; - -static void __cmd_map(void) +static int perf_sched__map(struct perf_sched *sched) { - max_cpu = sysconf(_SC_NPROCESSORS_CONF); + sched->max_cpu = sysconf(_SC_NPROCESSORS_CONF); setup_pager(); - read_events(true, NULL); - print_bad_events(); + if (perf_sched__read_events(sched, true, NULL)) + return -1; + print_bad_events(sched); + return 0; } -static void __cmd_replay(void) +static int perf_sched__replay(struct perf_sched *sched) { unsigned long i; - calibrate_run_measurement_overhead(); - calibrate_sleep_measurement_overhead(); + calibrate_run_measurement_overhead(sched); + calibrate_sleep_measurement_overhead(sched); - test_calibrations(); + test_calibrations(sched); - read_events(true, NULL); + if (perf_sched__read_events(sched, true, NULL)) + return -1; - printf("nr_run_events: %ld\n", nr_run_events); - printf("nr_sleep_events: %ld\n", nr_sleep_events); - printf("nr_wakeup_events: %ld\n", nr_wakeup_events); + printf("nr_run_events: %ld\n", sched->nr_run_events); + printf("nr_sleep_events: %ld\n", sched->nr_sleep_events); + printf("nr_wakeup_events: %ld\n", sched->nr_wakeup_events); - if (targetless_wakeups) - printf("target-less wakeups: %ld\n", targetless_wakeups); - if (multitarget_wakeups) - printf("multi-target wakeups: %ld\n", multitarget_wakeups); - if (nr_run_events_optimized) + if (sched->targetless_wakeups) + printf("target-less wakeups: %ld\n", sched->targetless_wakeups); + if (sched->multitarget_wakeups) + printf("multi-target wakeups: %ld\n", sched->multitarget_wakeups); + if (sched->nr_run_events_optimized) printf("run atoms optimized: %ld\n", - nr_run_events_optimized); + sched->nr_run_events_optimized); - print_task_traces(); - add_cross_task_wakeups(); + print_task_traces(sched); + add_cross_task_wakeups(sched); - create_tasks(); + create_tasks(sched); printf("------------------------------------------------------------\n"); - for (i = 0; i < replay_repeat; i++) - run_one_test(); -} - + for (i = 0; i < sched->replay_repeat; i++) + run_one_test(sched); -static const char * const sched_usage[] = { - "perf sched [<options>] {record|latency|map|replay|script}", - NULL -}; - -static const struct option sched_options[] = { - OPT_STRING('i', "input", &input_name, "file", - "input file name"), - OPT_INCR('v', "verbose", &verbose, - "be more verbose (show symbol address, etc)"), - OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, - "dump raw trace in ASCII"), - OPT_END() -}; - -static const char * const latency_usage[] = { - "perf sched latency [<options>]", - NULL -}; - -static const struct option latency_options[] = { - OPT_STRING('s', "sort", &sort_order, "key[,key2...]", - "sort by key(s): runtime, switch, avg, max"), - OPT_INCR('v', "verbose", &verbose, - "be more verbose (show symbol address, etc)"), - OPT_INTEGER('C', "CPU", &profile_cpu, - "CPU to profile on"), - OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, - "dump raw trace in ASCII"), - OPT_END() -}; - -static const char * const replay_usage[] = { - "perf sched replay [<options>]", - NULL -}; - -static const struct option replay_options[] = { - OPT_UINTEGER('r', "repeat", &replay_repeat, - "repeat the workload replay N times (-1: infinite)"), - OPT_INCR('v', "verbose", &verbose, - "be more verbose (show symbol address, etc)"), - OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, - "dump raw trace in ASCII"), - OPT_END() -}; + return 0; +} -static void setup_sorting(void) +static void setup_sorting(struct perf_sched *sched, const struct option *options, + const char * const usage_msg[]) { - char *tmp, *tok, *str = strdup(sort_order); + char *tmp, *tok, *str = strdup(sched->sort_order); for (tok = strtok_r(str, ", ", &tmp); tok; tok = strtok_r(NULL, ", ", &tmp)) { - if (sort_dimension__add(tok, &sort_list) < 0) { + if (sort_dimension__add(tok, &sched->sort_list) < 0) { error("Unknown --sort key: `%s'", tok); - usage_with_options(latency_usage, latency_options); + usage_with_options(usage_msg, options); } } free(str); - sort_dimension__add("pid", &cmp_pid); + sort_dimension__add("pid", &sched->cmp_pid); } -static const char *record_args[] = { - "record", - "-a", - "-R", - "-f", - "-m", "1024", - "-c", "1", - "-e", "sched:sched_switch", - "-e", "sched:sched_stat_wait", - "-e", "sched:sched_stat_sleep", - "-e", "sched:sched_stat_iowait", - "-e", "sched:sched_stat_runtime", - "-e", "sched:sched_process_exit", - "-e", "sched:sched_process_fork", - "-e", "sched:sched_wakeup", - "-e", "sched:sched_migrate_task", -}; - static int __cmd_record(int argc, const char **argv) { unsigned int rec_argc, i, j; const char **rec_argv; + const char * const record_args[] = { + "record", + "-a", + "-R", + "-f", + "-m", "1024", + "-c", "1", + "-e", "sched:sched_switch", + "-e", "sched:sched_stat_wait", + "-e", "sched:sched_stat_sleep", + "-e", "sched:sched_stat_iowait", + "-e", "sched:sched_stat_runtime", + "-e", "sched:sched_process_exit", + "-e", "sched:sched_process_fork", + "-e", "sched:sched_wakeup", + "-e", "sched:sched_migrate_task", + }; rec_argc = ARRAY_SIZE(record_args) + argc - 1; rec_argv = calloc(rec_argc + 1, sizeof(char *)); @@ -1841,8 +1664,85 @@ static int __cmd_record(int argc, const char **argv) return cmd_record(i, rec_argv, NULL); } -int cmd_sched(int argc, const char **argv, const char *prefix __used) +int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused) { + const char default_sort_order[] = "avg, max, switch, runtime"; + struct perf_sched sched = { + .tool = { + .sample = perf_sched__process_tracepoint_sample, + .comm = perf_event__process_comm, + .lost = perf_event__process_lost, + .fork = perf_event__process_task, + .ordered_samples = true, + }, + .cmp_pid = LIST_HEAD_INIT(sched.cmp_pid), + .sort_list = LIST_HEAD_INIT(sched.sort_list), + .start_work_mutex = PTHREAD_MUTEX_INITIALIZER, + .work_done_wait_mutex = PTHREAD_MUTEX_INITIALIZER, + .curr_pid = { [0 ... MAX_CPUS - 1] = -1 }, + .sort_order = default_sort_order, + .replay_repeat = 10, + .profile_cpu = -1, + .next_shortname1 = 'A', + .next_shortname2 = '0', + }; + const struct option latency_options[] = { + OPT_STRING('s', "sort", &sched.sort_order, "key[,key2...]", + "sort by key(s): runtime, switch, avg, max"), + OPT_INCR('v', "verbose", &verbose, + "be more verbose (show symbol address, etc)"), + OPT_INTEGER('C', "CPU", &sched.profile_cpu, + "CPU to profile on"), + OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, + "dump raw trace in ASCII"), + OPT_END() + }; + const struct option replay_options[] = { + OPT_UINTEGER('r', "repeat", &sched.replay_repeat, + "repeat the workload replay N times (-1: infinite)"), + OPT_INCR('v', "verbose", &verbose, + "be more verbose (show symbol address, etc)"), + OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, + "dump raw trace in ASCII"), + OPT_END() + }; + const struct option sched_options[] = { + OPT_STRING('i', "input", &sched.input_name, "file", + "input file name"), + OPT_INCR('v', "verbose", &verbose, + "be more verbose (show symbol address, etc)"), + OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, + "dump raw trace in ASCII"), + OPT_END() + }; + const char * const latency_usage[] = { + "perf sched latency [<options>]", + NULL + }; + const char * const replay_usage[] = { + "perf sched replay [<options>]", + NULL + }; + const char * const sched_usage[] = { + "perf sched [<options>] {record|latency|map|replay|script}", + NULL + }; + struct trace_sched_handler lat_ops = { + .wakeup_event = latency_wakeup_event, + .switch_event = latency_switch_event, + .runtime_event = latency_runtime_event, + .fork_event = latency_fork_event, + .migrate_task_event = latency_migrate_task_event, + }; + struct trace_sched_handler map_ops = { + .switch_event = map_switch_event, + }; + struct trace_sched_handler replay_ops = { + .wakeup_event = replay_wakeup_event, + .switch_event = replay_switch_event, + .fork_event = replay_fork_event, + }; + argc = parse_options(argc, argv, sched_options, sched_usage, PARSE_OPT_STOP_AT_NON_OPTION); if (!argc) @@ -1858,26 +1758,26 @@ int cmd_sched(int argc, const char **argv, const char *prefix __used) if (!strncmp(argv[0], "rec", 3)) { return __cmd_record(argc, argv); } else if (!strncmp(argv[0], "lat", 3)) { - trace_handler = &lat_ops; + sched.tp_handler = &lat_ops; if (argc > 1) { argc = parse_options(argc, argv, latency_options, latency_usage, 0); if (argc) usage_with_options(latency_usage, latency_options); } - setup_sorting(); - __cmd_lat(); + setup_sorting(&sched, latency_options, latency_usage); + return perf_sched__lat(&sched); } else if (!strcmp(argv[0], "map")) { - trace_handler = &map_ops; - setup_sorting(); - __cmd_map(); + sched.tp_handler = &map_ops; + setup_sorting(&sched, latency_options, latency_usage); + return perf_sched__map(&sched); } else if (!strncmp(argv[0], "rep", 3)) { - trace_handler = &replay_ops; + sched.tp_handler = &replay_ops; if (argc) { argc = parse_options(argc, argv, replay_options, replay_usage, 0); if (argc) usage_with_options(replay_usage, replay_options); } - __cmd_replay(); + return perf_sched__replay(&sched); } else { usage_with_options(sched_usage, sched_options); } diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index c350cfe..6d98a83 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -430,9 +430,9 @@ static void process_event(union perf_event *event, struct perf_sample *sample, printf("\n"); } -static int default_start_script(const char *script __unused, - int argc __unused, - const char **argv __unused) +static int default_start_script(const char *script __maybe_unused, + int argc __maybe_unused, + const char **argv __maybe_unused) { return 0; } @@ -442,8 +442,8 @@ static int default_stop_script(void) return 0; } -static int default_generate_script(struct pevent *pevent __unused, - const char *outfile __unused) +static int default_generate_script(struct pevent *pevent __maybe_unused, + const char *outfile __maybe_unused) { return 0; } @@ -474,7 +474,7 @@ static int cleanup_scripting(void) static const char *input_name; -static int process_sample_event(struct perf_tool *tool __used, +static int process_sample_event(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct perf_evsel *evsel, @@ -534,7 +534,7 @@ static struct perf_tool perf_script = { extern volatile int session_done; -static void sig_handler(int sig __unused) +static void sig_handler(int sig __maybe_unused) { session_done = 1; } @@ -644,8 +644,8 @@ static void list_available_languages(void) fprintf(stderr, "\n"); } -static int parse_scriptname(const struct option *opt __used, - const char *str, int unset __used) +static int parse_scriptname(const struct option *opt __maybe_unused, + const char *str, int unset __maybe_unused) { char spec[PATH_MAX]; const char *script, *ext; @@ -690,8 +690,8 @@ static int parse_scriptname(const struct option *opt __used, return 0; } -static int parse_output_fields(const struct option *opt __used, - const char *arg, int unset __used) +static int parse_output_fields(const struct option *opt __maybe_unused, + const char *arg, int unset __maybe_unused) { char *tok; int i, imax = sizeof(all_output_options) / sizeof(struct output_option); @@ -982,8 +982,9 @@ static char *get_script_root(struct dirent *script_dirent, const char *suffix) return script_root; } -static int list_available_scripts(const struct option *opt __used, - const char *s __used, int unset __used) +static int list_available_scripts(const struct option *opt __maybe_unused, + const char *s __maybe_unused, + int unset __maybe_unused) { struct dirent *script_next, *lang_next, script_dirent, lang_dirent; char scripts_path[MAXPATHLEN]; @@ -1172,7 +1173,7 @@ static int have_cmd(int argc, const char **argv) return 0; } -int cmd_script(int argc, const char **argv, const char *prefix __used) +int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) { char *rec_script_path = NULL; char *rep_script_path = NULL; diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 02f49eb..dab347d 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -417,7 +417,7 @@ static int read_counter(struct perf_evsel *counter) return 0; } -static int run_perf_stat(int argc __used, const char **argv) +static int run_perf_stat(int argc __maybe_unused, const char **argv) { unsigned long long t0, t1; struct perf_evsel *counter, *first; @@ -634,7 +634,9 @@ static const char *get_ratio_color(enum grc_type type, double ratio) return color; } -static void print_stalled_cycles_frontend(int cpu, struct perf_evsel *evsel __used, double avg) +static void print_stalled_cycles_frontend(int cpu, + struct perf_evsel *evsel + __maybe_unused, double avg) { double total, ratio = 0.0; const char *color; @@ -651,7 +653,9 @@ static void print_stalled_cycles_frontend(int cpu, struct perf_evsel *evsel __us fprintf(output, " frontend cycles idle "); } -static void print_stalled_cycles_backend(int cpu, struct perf_evsel *evsel __used, double avg) +static void print_stalled_cycles_backend(int cpu, + struct perf_evsel *evsel + __maybe_unused, double avg) { double total, ratio = 0.0; const char *color; @@ -668,7 +672,9 @@ static void print_stalled_cycles_backend(int cpu, struct perf_evsel *evsel __use fprintf(output, " backend cycles idle "); } -static void print_branch_misses(int cpu, struct perf_evsel *evsel __used, double avg) +static void print_branch_misses(int cpu, + struct perf_evsel *evsel __maybe_unused, + double avg) { double total, ratio = 0.0; const char *color; @@ -685,7 +691,9 @@ static void print_branch_misses(int cpu, struct perf_evsel *evsel __used, double fprintf(output, " of all branches "); } -static void print_l1_dcache_misses(int cpu, struct perf_evsel *evsel __used, double avg) +static void print_l1_dcache_misses(int cpu, + struct perf_evsel *evsel __maybe_unused, + double avg) { double total, ratio = 0.0; const char *color; @@ -702,7 +710,9 @@ static void print_l1_dcache_misses(int cpu, struct perf_evsel *evsel __used, dou fprintf(output, " of all L1-dcache hits "); } -static void print_l1_icache_misses(int cpu, struct perf_evsel *evsel __used, double avg) +static void print_l1_icache_misses(int cpu, + struct perf_evsel *evsel __maybe_unused, + double avg) { double total, ratio = 0.0; const char *color; @@ -719,7 +729,9 @@ static void print_l1_icache_misses(int cpu, struct perf_evsel *evsel __used, dou fprintf(output, " of all L1-icache hits "); } -static void print_dtlb_cache_misses(int cpu, struct perf_evsel *evsel __used, double avg) +static void print_dtlb_cache_misses(int cpu, + struct perf_evsel *evsel __maybe_unused, + double avg) { double total, ratio = 0.0; const char *color; @@ -736,7 +748,9 @@ static void print_dtlb_cache_misses(int cpu, struct perf_evsel *evsel __used, do fprintf(output, " of all dTLB cache hits "); } -static void print_itlb_cache_misses(int cpu, struct perf_evsel *evsel __used, double avg) +static void print_itlb_cache_misses(int cpu, + struct perf_evsel *evsel __maybe_unused, + double avg) { double total, ratio = 0.0; const char *color; @@ -753,7 +767,9 @@ static void print_itlb_cache_misses(int cpu, struct perf_evsel *evsel __used, do fprintf(output, " of all iTLB cache hits "); } -static void print_ll_cache_misses(int cpu, struct perf_evsel *evsel __used, double avg) +static void print_ll_cache_misses(int cpu, + struct perf_evsel *evsel __maybe_unused, + double avg) { double total, ratio = 0.0; const char *color; @@ -1059,8 +1075,8 @@ static const char * const stat_usage[] = { NULL }; -static int stat__set_big_num(const struct option *opt __used, - const char *s __used, int unset) +static int stat__set_big_num(const struct option *opt __maybe_unused, + const char *s __maybe_unused, int unset) { big_num_opt = unset ? 0 : 1; return 0; @@ -1154,7 +1170,7 @@ static int add_default_attributes(void) return perf_evlist__add_default_attrs(evsel_list, very_very_detailed_attrs); } -int cmd_stat(int argc, const char **argv, const char *prefix __used) +int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) { struct perf_evsel *pos; int status = -ENOMEM; diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c index cf33e50..d33143e 100644 --- a/tools/perf/builtin-test.c +++ b/tools/perf/builtin-test.c @@ -18,7 +18,8 @@ #include <sys/mman.h> -static int vmlinux_matches_kallsyms_filter(struct map *map __used, struct symbol *sym) +static int vmlinux_matches_kallsyms_filter(struct map *map __maybe_unused, + struct symbol *sym) { bool *visited = symbol__priv(sym); *visited = true; @@ -996,7 +997,9 @@ static u64 mmap_read_self(void *addr) /* * If the RDPMC instruction faults then signal this back to the test parent task: */ -static void segfault_handler(int sig __used, siginfo_t *info __used, void *uc __used) +static void segfault_handler(int sig __maybe_unused, + siginfo_t *info __maybe_unused, + void *uc __maybe_unused) { exit(-1); } @@ -1023,14 +1026,16 @@ static int __test__rdpmc(void) fd = sys_perf_event_open(&attr, 0, -1, -1, 0); if (fd < 0) { - die("Error: sys_perf_event_open() syscall returned " - "with %d (%s)\n", fd, strerror(errno)); + pr_debug("Error: sys_perf_event_open() syscall returned " + "with %d (%s)\n", fd, strerror(errno)); + return -1; } addr = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0); if (addr == (void *)(-1)) { - die("Error: mmap() syscall returned " - "with (%s)\n", strerror(errno)); + pr_debug("Error: mmap() syscall returned with (%s)\n", + strerror(errno)); + goto out_close; } for (n = 0; n < 6; n++) { @@ -1051,9 +1056,9 @@ static int __test__rdpmc(void) } munmap(addr, page_size); - close(fd); - pr_debug(" "); +out_close: + close(fd); if (!delta_sum) return -1; @@ -1313,7 +1318,7 @@ static int perf_test__list(int argc, const char **argv) return 0; } -int cmd_test(int argc, const char **argv, const char *prefix __used) +int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused) { const char * const test_usage[] = { "perf test [<options>] [{list <test-name-fragment>|[<test-name-fragments>|<test-numbers>]}]", diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index 3b75b2e..55a3a6c 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c @@ -275,28 +275,28 @@ static int cpus_cstate_state[MAX_CPUS]; static u64 cpus_pstate_start_times[MAX_CPUS]; static u64 cpus_pstate_state[MAX_CPUS]; -static int process_comm_event(struct perf_tool *tool __used, +static int process_comm_event(struct perf_tool *tool __maybe_unused, union perf_event *event, - struct perf_sample *sample __used, - struct machine *machine __used) + struct perf_sample *sample __maybe_unused, + struct machine *machine __maybe_unused) { pid_set_comm(event->comm.tid, event->comm.comm); return 0; } -static int process_fork_event(struct perf_tool *tool __used, +static int process_fork_event(struct perf_tool *tool __maybe_unused, union perf_event *event, - struct perf_sample *sample __used, - struct machine *machine __used) + struct perf_sample *sample __maybe_unused, + struct machine *machine __maybe_unused) { pid_fork(event->fork.pid, event->fork.ppid, event->fork.time); return 0; } -static int process_exit_event(struct perf_tool *tool __used, +static int process_exit_event(struct perf_tool *tool __maybe_unused, union perf_event *event, - struct perf_sample *sample __used, - struct machine *machine __used) + struct perf_sample *sample __maybe_unused, + struct machine *machine __maybe_unused) { pid_exit(event->fork.pid, event->fork.time); return 0; @@ -491,11 +491,11 @@ static void sched_switch(int cpu, u64 timestamp, struct trace_entry *te) } -static int process_sample_event(struct perf_tool *tool __used, - union perf_event *event __used, +static int process_sample_event(struct perf_tool *tool __maybe_unused, + union perf_event *event __maybe_unused, struct perf_sample *sample, struct perf_evsel *evsel, - struct machine *machine __used) + struct machine *machine __maybe_unused) { struct trace_entry *te; @@ -1081,7 +1081,8 @@ static int __cmd_record(int argc, const char **argv) } static int -parse_process(const struct option *opt __used, const char *arg, int __used unset) +parse_process(const struct option *opt __maybe_unused, const char *arg, + int __maybe_unused unset) { if (arg) add_process_filter(arg); @@ -1106,7 +1107,8 @@ static const struct option options[] = { }; -int cmd_timechart(int argc, const char **argv, const char *prefix __used) +int cmd_timechart(int argc, const char **argv, + const char *prefix __maybe_unused) { argc = parse_options(argc, argv, options, timechart_usage, PARSE_OPT_STOP_AT_NON_OPTION); diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 0513aaa..5550754 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -95,7 +95,8 @@ static void perf_top__update_print_entries(struct perf_top *top) top->print_entries -= 9; } -static void perf_top__sig_winch(int sig __used, siginfo_t *info __used, void *arg) +static void perf_top__sig_winch(int sig __maybe_unused, + siginfo_t *info __maybe_unused, void *arg) { struct perf_top *top = arg; @@ -663,7 +664,7 @@ static const char *skip_symbols[] = { NULL }; -static int symbol_filter(struct map *map __used, struct symbol *sym) +static int symbol_filter(struct map *map __maybe_unused, struct symbol *sym) { const char *name = sym->name; int i; @@ -1163,7 +1164,7 @@ static const char * const top_usage[] = { NULL }; -int cmd_top(int argc, const char **argv, const char *prefix __used) +int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) { struct perf_evsel *pos; int status; diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c index 1818a53..4aeb7d5 100644 --- a/tools/perf/ui/browser.c +++ b/tools/perf/ui/browser.c @@ -269,7 +269,7 @@ int ui_browser__show(struct ui_browser *browser, const char *title, return err ? 0 : -1; } -void ui_browser__hide(struct ui_browser *browser __used) +void ui_browser__hide(struct ui_browser *browser __maybe_unused) { pthread_mutex_lock(&ui__lock); ui_helpline__pop(); @@ -518,7 +518,7 @@ static struct ui_browser__colorset { static int ui_browser__color_config(const char *var, const char *value, - void *data __used) + void *data __maybe_unused) { char *fg = NULL, *bg; int i; @@ -602,7 +602,8 @@ void __ui_browser__vline(struct ui_browser *browser, unsigned int column, SLsmg_set_char_set(0); } -void ui_browser__write_graph(struct ui_browser *browser __used, int graph) +void ui_browser__write_graph(struct ui_browser *browser __maybe_unused, + int graph) { SLsmg_set_char_set(1); SLsmg_write_char(graph); diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index 67a2703..8f8cd2d 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c @@ -54,7 +54,8 @@ static inline struct browser_disasm_line *disasm_line__browser(struct disasm_lin return (struct browser_disasm_line *)(dl + 1); } -static bool disasm_line__filter(struct ui_browser *browser __used, void *entry) +static bool disasm_line__filter(struct ui_browser *browser __maybe_unused, + void *entry) { if (annotate_browser__opts.hide_src_code) { struct disasm_line *dl = list_entry(entry, struct disasm_line, node); @@ -928,7 +929,8 @@ static int annotate_config__cmp(const void *name, const void *cfgp) return strcmp(name, cfg->name); } -static int annotate__config(const char *var, const char *value, void *data __used) +static int annotate__config(const char *var, const char *value, + void *data __maybe_unused) { struct annotate__config *cfg; const char *name; diff --git a/tools/perf/ui/gtk/browser.c b/tools/perf/ui/gtk/browser.c index 3c16ab5..55acba6 100644 --- a/tools/perf/ui/gtk/browser.c +++ b/tools/perf/ui/gtk/browser.c @@ -237,8 +237,9 @@ static GtkWidget *perf_gtk__setup_statusbar(void) int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, const char *help, - void (*timer) (void *arg)__used, - void *arg __used, int delay_secs __used) + void (*timer) (void *arg)__maybe_unused, + void *arg __maybe_unused, + int delay_secs __maybe_unused) { struct perf_evsel *pos; GtkWidget *vbox; diff --git a/tools/perf/ui/gtk/setup.c b/tools/perf/ui/gtk/setup.c index 2642943..3c4c6ef 100644 --- a/tools/perf/ui/gtk/setup.c +++ b/tools/perf/ui/gtk/setup.c @@ -12,7 +12,7 @@ int perf_gtk__init(void) return gtk_init_check(NULL, NULL) ? 0 : -1; } -void perf_gtk__exit(bool wait_for_ok __used) +void perf_gtk__exit(bool wait_for_ok __maybe_unused) { if (!perf_gtk__is_active_context(pgctx)) return; diff --git a/tools/perf/ui/gtk/util.c b/tools/perf/ui/gtk/util.c index b8efb96..8aada5b 100644 --- a/tools/perf/ui/gtk/util.c +++ b/tools/perf/ui/gtk/util.c @@ -117,8 +117,8 @@ struct perf_error_ops perf_gtk_eops = { * For now, just add stubs for NO_NEWT=1 build. */ #ifdef NO_NEWT_SUPPORT -void ui_progress__update(u64 curr __used, u64 total __used, - const char *title __used) +void ui_progress__update(u64 curr __maybe_unused, u64 total __maybe_unused, + const char *title __maybe_unused) { } #endif diff --git a/tools/perf/ui/helpline.c b/tools/perf/ui/helpline.c index 78ba28a..a49bcf3 100644 --- a/tools/perf/ui/helpline.c +++ b/tools/perf/ui/helpline.c @@ -12,7 +12,7 @@ static void nop_helpline__pop(void) { } -static void nop_helpline__push(const char *msg __used) +static void nop_helpline__push(const char *msg __maybe_unused) { } diff --git a/tools/perf/ui/helpline.h b/tools/perf/ui/helpline.h index a2487f9..2b667ee 100644 --- a/tools/perf/ui/helpline.h +++ b/tools/perf/ui/helpline.h @@ -24,8 +24,8 @@ void ui_helpline__puts(const char *msg); extern char ui_helpline__current[512]; #ifdef NO_NEWT_SUPPORT -static inline int ui_helpline__show_help(const char *format __used, - va_list ap __used) +static inline int ui_helpline__show_help(const char *format __maybe_unused, + va_list ap __maybe_unused) { return 0; } @@ -35,8 +35,8 @@ int ui_helpline__show_help(const char *format, va_list ap); #endif /* NO_NEWT_SUPPORT */ #ifdef NO_GTK2_SUPPORT -static inline int perf_gtk__show_helpline(const char *format __used, - va_list ap __used) +static inline int perf_gtk__show_helpline(const char *format __maybe_unused, + va_list ap __maybe_unused) { return 0; } diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 031b349..407e855 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -13,7 +13,7 @@ static int hpp__header_overhead(struct perf_hpp *hpp) return scnprintf(hpp->buf, hpp->size, fmt); } -static int hpp__width_overhead(struct perf_hpp *hpp __used) +static int hpp__width_overhead(struct perf_hpp *hpp __maybe_unused) { return 8; } @@ -62,7 +62,7 @@ static int hpp__header_overhead_sys(struct perf_hpp *hpp) return scnprintf(hpp->buf, hpp->size, fmt, "sys"); } -static int hpp__width_overhead_sys(struct perf_hpp *hpp __used) +static int hpp__width_overhead_sys(struct perf_hpp *hpp __maybe_unused) { return 6; } @@ -88,7 +88,7 @@ static int hpp__header_overhead_us(struct perf_hpp *hpp) return scnprintf(hpp->buf, hpp->size, fmt, "user"); } -static int hpp__width_overhead_us(struct perf_hpp *hpp __used) +static int hpp__width_overhead_us(struct perf_hpp *hpp __maybe_unused) { return 6; } @@ -112,7 +112,7 @@ static int hpp__header_overhead_guest_sys(struct perf_hpp *hpp) return scnprintf(hpp->buf, hpp->size, "guest sys"); } -static int hpp__width_overhead_guest_sys(struct perf_hpp *hpp __used) +static int hpp__width_overhead_guest_sys(struct perf_hpp *hpp __maybe_unused) { return 9; } @@ -138,7 +138,7 @@ static int hpp__header_overhead_guest_us(struct perf_hpp *hpp) return scnprintf(hpp->buf, hpp->size, "guest usr"); } -static int hpp__width_overhead_guest_us(struct perf_hpp *hpp __used) +static int hpp__width_overhead_guest_us(struct perf_hpp *hpp __maybe_unused) { return 9; } @@ -166,7 +166,7 @@ static int hpp__header_samples(struct perf_hpp *hpp) return scnprintf(hpp->buf, hpp->size, fmt, "Samples"); } -static int hpp__width_samples(struct perf_hpp *hpp __used) +static int hpp__width_samples(struct perf_hpp *hpp __maybe_unused) { return 11; } @@ -185,7 +185,7 @@ static int hpp__header_period(struct perf_hpp *hpp) return scnprintf(hpp->buf, hpp->size, fmt, "Period"); } -static int hpp__width_period(struct perf_hpp *hpp __used) +static int hpp__width_period(struct perf_hpp *hpp __maybe_unused) { return 12; } @@ -204,7 +204,7 @@ static int hpp__header_delta(struct perf_hpp *hpp) return scnprintf(hpp->buf, hpp->size, fmt, "Delta"); } -static int hpp__width_delta(struct perf_hpp *hpp __used) +static int hpp__width_delta(struct perf_hpp *hpp __maybe_unused) { return 7; } @@ -238,12 +238,13 @@ static int hpp__header_displ(struct perf_hpp *hpp) return scnprintf(hpp->buf, hpp->size, "Displ."); } -static int hpp__width_displ(struct perf_hpp *hpp __used) +static int hpp__width_displ(struct perf_hpp *hpp __maybe_unused) { return 6; } -static int hpp__entry_displ(struct perf_hpp *hpp, struct hist_entry *he __used) +static int hpp__entry_displ(struct perf_hpp *hpp, + struct hist_entry *he __maybe_unused) { const char *fmt = symbol_conf.field_sep ? "%s" : "%6.6s"; char buf[32] = " "; diff --git a/tools/perf/ui/tui/setup.c b/tools/perf/ui/tui/setup.c index 4dc0887..60debb8 100644 --- a/tools/perf/ui/tui/setup.c +++ b/tools/perf/ui/tui/setup.c @@ -28,7 +28,7 @@ void ui__refresh_dimensions(bool force) } } -static void ui__sigwinch(int sig __used) +static void ui__sigwinch(int sig __maybe_unused) { ui__need_resize = 1; } @@ -88,7 +88,7 @@ int ui__getch(int delay_secs) return SLkp_getkey(); } -static void newt_suspend(void *d __used) +static void newt_suspend(void *d __maybe_unused) { newtSuspend(); raise(SIGTSTP); diff --git a/tools/perf/util/alias.c b/tools/perf/util/alias.c index b8144e8..e6d1347 100644 --- a/tools/perf/util/alias.c +++ b/tools/perf/util/alias.c @@ -3,7 +3,8 @@ static const char *alias_key; static char *alias_val; -static int alias_lookup_cb(const char *k, const char *v, void *cb __used) +static int alias_lookup_cb(const char *k, const char *v, + void *cb __maybe_unused) { if (!prefixcmp(k, "alias.") && !strcmp(k+6, alias_key)) { if (!v) diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 04eafd3..f0a9103 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -313,8 +313,8 @@ static struct ins_ops dec_ops = { .scnprintf = dec__scnprintf, }; -static int nop__scnprintf(struct ins *ins __used, char *bf, size_t size, - struct ins_operands *ops __used) +static int nop__scnprintf(struct ins *ins __maybe_unused, char *bf, size_t size, + struct ins_operands *ops __maybe_unused) { return scnprintf(bf, size, "%-6.6s", "nop"); } @@ -416,7 +416,7 @@ static struct ins *ins__find(const char *name) return bsearch(name, instructions, nmemb, sizeof(struct ins), ins__cmp); } -int symbol__annotate_init(struct map *map __used, struct symbol *sym) +int symbol__annotate_init(struct map *map __maybe_unused, struct symbol *sym) { struct annotation *notes = symbol__annotation(sym); pthread_mutex_init(¬es->lock, NULL); diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index 62a6e7a..9b5b21e 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h @@ -126,7 +126,7 @@ int symbol__alloc_hist(struct symbol *sym); void symbol__annotate_zero_histograms(struct symbol *sym); int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize); -int symbol__annotate_init(struct map *map __used, struct symbol *sym); +int symbol__annotate_init(struct map *map __maybe_unused, struct symbol *sym); int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx, bool full_paths, int min_pcnt, int max_lines, int context); @@ -139,11 +139,12 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx, int max_lines); #ifdef NO_NEWT_SUPPORT -static inline int symbol__tui_annotate(struct symbol *sym __used, - struct map *map __used, - int evidx __used, - void(*timer)(void *arg) __used, - void *arg __used, int delay_secs __used) +static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused, + struct map *map __maybe_unused, + int evidx __maybe_unused, + void(*timer)(void *arg) __maybe_unused, + void *arg __maybe_unused, + int delay_secs __maybe_unused) { return 0; } diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c index fd9a594..8e3a740 100644 --- a/tools/perf/util/build-id.c +++ b/tools/perf/util/build-id.c @@ -16,10 +16,10 @@ #include "session.h" #include "tool.h" -static int build_id__mark_dso_hit(struct perf_tool *tool __used, +static int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused, union perf_event *event, - struct perf_sample *sample __used, - struct perf_evsel *evsel __used, + struct perf_sample *sample __maybe_unused, + struct perf_evsel *evsel __maybe_unused, struct machine *machine) { struct addr_location al; @@ -41,9 +41,10 @@ static int build_id__mark_dso_hit(struct perf_tool *tool __used, return 0; } -static int perf_event__exit_del_thread(struct perf_tool *tool __used, +static int perf_event__exit_del_thread(struct perf_tool *tool __maybe_unused, union perf_event *event, - struct perf_sample *sample __used, + struct perf_sample *sample + __maybe_unused, struct machine *machine) { struct thread *thread = machine__findnew_thread(machine, event->fork.tid); diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h index cff18c6..ab17694 100644 --- a/tools/perf/util/cache.h +++ b/tools/perf/util/cache.h @@ -39,7 +39,7 @@ static inline void setup_browser(bool fallback_to_pager) if (fallback_to_pager) setup_pager(); } -static inline void exit_browser(bool wait_for_ok __used) {} +static inline void exit_browser(bool wait_for_ok __maybe_unused) {} #else void setup_browser(bool fallback_to_pager); void exit_browser(bool wait_for_ok); @@ -49,7 +49,7 @@ static inline int ui__init(void) { return -1; } -static inline void ui__exit(bool wait_for_ok __used) {} +static inline void ui__exit(bool wait_for_ok __maybe_unused) {} #else int ui__init(void); void ui__exit(bool wait_for_ok); @@ -60,7 +60,7 @@ static inline int perf_gtk__init(void) { return -1; } -static inline void perf_gtk__exit(bool wait_for_ok __used) {} +static inline void perf_gtk__exit(bool wait_for_ok __maybe_unused) {} #else int perf_gtk__init(void); void perf_gtk__exit(bool wait_for_ok); diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index 3a6bff4..d3b3f5d 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c @@ -93,7 +93,7 @@ __sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node, */ static void sort_chain_flat(struct rb_root *rb_root, struct callchain_root *root, - u64 min_hit, struct callchain_param *param __used) + u64 min_hit, struct callchain_param *param __maybe_unused) { __sort_chain_flat(rb_root, &root->node, min_hit); } @@ -115,7 +115,7 @@ static void __sort_chain_graph_abs(struct callchain_node *node, static void sort_chain_graph_abs(struct rb_root *rb_root, struct callchain_root *chain_root, - u64 min_hit, struct callchain_param *param __used) + u64 min_hit, struct callchain_param *param __maybe_unused) { __sort_chain_graph_abs(&chain_root->node, min_hit); rb_root->rb_node = chain_root->node.rb_root.rb_node; @@ -140,7 +140,7 @@ static void __sort_chain_graph_rel(struct callchain_node *node, static void sort_chain_graph_rel(struct rb_root *rb_root, struct callchain_root *chain_root, - u64 min_hit __used, struct callchain_param *param) + u64 min_hit __maybe_unused, struct callchain_param *param) { __sort_chain_graph_rel(&chain_root->node, param->min_percent / 100.0); rb_root->rb_node = chain_root->node.rb_root.rb_node; diff --git a/tools/perf/util/cgroup.c b/tools/perf/util/cgroup.c index dbe2f16..96bbda1 100644 --- a/tools/perf/util/cgroup.c +++ b/tools/perf/util/cgroup.c @@ -138,8 +138,8 @@ void close_cgroup(struct cgroup_sel *cgrp) } } -int parse_cgroups(const struct option *opt __used, const char *str, - int unset __used) +int parse_cgroups(const struct option *opt __maybe_unused, const char *str, + int unset __maybe_unused) { struct perf_evlist *evlist = *(struct perf_evlist **)opt->value; const char *p, *e, *eos = str + strlen(str); diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c index 6faa3a1..3e0fdd3 100644 --- a/tools/perf/util/config.c +++ b/tools/perf/util/config.c @@ -342,13 +342,15 @@ const char *perf_config_dirname(const char *name, const char *value) return value; } -static int perf_default_core_config(const char *var __used, const char *value __used) +static int perf_default_core_config(const char *var __maybe_unused, + const char *value __maybe_unused) { /* Add other config variables here. */ return 0; } -int perf_default_config(const char *var, const char *value, void *dummy __used) +int perf_default_config(const char *var, const char *value, + void *dummy __maybe_unused) { if (!prefixcmp(var, "core.")) return perf_default_core_config(var, value); diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h index 05e660c..bb2e7d1 100644 --- a/tools/perf/util/debug.h +++ b/tools/perf/util/debug.h @@ -16,19 +16,20 @@ struct ui_progress; struct perf_error_ops; #if defined(NO_NEWT_SUPPORT) && defined(NO_GTK2_SUPPORT) -static inline void ui_progress__update(u64 curr __used, u64 total __used, - const char *title __used) {} +static inline void ui_progress__update(u64 curr __maybe_unused, + u64 total __maybe_unused, + const char *title __maybe_unused) {} #define ui__error(format, arg...) ui__warning(format, ##arg) static inline int -perf_error__register(struct perf_error_ops *eops __used) +perf_error__register(struct perf_error_ops *eops __maybe_unused) { return 0; } static inline int -perf_error__unregister(struct perf_error_ops *eops __used) +perf_error__unregister(struct perf_error_ops *eops __maybe_unused) { return 0; } diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 84ff6f16..8202f5c 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -112,7 +112,7 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool, event->comm.header.type = PERF_RECORD_COMM; size = strlen(event->comm.comm) + 1; - size = ALIGN(size, sizeof(u64)); + size = PERF_ALIGN(size, sizeof(u64)); memset(event->comm.comm + size, 0, machine->id_hdr_size); event->comm.header.size = (sizeof(event->comm) - (sizeof(event->comm.comm) - size) + @@ -145,7 +145,7 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool, sizeof(event->comm.comm)); size = strlen(event->comm.comm) + 1; - size = ALIGN(size, sizeof(u64)); + size = PERF_ALIGN(size, sizeof(u64)); memset(event->comm.comm + size, 0, machine->id_hdr_size); event->comm.header.size = (sizeof(event->comm) - (sizeof(event->comm.comm) - size) + @@ -228,7 +228,7 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool, size = strlen(execname); execname[size - 1] = '\0'; /* Remove \n */ memcpy(event->mmap.filename, execname, size); - size = ALIGN(size, sizeof(u64)); + size = PERF_ALIGN(size, sizeof(u64)); event->mmap.len -= event->mmap.start; event->mmap.header.size = (sizeof(event->mmap) - (sizeof(event->mmap.filename) - size)); @@ -282,7 +282,7 @@ int perf_event__synthesize_modules(struct perf_tool *tool, if (pos->dso->kernel) continue; - size = ALIGN(pos->dso->long_name_len + 1, sizeof(u64)); + size = PERF_ALIGN(pos->dso->long_name_len + 1, sizeof(u64)); event->mmap.header.type = PERF_RECORD_MMAP; event->mmap.header.size = (sizeof(event->mmap) - (sizeof(event->mmap.filename) - size)); @@ -494,7 +494,7 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool, map = machine->vmlinux_maps[MAP__FUNCTION]; size = snprintf(event->mmap.filename, sizeof(event->mmap.filename), "%s%s", mmap_name, symbol_name) + 1; - size = ALIGN(size, sizeof(u64)); + size = PERF_ALIGN(size, sizeof(u64)); event->mmap.header.type = PERF_RECORD_MMAP; event->mmap.header.size = (sizeof(event->mmap) - (sizeof(event->mmap.filename) - size) + machine->id_hdr_size); @@ -514,9 +514,9 @@ size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp) return fprintf(fp, ": %s:%d\n", event->comm.comm, event->comm.tid); } -int perf_event__process_comm(struct perf_tool *tool __used, +int perf_event__process_comm(struct perf_tool *tool __maybe_unused, union perf_event *event, - struct perf_sample *sample __used, + struct perf_sample *sample __maybe_unused, struct machine *machine) { struct thread *thread = machine__findnew_thread(machine, event->comm.tid); @@ -532,10 +532,10 @@ int perf_event__process_comm(struct perf_tool *tool __used, return 0; } -int perf_event__process_lost(struct perf_tool *tool __used, +int perf_event__process_lost(struct perf_tool *tool __maybe_unused, union perf_event *event, - struct perf_sample *sample __used, - struct machine *machine __used) + struct perf_sample *sample __maybe_unused, + struct machine *machine __maybe_unused) { dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n", event->lost.id, event->lost.lost); @@ -555,7 +555,8 @@ static void perf_event__set_kernel_mmap_len(union perf_event *event, maps[MAP__FUNCTION]->end = ~0ULL; } -static int perf_event__process_kernel_mmap(struct perf_tool *tool __used, +static int perf_event__process_kernel_mmap(struct perf_tool *tool + __maybe_unused, union perf_event *event, struct machine *machine) { @@ -657,7 +658,7 @@ size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp) int perf_event__process_mmap(struct perf_tool *tool, union perf_event *event, - struct perf_sample *sample __used, + struct perf_sample *sample __maybe_unused, struct machine *machine) { struct thread *thread; @@ -701,9 +702,9 @@ size_t perf_event__fprintf_task(union perf_event *event, FILE *fp) event->fork.ppid, event->fork.ptid); } -int perf_event__process_task(struct perf_tool *tool __used, +int perf_event__process_task(struct perf_tool *tool __maybe_unused, union perf_event *event, - struct perf_sample *sample __used, + struct perf_sample *sample __maybe_unused, struct machine *machine) { struct thread *thread = machine__findnew_thread(machine, event->fork.tid); diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index 0e088d0..21b99e7 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h @@ -101,7 +101,7 @@ struct perf_sample { struct build_id_event { struct perf_event_header header; pid_t pid; - u8 build_id[ALIGN(BUILD_ID_SIZE, sizeof(u64))]; + u8 build_id[PERF_ALIGN(BUILD_ID_SIZE, sizeof(u64))]; char filename[]; }; diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 06f7644..1506ba0 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -10,6 +10,7 @@ #include <byteswap.h> #include <linux/bitops.h> #include "asm/bug.h" +#include "event-parse.h" #include "evsel.h" #include "evlist.h" #include "util.h" @@ -1000,3 +1001,37 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type, return 0; } + +char *perf_evsel__strval(struct perf_evsel *evsel, struct perf_sample *sample, + const char *name) +{ + struct format_field *field = pevent_find_field(evsel->tp_format, name); + int offset; + + if (!field) + return NULL; + + offset = field->offset; + + if (field->flags & FIELD_IS_DYNAMIC) { + offset = *(int *)(sample->raw_data + field->offset); + offset &= 0xffff; + } + + return sample->raw_data + offset; +} + +u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample, + const char *name) +{ + struct format_field *field = pevent_find_field(evsel->tp_format, name); + u64 val; + + if (!field) + return 0; + + val = pevent_read_number(evsel->tp_format->pevent, + sample->raw_data + field->offset, field->size); + return val; + +} diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 390690e..dc40fe3 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -120,6 +120,13 @@ int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, struct thread_map *threads); void perf_evsel__close(struct perf_evsel *evsel, int ncpus, int nthreads); +struct perf_sample; + +char *perf_evsel__strval(struct perf_evsel *evsel, struct perf_sample *sample, + const char *name); +u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample, + const char *name); + #define perf_evsel__match(evsel, t, c) \ (evsel->attr.type == PERF_TYPE_##t && \ evsel->attr.config == PERF_COUNT_##c) diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index d07bc13..acbf633 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -21,6 +21,7 @@ #include "debug.h" #include "cpumap.h" #include "pmu.h" +#include "vdso.h" static bool no_buildid_cache = false; @@ -129,7 +130,7 @@ static int do_write_string(int fd, const char *str) int ret; olen = strlen(str) + 1; - len = ALIGN(olen, NAME_ALIGN); + len = PERF_ALIGN(olen, NAME_ALIGN); /* write len, incl. \0 */ ret = do_write(fd, &len, sizeof(len)); @@ -207,6 +208,29 @@ perf_header__set_cmdline(int argc, const char **argv) continue; \ else +static int write_buildid(char *name, size_t name_len, u8 *build_id, + pid_t pid, u16 misc, int fd) +{ + int err; + struct build_id_event b; + size_t len; + + len = name_len + 1; + len = PERF_ALIGN(len, NAME_ALIGN); + + memset(&b, 0, sizeof(b)); + memcpy(&b.build_id, build_id, BUILD_ID_SIZE); + b.pid = pid; + b.header.misc = misc; + b.header.size = sizeof(b) + len; + + err = do_write(fd, &b, sizeof(b)); + if (err < 0) + return err; + + return write_padded(fd, name, name_len + 1, len); +} + static int __dsos__write_buildid_table(struct list_head *head, pid_t pid, u16 misc, int fd) { @@ -214,24 +238,23 @@ static int __dsos__write_buildid_table(struct list_head *head, pid_t pid, dsos__for_each_with_build_id(pos, head) { int err; - struct build_id_event b; - size_t len; + char *name; + size_t name_len; if (!pos->hit) continue; - len = pos->long_name_len + 1; - len = ALIGN(len, NAME_ALIGN); - memset(&b, 0, sizeof(b)); - memcpy(&b.build_id, pos->build_id, sizeof(pos->build_id)); - b.pid = pid; - b.header.misc = misc; - b.header.size = sizeof(b) + len; - err = do_write(fd, &b, sizeof(b)); - if (err < 0) - return err; - err = write_padded(fd, pos->long_name, - pos->long_name_len + 1, len); - if (err < 0) + + if (is_vdso_map(pos->short_name)) { + name = (char *) VDSO__MAP_NAME; + name_len = sizeof(VDSO__MAP_NAME) + 1; + } else { + name = pos->long_name; + name_len = pos->long_name_len + 1; + } + + err = write_buildid(name, name_len, pos->build_id, + pid, misc, fd); + if (err) return err; } @@ -277,19 +300,20 @@ static int dsos__write_buildid_table(struct perf_header *header, int fd) } int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, - const char *name, bool is_kallsyms) + const char *name, bool is_kallsyms, bool is_vdso) { const size_t size = PATH_MAX; char *realname, *filename = zalloc(size), *linkname = zalloc(size), *targetname; int len, err = -1; + bool slash = is_kallsyms || is_vdso; if (is_kallsyms) { if (symbol_conf.kptr_restrict) { pr_debug("Not caching a kptr_restrict'ed /proc/kallsyms\n"); return 0; } - realname = (char *)name; + realname = (char *) name; } else realname = realpath(name, NULL); @@ -297,7 +321,8 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, goto out_free; len = scnprintf(filename, size, "%s%s%s", - debugdir, is_kallsyms ? "/" : "", realname); + debugdir, slash ? "/" : "", + is_vdso ? VDSO__MAP_NAME : realname); if (mkdir_p(filename, 0755)) goto out_free; @@ -333,13 +358,14 @@ out_free: static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size, const char *name, const char *debugdir, - bool is_kallsyms) + bool is_kallsyms, bool is_vdso) { char sbuild_id[BUILD_ID_SIZE * 2 + 1]; build_id__sprintf(build_id, build_id_size, sbuild_id); - return build_id_cache__add_s(sbuild_id, debugdir, name, is_kallsyms); + return build_id_cache__add_s(sbuild_id, debugdir, name, + is_kallsyms, is_vdso); } int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir) @@ -383,9 +409,11 @@ out_free: static int dso__cache_build_id(struct dso *dso, const char *debugdir) { bool is_kallsyms = dso->kernel && dso->long_name[0] != '/'; + bool is_vdso = is_vdso_map(dso->short_name); return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), - dso->long_name, debugdir, is_kallsyms); + dso->long_name, debugdir, + is_kallsyms, is_vdso); } static int __dsos__cache_build_ids(struct list_head *head, const char *debugdir) @@ -447,7 +475,7 @@ static bool perf_session__read_build_ids(struct perf_session *session, bool with return ret; } -static int write_tracing_data(int fd, struct perf_header *h __used, +static int write_tracing_data(int fd, struct perf_header *h __maybe_unused, struct perf_evlist *evlist) { return read_tracing_data(fd, &evlist->entries); @@ -455,7 +483,7 @@ static int write_tracing_data(int fd, struct perf_header *h __used, static int write_build_id(int fd, struct perf_header *h, - struct perf_evlist *evlist __used) + struct perf_evlist *evlist __maybe_unused) { struct perf_session *session; int err; @@ -476,8 +504,8 @@ static int write_build_id(int fd, struct perf_header *h, return 0; } -static int write_hostname(int fd, struct perf_header *h __used, - struct perf_evlist *evlist __used) +static int write_hostname(int fd, struct perf_header *h __maybe_unused, + struct perf_evlist *evlist __maybe_unused) { struct utsname uts; int ret; @@ -489,8 +517,8 @@ static int write_hostname(int fd, struct perf_header *h __used, return do_write_string(fd, uts.nodename); } -static int write_osrelease(int fd, struct perf_header *h __used, - struct perf_evlist *evlist __used) +static int write_osrelease(int fd, struct perf_header *h __maybe_unused, + struct perf_evlist *evlist __maybe_unused) { struct utsname uts; int ret; @@ -502,8 +530,8 @@ static int write_osrelease(int fd, struct perf_header *h __used, return do_write_string(fd, uts.release); } -static int write_arch(int fd, struct perf_header *h __used, - struct perf_evlist *evlist __used) +static int write_arch(int fd, struct perf_header *h __maybe_unused, + struct perf_evlist *evlist __maybe_unused) { struct utsname uts; int ret; @@ -515,14 +543,14 @@ static int write_arch(int fd, struct perf_header *h __used, return do_write_string(fd, uts.machine); } -static int write_version(int fd, struct perf_header *h __used, - struct perf_evlist *evlist __used) +static int write_version(int fd, struct perf_header *h __maybe_unused, + struct perf_evlist *evlist __maybe_unused) { return do_write_string(fd, perf_version_string); } -static int write_cpudesc(int fd, struct perf_header *h __used, - struct perf_evlist *evlist __used) +static int write_cpudesc(int fd, struct perf_header *h __maybe_unused, + struct perf_evlist *evlist __maybe_unused) { #ifndef CPUINFO_PROC #define CPUINFO_PROC NULL @@ -580,8 +608,8 @@ done: return ret; } -static int write_nrcpus(int fd, struct perf_header *h __used, - struct perf_evlist *evlist __used) +static int write_nrcpus(int fd, struct perf_header *h __maybe_unused, + struct perf_evlist *evlist __maybe_unused) { long nr; u32 nrc, nra; @@ -606,7 +634,7 @@ static int write_nrcpus(int fd, struct perf_header *h __used, return do_write(fd, &nra, sizeof(nra)); } -static int write_event_desc(int fd, struct perf_header *h __used, +static int write_event_desc(int fd, struct perf_header *h __maybe_unused, struct perf_evlist *evlist) { struct perf_evsel *evsel; @@ -663,8 +691,8 @@ static int write_event_desc(int fd, struct perf_header *h __used, return 0; } -static int write_cmdline(int fd, struct perf_header *h __used, - struct perf_evlist *evlist __used) +static int write_cmdline(int fd, struct perf_header *h __maybe_unused, + struct perf_evlist *evlist __maybe_unused) { char buf[MAXPATHLEN]; char proc[32]; @@ -832,8 +860,8 @@ static struct cpu_topo *build_cpu_topology(void) return tp; } -static int write_cpu_topology(int fd, struct perf_header *h __used, - struct perf_evlist *evlist __used) +static int write_cpu_topology(int fd, struct perf_header *h __maybe_unused, + struct perf_evlist *evlist __maybe_unused) { struct cpu_topo *tp; u32 i; @@ -868,8 +896,8 @@ done: -static int write_total_mem(int fd, struct perf_header *h __used, - struct perf_evlist *evlist __used) +static int write_total_mem(int fd, struct perf_header *h __maybe_unused, + struct perf_evlist *evlist __maybe_unused) { char *buf = NULL; FILE *fp; @@ -954,8 +982,8 @@ done: return ret; } -static int write_numa_topology(int fd, struct perf_header *h __used, - struct perf_evlist *evlist __used) +static int write_numa_topology(int fd, struct perf_header *h __maybe_unused, + struct perf_evlist *evlist __maybe_unused) { char *buf = NULL; size_t len = 0; @@ -1015,8 +1043,8 @@ done: * }; */ -static int write_pmu_mappings(int fd, struct perf_header *h __used, - struct perf_evlist *evlist __used) +static int write_pmu_mappings(int fd, struct perf_header *h __maybe_unused, + struct perf_evlist *evlist __maybe_unused) { struct perf_pmu *pmu = NULL; off_t offset = lseek(fd, 0, SEEK_CUR); @@ -1046,13 +1074,14 @@ static int write_pmu_mappings(int fd, struct perf_header *h __used, * default get_cpuid(): nothing gets recorded * actual implementation must be in arch/$(ARCH)/util/header.c */ -int __attribute__((weak)) get_cpuid(char *buffer __used, size_t sz __used) +int __attribute__ ((weak)) get_cpuid(char *buffer __maybe_unused, + size_t sz __maybe_unused) { return -1; } -static int write_cpuid(int fd, struct perf_header *h __used, - struct perf_evlist *evlist __used) +static int write_cpuid(int fd, struct perf_header *h __maybe_unused, + struct perf_evlist *evlist __maybe_unused) { char buffer[64]; int ret; @@ -1066,8 +1095,9 @@ write_it: return do_write_string(fd, buffer); } -static int write_branch_stack(int fd __used, struct perf_header *h __used, - struct perf_evlist *evlist __used) +static int write_branch_stack(int fd __maybe_unused, + struct perf_header *h __maybe_unused, + struct perf_evlist *evlist __maybe_unused) { return 0; } @@ -1344,7 +1374,8 @@ static void print_event_desc(struct perf_header *ph, int fd, FILE *fp) free_event_desc(events); } -static void print_total_mem(struct perf_header *h __used, int fd, FILE *fp) +static void print_total_mem(struct perf_header *h __maybe_unused, int fd, + FILE *fp) { uint64_t mem; ssize_t ret; @@ -1362,7 +1393,8 @@ error: fprintf(fp, "# total memory : unknown\n"); } -static void print_numa_topology(struct perf_header *h __used, int fd, FILE *fp) +static void print_numa_topology(struct perf_header *h __maybe_unused, int fd, + FILE *fp) { ssize_t ret; u32 nr, c, i; @@ -1422,7 +1454,8 @@ static void print_cpuid(struct perf_header *ph, int fd, FILE *fp) free(str); } -static void print_branch_stack(struct perf_header *ph __used, int fd __used, +static void print_branch_stack(struct perf_header *ph __maybe_unused, + int fd __maybe_unused, FILE *fp) { fprintf(fp, "# contains samples with branch stack\n"); @@ -1532,7 +1565,7 @@ static int perf_header__read_build_ids_abi_quirk(struct perf_header *header, struct perf_session *session = container_of(header, struct perf_session, header); struct { struct perf_event_header header; - u8 build_id[ALIGN(BUILD_ID_SIZE, sizeof(u64))]; + u8 build_id[PERF_ALIGN(BUILD_ID_SIZE, sizeof(u64))]; char filename[0]; } old_bev; struct build_id_event bev; @@ -1621,9 +1654,10 @@ out: return err; } -static int process_tracing_data(struct perf_file_section *section __unused, - struct perf_header *ph __unused, - int feat __unused, int fd, void *data) +static int process_tracing_data(struct perf_file_section *section + __maybe_unused, + struct perf_header *ph __maybe_unused, + int feat __maybe_unused, int fd, void *data) { trace_report(fd, data, false); return 0; @@ -1631,7 +1665,8 @@ static int process_tracing_data(struct perf_file_section *section __unused, static int process_build_id(struct perf_file_section *section, struct perf_header *ph, - int feat __unused, int fd, void *data __used) + int feat __maybe_unused, int fd, + void *data __maybe_unused) { if (perf_header__read_build_ids(ph, fd, section->offset, section->size)) pr_debug("Failed to read buildids, continuing...\n"); @@ -1670,9 +1705,9 @@ perf_evlist__set_event_name(struct perf_evlist *evlist, struct perf_evsel *event } static int -process_event_desc(struct perf_file_section *section __unused, - struct perf_header *header, int feat __unused, int fd, - void *data __used) +process_event_desc(struct perf_file_section *section __maybe_unused, + struct perf_header *header, int feat __maybe_unused, int fd, + void *data __maybe_unused) { struct perf_session *session = container_of(header, struct perf_session, header); struct perf_evsel *evsel, *events = read_event_desc(header, fd); @@ -2439,7 +2474,7 @@ int perf_event__synthesize_attr(struct perf_tool *tool, int err; size = sizeof(struct perf_event_attr); - size = ALIGN(size, sizeof(u64)); + size = PERF_ALIGN(size, sizeof(u64)); size += sizeof(struct perf_event_header); size += ids * sizeof(u64); @@ -2537,7 +2572,7 @@ int perf_event__synthesize_event_type(struct perf_tool *tool, ev.event_type.header.type = PERF_RECORD_HEADER_EVENT_TYPE; size = strlen(ev.event_type.event_type.name); - size = ALIGN(size, sizeof(u64)); + size = PERF_ALIGN(size, sizeof(u64)); ev.event_type.header.size = sizeof(ev.event_type) - (sizeof(ev.event_type.event_type.name) - size); @@ -2568,7 +2603,7 @@ int perf_event__synthesize_event_types(struct perf_tool *tool, return err; } -int perf_event__process_event_type(struct perf_tool *tool __unused, +int perf_event__process_event_type(struct perf_tool *tool __maybe_unused, union perf_event *event) { if (perf_header__push_event(event->event_type.event_type.event_id, @@ -2585,7 +2620,7 @@ int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd, union perf_event ev; struct tracing_data *tdata; ssize_t size = 0, aligned_size = 0, padding; - int err __used = 0; + int err __maybe_unused = 0; /* * We are going to store the size of the data followed @@ -2606,7 +2641,7 @@ int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd, ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA; size = tdata->size; - aligned_size = ALIGN(size, sizeof(u64)); + aligned_size = PERF_ALIGN(size, sizeof(u64)); padding = aligned_size - size; ev.tracing_data.header.size = sizeof(ev.tracing_data); ev.tracing_data.size = aligned_size; @@ -2637,7 +2672,7 @@ int perf_event__process_tracing_data(union perf_event *event, size_read = trace_report(session->fd, &session->pevent, session->repipe); - padding = ALIGN(size_read, sizeof(u64)) - size_read; + padding = PERF_ALIGN(size_read, sizeof(u64)) - size_read; if (read(session->fd, buf, padding) < 0) die("reading input file"); @@ -2671,7 +2706,7 @@ int perf_event__synthesize_build_id(struct perf_tool *tool, memset(&ev, 0, sizeof(ev)); len = pos->long_name_len + 1; - len = ALIGN(len, NAME_ALIGN); + len = PERF_ALIGN(len, NAME_ALIGN); memcpy(&ev.build_id.build_id, pos->build_id, sizeof(pos->build_id)); ev.build_id.header.type = PERF_RECORD_HEADER_BUILD_ID; ev.build_id.header.misc = misc; @@ -2684,7 +2719,7 @@ int perf_event__synthesize_build_id(struct perf_tool *tool, return err; } -int perf_event__process_build_id(struct perf_tool *tool __used, +int perf_event__process_build_id(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_session *session) { diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index 9d5eedc..209dad4 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h @@ -96,7 +96,7 @@ int perf_header__process_sections(struct perf_header *header, int fd, int perf_header__fprintf_info(struct perf_session *s, FILE *fp, bool full); int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, - const char *name, bool is_kallsyms); + const char *name, bool is_kallsyms, bool is_vdso); int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir); int perf_event__synthesize_attr(struct perf_tool *tool, diff --git a/tools/perf/util/help.c b/tools/perf/util/help.c index 4fa764d..8b1f6e8 100644 --- a/tools/perf/util/help.c +++ b/tools/perf/util/help.c @@ -332,7 +332,8 @@ const char *help_unknown_cmd(const char *cmd) exit(1); } -int cmd_version(int argc __used, const char **argv __used, const char *prefix __used) +int cmd_version(int argc __maybe_unused, const char **argv __maybe_unused, + const char *prefix __maybe_unused) { printf("perf version %s\n", perf_version_string); return 0; diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 0ba65ad..6ec5398 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -394,7 +394,7 @@ void hist_entry__free(struct hist_entry *he) * collapse the histogram */ -static bool hists__collapse_insert_entry(struct hists *hists __used, +static bool hists__collapse_insert_entry(struct hists *hists __maybe_unused, struct rb_root *root, struct hist_entry *he) { diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 4146f51..f011ad4 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -156,20 +156,22 @@ struct perf_evlist; #ifdef NO_NEWT_SUPPORT static inline -int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __used, - const char *help __used, - void(*timer)(void *arg) __used, - void *arg __used, - int refresh __used) +int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused, + const char *help __maybe_unused, + void(*timer)(void *arg) __maybe_unused, + void *arg __maybe_unused, + int refresh __maybe_unused) { return 0; } -static inline int hist_entry__tui_annotate(struct hist_entry *self __used, - int evidx __used, - void(*timer)(void *arg) __used, - void *arg __used, - int delay_secs __used) +static inline int hist_entry__tui_annotate(struct hist_entry *self + __maybe_unused, + int evidx __maybe_unused, + void(*timer)(void *arg) + __maybe_unused, + void *arg __maybe_unused, + int delay_secs __maybe_unused) { return 0; } @@ -187,11 +189,11 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, #ifdef NO_GTK2_SUPPORT static inline -int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __used, - const char *help __used, - void(*timer)(void *arg) __used, - void *arg __used, - int refresh __used) +int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __maybe_unused, + const char *help __maybe_unused, + void(*timer)(void *arg) __maybe_unused, + void *arg __maybe_unused, + int refresh __maybe_unused) { return 0; } diff --git a/tools/perf/util/include/linux/bitops.h b/tools/perf/util/include/linux/bitops.h index 587a230..a55d8cf0 100644 --- a/tools/perf/util/include/linux/bitops.h +++ b/tools/perf/util/include/linux/bitops.h @@ -5,6 +5,10 @@ #include <linux/compiler.h> #include <asm/hweight.h> +#ifndef __WORDSIZE +#define __WORDSIZE (__SIZEOF_LONG__ * 8) +#endif + #define BITS_PER_LONG __WORDSIZE #define BITS_PER_BYTE 8 #define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long)) diff --git a/tools/perf/util/include/linux/compiler.h b/tools/perf/util/include/linux/compiler.h index 2dc8671..96b919d 100644 --- a/tools/perf/util/include/linux/compiler.h +++ b/tools/perf/util/include/linux/compiler.h @@ -9,7 +9,13 @@ #define __attribute_const__ #endif -#define __used __attribute__((__unused__)) +#ifndef __maybe_unused +#define __maybe_unused __attribute__((unused)) +#endif #define __packed __attribute__((__packed__)) +#ifndef __force +#define __force +#endif + #endif diff --git a/tools/perf/util/include/linux/kernel.h b/tools/perf/util/include/linux/kernel.h index 4af9a10..d8c927c 100644 --- a/tools/perf/util/include/linux/kernel.h +++ b/tools/perf/util/include/linux/kernel.h @@ -8,8 +8,8 @@ #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) -#define ALIGN(x,a) __ALIGN_MASK(x,(typeof(x))(a)-1) -#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask)) +#define PERF_ALIGN(x, a) __PERF_ALIGN_MASK(x, (typeof(x))(a)-1) +#define __PERF_ALIGN_MASK(x, mask) (((x)+(mask))&~(mask)) #ifndef offsetof #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) @@ -46,6 +46,15 @@ _min1 < _min2 ? _min1 : _min2; }) #endif +#ifndef roundup +#define roundup(x, y) ( \ +{ \ + const typeof(y) __y = y; \ + (((x) + (__y - 1)) / __y) * __y; \ +} \ +) +#endif + #ifndef BUG_ON #ifdef NDEBUG #define BUG_ON(cond) do { if (cond) {} } while (0) diff --git a/tools/perf/util/include/linux/magic.h b/tools/perf/util/include/linux/magic.h new file mode 100644 index 0000000..58b64ed --- /dev/null +++ b/tools/perf/util/include/linux/magic.h @@ -0,0 +1,12 @@ +#ifndef _PERF_LINUX_MAGIC_H_ +#define _PERF_LINUX_MAGIC_H_ + +#ifndef DEBUGFS_MAGIC +#define DEBUGFS_MAGIC 0x64626720 +#endif + +#ifndef SYSFS_MAGIC +#define SYSFS_MAGIC 0x62656572 +#endif + +#endif diff --git a/tools/perf/util/include/linux/string.h b/tools/perf/util/include/linux/string.h index 3b2f590..6f19c54 100644 --- a/tools/perf/util/include/linux/string.h +++ b/tools/perf/util/include/linux/string.h @@ -1 +1,3 @@ #include <string.h> + +void *memdup(const void *src, size_t len); diff --git a/tools/perf/util/include/linux/types.h b/tools/perf/util/include/linux/types.h index 12de3b8..eb46478 100644 --- a/tools/perf/util/include/linux/types.h +++ b/tools/perf/util/include/linux/types.h @@ -3,6 +3,14 @@ #include <asm/types.h> +#ifndef __bitwise +#define __bitwise +#endif + +#ifndef __le32 +typedef __u32 __bitwise __le32; +#endif + #define DECLARE_BITMAP(name,bits) \ unsigned long name[BITS_TO_LONGS(bits)] diff --git a/tools/perf/util/intlist.c b/tools/perf/util/intlist.c index 77c504f..9d07400 100644 --- a/tools/perf/util/intlist.c +++ b/tools/perf/util/intlist.c @@ -11,7 +11,7 @@ #include "intlist.h" -static struct rb_node *intlist__node_new(struct rblist *rblist __used, +static struct rb_node *intlist__node_new(struct rblist *rblist __maybe_unused, const void *entry) { int i = (int)((long)entry); @@ -31,7 +31,7 @@ static void int_node__delete(struct int_node *ilist) free(ilist); } -static void intlist__node_delete(struct rblist *rblist __used, +static void intlist__node_delete(struct rblist *rblist __maybe_unused, struct rb_node *rb_node) { struct int_node *node = container_of(rb_node, struct int_node, rb_node); diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 7d37159..b442ee4 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c @@ -9,6 +9,7 @@ #include "map.h" #include "thread.h" #include "strlist.h" +#include "vdso.h" const char *map_type__name[MAP__NR_TYPES] = { [MAP__FUNCTION] = "Functions", @@ -23,7 +24,6 @@ static inline int is_anon_memory(const char *filename) static inline int is_no_dso_memory(const char *filename) { return !strcmp(filename, "[stack]") || - !strcmp(filename, "[vdso]") || !strcmp(filename, "[heap]"); } @@ -52,9 +52,10 @@ struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, if (self != NULL) { char newfilename[PATH_MAX]; struct dso *dso; - int anon, no_dso; + int anon, no_dso, vdso; anon = is_anon_memory(filename); + vdso = is_vdso_map(filename); no_dso = is_no_dso_memory(filename); if (anon) { @@ -62,7 +63,12 @@ struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, filename = newfilename; } - dso = __dsos__findnew(dsos__list, filename); + if (vdso) { + pgoff = 0; + dso = vdso__dso_findnew(dsos__list); + } else + dso = __dsos__findnew(dsos__list, filename); + if (dso == NULL) goto out_delete; diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index 25ab4cd..d2250fc 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h @@ -96,7 +96,7 @@ static inline u64 map__unmap_ip(struct map *map, u64 ip) return ip + map->start - map->pgoff; } -static inline u64 identity__map_ip(struct map *map __used, u64 ip) +static inline u64 identity__map_ip(struct map *map __maybe_unused, u64 ip) { return ip; } diff --git a/tools/perf/util/parse-events-test.c b/tools/perf/util/parse-events-test.c index bc8b651..d7244e5 100644 --- a/tools/perf/util/parse-events-test.c +++ b/tools/perf/util/parse-events-test.c @@ -569,7 +569,7 @@ static int test__group2(struct perf_evlist *evlist) return 0; } -static int test__group3(struct perf_evlist *evlist __used) +static int test__group3(struct perf_evlist *evlist __maybe_unused) { struct perf_evsel *evsel, *leader; @@ -648,7 +648,7 @@ static int test__group3(struct perf_evlist *evlist __used) return 0; } -static int test__group4(struct perf_evlist *evlist __used) +static int test__group4(struct perf_evlist *evlist __maybe_unused) { struct perf_evsel *evsel, *leader; @@ -684,7 +684,7 @@ static int test__group4(struct perf_evlist *evlist __used) return 0; } -static int test__group5(struct perf_evlist *evlist __used) +static int test__group5(struct perf_evlist *evlist __maybe_unused) { struct perf_evsel *evsel, *leader; diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index a031ee1..44afcf4 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -807,7 +807,8 @@ int parse_events_terms(struct list_head *terms, const char *str) return ret; } -int parse_events(struct perf_evlist *evlist, const char *str, int unset __used) +int parse_events(struct perf_evlist *evlist, const char *str, + int unset __maybe_unused) { struct parse_events_data__events data = { .list = LIST_HEAD_INIT(data.list), @@ -833,14 +834,14 @@ int parse_events(struct perf_evlist *evlist, const char *str, int unset __used) } int parse_events_option(const struct option *opt, const char *str, - int unset __used) + int unset __maybe_unused) { struct perf_evlist *evlist = *(struct perf_evlist **)opt->value; return parse_events(evlist, str, unset); } int parse_filter(const struct option *opt, const char *str, - int unset __used) + int unset __maybe_unused) { struct perf_evlist *evlist = *(struct perf_evlist **)opt->value; struct perf_evsel *last = NULL; diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l index f5e28dc..c87efc1 100644 --- a/tools/perf/util/parse-events.l +++ b/tools/perf/util/parse-events.l @@ -207,7 +207,7 @@ r{num_raw_hex} { return raw(yyscanner); } %% -int parse_events_wrap(void *scanner __used) +int parse_events_wrap(void *scanner __maybe_unused) { return 1; } diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y index 42d9a17..cd88209 100644 --- a/tools/perf/util/parse-events.y +++ b/tools/perf/util/parse-events.y @@ -391,7 +391,7 @@ sep_slash_dc: '/' | ':' | %% -void parse_events_error(void *data __used, void *scanner __used, - char const *msg __used) +void parse_events_error(void *data __maybe_unused, void *scanner __maybe_unused, + char const *msg __maybe_unused) { } diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c index 594f8fa..443fc11 100644 --- a/tools/perf/util/parse-options.c +++ b/tools/perf/util/parse-options.c @@ -557,7 +557,8 @@ int parse_options_usage(const char * const *usagestr, } -int parse_opt_verbosity_cb(const struct option *opt, const char *arg __used, +int parse_opt_verbosity_cb(const struct option *opt, + const char *arg __maybe_unused, int unset) { int *target = opt->value; diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h index 9bd6c4e..316dbe7 100644 --- a/tools/perf/util/perf_regs.h +++ b/tools/perf/util/perf_regs.h @@ -6,7 +6,7 @@ #else #define PERF_REGS_MASK 0 -static inline const char *perf_reg_name(int id __used) +static inline const char *perf_reg_name(int id __maybe_unused) { return NULL; } diff --git a/tools/perf/util/pmu.y b/tools/perf/util/pmu.y index 20ea77e..ec89804 100644 --- a/tools/perf/util/pmu.y +++ b/tools/perf/util/pmu.y @@ -86,8 +86,8 @@ PP_VALUE %% -void perf_pmu_error(struct list_head *list __used, - char *name __used, - char const *msg __used) +void perf_pmu_error(struct list_head *list __maybe_unused, + char *name __maybe_unused, + char const *msg __maybe_unused) { } diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index e8c72de..4ce04c2 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -41,7 +41,7 @@ #include "symbol.h" #include "thread.h" #include "debugfs.h" -#include "trace-event.h" /* For __unused */ +#include "trace-event.h" /* For __maybe_unused */ #include "probe-event.h" #include "probe-finder.h" #include "session.h" @@ -647,8 +647,8 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp, } static int try_to_find_probe_trace_events(struct perf_probe_event *pev, - struct probe_trace_event **tevs __unused, - int max_tevs __unused, const char *target) + struct probe_trace_event **tevs __maybe_unused, + int max_tevs __maybe_unused, const char *target) { if (perf_probe_event_need_dwarf(pev)) { pr_warning("Debuginfo-analysis is not supported.\n"); @@ -661,17 +661,18 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev, return 0; } -int show_line_range(struct line_range *lr __unused, const char *module __unused) +int show_line_range(struct line_range *lr __maybe_unused, + const char *module __maybe_unused) { pr_warning("Debuginfo-analysis is not supported.\n"); return -ENOSYS; } -int show_available_vars(struct perf_probe_event *pevs __unused, - int npevs __unused, int max_vls __unused, - const char *module __unused, - struct strfilter *filter __unused, - bool externs __unused) +int show_available_vars(struct perf_probe_event *pevs __maybe_unused, + int npevs __maybe_unused, int max_vls __maybe_unused, + const char *module __maybe_unused, + struct strfilter *filter __maybe_unused, + bool externs __maybe_unused) { pr_warning("Debuginfo-analysis is not supported.\n"); return -ENOSYS; @@ -2183,7 +2184,7 @@ static struct strfilter *available_func_filter; * If a symbol corresponds to a function with global binding and * matches filter return 0. For all others return 1. */ -static int filter_available_functions(struct map *map __unused, +static int filter_available_functions(struct map *map __maybe_unused, struct symbol *sym) { if (sym->binding == STB_GLOBAL && diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index d448984..526ba56 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -207,7 +207,7 @@ static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self, #else /* With older elfutils, this just support kernel module... */ static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self, - Dwarf_Addr addr __used) + Dwarf_Addr addr __maybe_unused) { const char *path = kernel_get_module_path("kernel"); @@ -1419,7 +1419,7 @@ static int line_range_add_line(const char *src, unsigned int lineno, } static int line_range_walk_cb(const char *fname, int lineno, - Dwarf_Addr addr __used, + Dwarf_Addr addr __maybe_unused, void *data) { struct line_finder *lf = data; diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index 27187f0..ca85444 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -672,7 +672,7 @@ struct pyrf_evlist { }; static int pyrf_evlist__init(struct pyrf_evlist *pevlist, - PyObject *args, PyObject *kwargs __used) + PyObject *args, PyObject *kwargs __maybe_unused) { PyObject *pcpus = NULL, *pthreads = NULL; struct cpu_map *cpus; @@ -733,7 +733,8 @@ static PyObject *pyrf_evlist__poll(struct pyrf_evlist *pevlist, } static PyObject *pyrf_evlist__get_pollfd(struct pyrf_evlist *pevlist, - PyObject *args __used, PyObject *kwargs __used) + PyObject *args __maybe_unused, + PyObject *kwargs __maybe_unused) { struct perf_evlist *evlist = &pevlist->evlist; PyObject *list = PyList_New(0); @@ -765,7 +766,8 @@ free_list: static PyObject *pyrf_evlist__add(struct pyrf_evlist *pevlist, - PyObject *args, PyObject *kwargs __used) + PyObject *args, + PyObject *kwargs __maybe_unused) { struct perf_evlist *evlist = &pevlist->evlist; PyObject *pevsel; diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c index 94e6736..ffde3e4 100644 --- a/tools/perf/util/scripting-engines/trace-event-perl.c +++ b/tools/perf/util/scripting-engines/trace-event-perl.c @@ -257,10 +257,10 @@ static inline struct event_format *find_cache_event(struct perf_evsel *evsel) return event; } -static void perl_process_tracepoint(union perf_event *perf_event __unused, +static void perl_process_tracepoint(union perf_event *perf_event __maybe_unused, struct perf_sample *sample, struct perf_evsel *evsel, - struct machine *machine __unused, + struct machine *machine __maybe_unused, struct addr_location *al) { struct format_field *field; @@ -349,8 +349,8 @@ static void perl_process_tracepoint(union perf_event *perf_event __unused, static void perl_process_event_generic(union perf_event *event, struct perf_sample *sample, struct perf_evsel *evsel, - struct machine *machine __unused, - struct addr_location *al __unused) + struct machine *machine __maybe_unused, + struct addr_location *al __maybe_unused) { dSP; diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index afba097..730c663 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -221,10 +221,11 @@ static inline struct event_format *find_cache_event(struct perf_evsel *evsel) return event; } -static void python_process_tracepoint(union perf_event *perf_event __unused, +static void python_process_tracepoint(union perf_event *perf_event + __maybe_unused, struct perf_sample *sample, struct perf_evsel *evsel, - struct machine *machine __unused, + struct machine *machine __maybe_unused, struct addr_location *al) { PyObject *handler, *retval, *context, *t, *obj, *dict = NULL; @@ -339,10 +340,11 @@ static void python_process_tracepoint(union perf_event *perf_event __unused, Py_DECREF(t); } -static void python_process_general_event(union perf_event *perf_event __unused, +static void python_process_general_event(union perf_event *perf_event + __maybe_unused, struct perf_sample *sample, struct perf_evsel *evsel, - struct machine *machine __unused, + struct machine *machine __maybe_unused, struct addr_location *al) { PyObject *handler, *retval, *t, *dict; diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 9453758..3049b0a 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -17,6 +17,7 @@ #include "event-parse.h" #include "perf_regs.h" #include "unwind.h" +#include "vdso.h" static int perf_session__open(struct perf_session *self, bool force) { @@ -211,6 +212,7 @@ void perf_session__delete(struct perf_session *self) machine__exit(&self->host_machine); close(self->fd); free(self); + vdso__exit(); } void machine__remove_thread(struct machine *self, struct thread *th) @@ -388,55 +390,64 @@ int machine__resolve_callchain(struct machine *machine, (evsel->attr.sample_type & PERF_SAMPLE_STACK_USER))) return 0; + /* Bail out if nothing was captured. */ + if ((!sample->user_regs.regs) || + (!sample->user_stack.size)) + return 0; + return unwind__get_entries(unwind_entry, &callchain_cursor, machine, thread, evsel->attr.sample_regs_user, sample); } -static int process_event_synth_tracing_data_stub(union perf_event *event __used, - struct perf_session *session __used) +static int process_event_synth_tracing_data_stub(union perf_event *event + __maybe_unused, + struct perf_session *session + __maybe_unused) { dump_printf(": unhandled!\n"); return 0; } -static int process_event_synth_attr_stub(union perf_event *event __used, - struct perf_evlist **pevlist __used) +static int process_event_synth_attr_stub(union perf_event *event __maybe_unused, + struct perf_evlist **pevlist + __maybe_unused) { dump_printf(": unhandled!\n"); return 0; } -static int process_event_sample_stub(struct perf_tool *tool __used, - union perf_event *event __used, - struct perf_sample *sample __used, - struct perf_evsel *evsel __used, - struct machine *machine __used) +static int process_event_sample_stub(struct perf_tool *tool __maybe_unused, + union perf_event *event __maybe_unused, + struct perf_sample *sample __maybe_unused, + struct perf_evsel *evsel __maybe_unused, + struct machine *machine __maybe_unused) { dump_printf(": unhandled!\n"); return 0; } -static int process_event_stub(struct perf_tool *tool __used, - union perf_event *event __used, - struct perf_sample *sample __used, - struct machine *machine __used) +static int process_event_stub(struct perf_tool *tool __maybe_unused, + union perf_event *event __maybe_unused, + struct perf_sample *sample __maybe_unused, + struct machine *machine __maybe_unused) { dump_printf(": unhandled!\n"); return 0; } -static int process_finished_round_stub(struct perf_tool *tool __used, - union perf_event *event __used, - struct perf_session *perf_session __used) +static int process_finished_round_stub(struct perf_tool *tool __maybe_unused, + union perf_event *event __maybe_unused, + struct perf_session *perf_session + __maybe_unused) { dump_printf(": unhandled!\n"); return 0; } -static int process_event_type_stub(struct perf_tool *tool __used, - union perf_event *event __used) +static int process_event_type_stub(struct perf_tool *tool __maybe_unused, + union perf_event *event __maybe_unused) { dump_printf(": unhandled!\n"); return 0; @@ -513,7 +524,7 @@ static void swap_sample_id_all(union perf_event *event, void *data) } static void perf_event__all64_swap(union perf_event *event, - bool sample_id_all __used) + bool sample_id_all __maybe_unused) { struct perf_event_header *hdr = &event->header; mem_bswap_64(hdr + 1, event->header.size - sizeof(*hdr)); @@ -527,7 +538,7 @@ static void perf_event__comm_swap(union perf_event *event, bool sample_id_all) if (sample_id_all) { void *data = &event->comm.comm; - data += ALIGN(strlen(data) + 1, sizeof(u64)); + data += PERF_ALIGN(strlen(data) + 1, sizeof(u64)); swap_sample_id_all(event, data); } } @@ -544,7 +555,7 @@ static void perf_event__mmap_swap(union perf_event *event, if (sample_id_all) { void *data = &event->mmap.filename; - data += ALIGN(strlen(data) + 1, sizeof(u64)); + data += PERF_ALIGN(strlen(data) + 1, sizeof(u64)); swap_sample_id_all(event, data); } } @@ -624,7 +635,7 @@ void perf_event__attr_swap(struct perf_event_attr *attr) } static void perf_event__hdr_attr_swap(union perf_event *event, - bool sample_id_all __used) + bool sample_id_all __maybe_unused) { size_t size; @@ -636,14 +647,14 @@ static void perf_event__hdr_attr_swap(union perf_event *event, } static void perf_event__event_type_swap(union perf_event *event, - bool sample_id_all __used) + bool sample_id_all __maybe_unused) { event->event_type.event_type.event_id = bswap_64(event->event_type.event_type.event_id); } static void perf_event__tracing_data_swap(union perf_event *event, - bool sample_id_all __used) + bool sample_id_all __maybe_unused) { event->tracing_data.size = bswap_32(event->tracing_data.size); } @@ -784,7 +795,7 @@ static int flush_sample_queue(struct perf_session *s, * etc... */ static int process_finished_round(struct perf_tool *tool, - union perf_event *event __used, + union perf_event *event __maybe_unused, struct perf_session *session) { int ret = flush_sample_queue(session, tool); diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 7a2fbd8..0981bc7 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -170,7 +170,7 @@ static int hist_entry__dso_snprintf(struct hist_entry *self, char *bf, static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym, u64 ip, char level, char *bf, size_t size, - unsigned int width __used) + unsigned int width __maybe_unused) { size_t ret = 0; @@ -205,7 +205,8 @@ struct sort_entry sort_dso = { }; static int hist_entry__sym_snprintf(struct hist_entry *self, char *bf, - size_t size, unsigned int width __used) + size_t size, + unsigned int width __maybe_unused) { return _hist_entry__sym_snprintf(self->ms.map, self->ms.sym, self->ip, self->level, bf, size, width); @@ -248,7 +249,8 @@ sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right) } static int hist_entry__srcline_snprintf(struct hist_entry *self, char *bf, - size_t size, unsigned int width __used) + size_t size, + unsigned int width __maybe_unused) { FILE *fp; char cmd[PATH_MAX + 2], *path = self->srcline, *nl; @@ -397,7 +399,8 @@ sort__sym_to_cmp(struct hist_entry *left, struct hist_entry *right) } static int hist_entry__sym_from_snprintf(struct hist_entry *self, char *bf, - size_t size, unsigned int width __used) + size_t size, + unsigned int width __maybe_unused) { struct addr_map_symbol *from = &self->branch_info->from; return _hist_entry__sym_snprintf(from->map, from->sym, from->addr, @@ -406,7 +409,8 @@ static int hist_entry__sym_from_snprintf(struct hist_entry *self, char *bf, } static int hist_entry__sym_to_snprintf(struct hist_entry *self, char *bf, - size_t size, unsigned int width __used) + size_t size, + unsigned int width __maybe_unused) { struct addr_map_symbol *to = &self->branch_info->to; return _hist_entry__sym_snprintf(to->map, to->sym, to->addr, diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c index 199bc4d..3217059 100644 --- a/tools/perf/util/string.c +++ b/tools/perf/util/string.c @@ -1,5 +1,5 @@ #include "util.h" -#include "string.h" +#include "linux/string.h" #define K 1024LL /* @@ -335,3 +335,19 @@ char *rtrim(char *s) return s; } + +/** + * memdup - duplicate region of memory + * @src: memory region to duplicate + * @len: memory region length + */ +void *memdup(const void *src, size_t len) +{ + void *p; + + p = malloc(len); + if (p) + memcpy(p, src, len); + + return p; +} diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c index 6738ea1..259f8f2 100644 --- a/tools/perf/util/symbol-minimal.c +++ b/tools/perf/util/symbol-minimal.c @@ -69,8 +69,9 @@ static int read_build_id(void *note_data, size_t note_len, void *bf, return -1; } -int filename__read_debuglink(const char *filename __used, - char *debuglink __used, size_t size __used) +int filename__read_debuglink(const char *filename __maybe_unused, + char *debuglink __maybe_unused, + size_t size __maybe_unused) { return -1; } @@ -241,7 +242,8 @@ out: return ret; } -int symsrc__init(struct symsrc *ss, struct dso *dso __used, const char *name, +int symsrc__init(struct symsrc *ss, struct dso *dso __maybe_unused, + const char *name, enum dso_binary_type type) { int fd = open(name, O_RDONLY); @@ -260,13 +262,13 @@ out_close: return -1; } -bool symsrc__possibly_runtime(struct symsrc *ss __used) +bool symsrc__possibly_runtime(struct symsrc *ss __maybe_unused) { /* Assume all sym sources could be a runtime image. */ return true; } -bool symsrc__has_symtab(struct symsrc *ss __used) +bool symsrc__has_symtab(struct symsrc *ss __maybe_unused) { return false; } @@ -277,17 +279,19 @@ void symsrc__destroy(struct symsrc *ss) close(ss->fd); } -int dso__synthesize_plt_symbols(struct dso *dso __used, - struct symsrc *ss __used, - struct map *map __used, - symbol_filter_t filter __used) +int dso__synthesize_plt_symbols(struct dso *dso __maybe_unused, + struct symsrc *ss __maybe_unused, + struct map *map __maybe_unused, + symbol_filter_t filter __maybe_unused) { return 0; } -int dso__load_sym(struct dso *dso, struct map *map __used, struct symsrc *ss, - struct symsrc *runtime_ss __used, - symbol_filter_t filter __used, int kmodule __used) +int dso__load_sym(struct dso *dso, struct map *map __maybe_unused, + struct symsrc *ss, + struct symsrc *runtime_ss __maybe_unused, + symbol_filter_t filter __maybe_unused, + int kmodule __maybe_unused) { unsigned char *build_id[BUILD_ID_SIZE]; diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 753699a..e2e8c69 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1596,7 +1596,7 @@ void dsos__add(struct list_head *head, struct dso *dso) list_add_tail(&dso->node, head); } -static struct dso *dsos__find(struct list_head *head, const char *name) +struct dso *dsos__find(struct list_head *head, const char *name) { struct dso *pos; @@ -1755,7 +1755,7 @@ struct process_args { }; static int symbol__in_kernel(void *arg, const char *name, - char type __used, u64 start) + char type __maybe_unused, u64 start) { struct process_args *args = arg; @@ -1991,7 +1991,7 @@ int symbol__init(void) if (symbol_conf.initialized) return 0; - symbol_conf.priv_size = ALIGN(symbol_conf.priv_size, sizeof(u64)); + symbol_conf.priv_size = PERF_ALIGN(symbol_conf.priv_size, sizeof(u64)); symbol__elf_init(); diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 41a15da..4ff45e3 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -21,14 +21,15 @@ #ifdef HAVE_CPLUS_DEMANGLE extern char *cplus_demangle(const char *, int); -static inline char *bfd_demangle(void __used *v, const char *c, int i) +static inline char *bfd_demangle(void __maybe_unused *v, const char *c, int i) { return cplus_demangle(c, i); } #else #ifdef NO_DEMANGLE -static inline char *bfd_demangle(void __used *v, const char __used *c, - int __used i) +static inline char *bfd_demangle(void __maybe_unused *v, + const char __maybe_unused *c, + int __maybe_unused i) { return NULL; } @@ -294,6 +295,7 @@ static inline void dso__set_loaded(struct dso *dso, enum map_type type) void dso__sort_by_name(struct dso *dso, enum map_type type); void dsos__add(struct list_head *head, struct dso *dso); +struct dso *dsos__find(struct list_head *head, const char *name); struct dso *__dsos__findnew(struct list_head *head, const char *name); int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter); diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c index a5a554e..aa4c860 100644 --- a/tools/perf/util/trace-event-parse.c +++ b/tools/perf/util/trace-event-parse.c @@ -221,7 +221,7 @@ void print_event(struct pevent *pevent, int cpu, void *data, int size, } void parse_proc_kallsyms(struct pevent *pevent, - char *file, unsigned int size __unused) + char *file, unsigned int size __maybe_unused) { unsigned long long addr; char *func; @@ -253,7 +253,7 @@ void parse_proc_kallsyms(struct pevent *pevent, } void parse_ftrace_printk(struct pevent *pevent, - char *file, unsigned int size __unused) + char *file, unsigned int size __maybe_unused) { unsigned long long addr; char *printk; diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c index 302ff26..8715a10 100644 --- a/tools/perf/util/trace-event-scripting.c +++ b/tools/perf/util/trace-event-scripting.c @@ -35,11 +35,11 @@ static int stop_script_unsupported(void) return 0; } -static void process_event_unsupported(union perf_event *event __unused, - struct perf_sample *sample __unused, - struct perf_evsel *evsel __unused, - struct machine *machine __unused, - struct addr_location *al __unused) +static void process_event_unsupported(union perf_event *event __maybe_unused, + struct perf_sample *sample __maybe_unused, + struct perf_evsel *evsel __maybe_unused, + struct machine *machine __maybe_unused, + struct addr_location *al __maybe_unused) { } @@ -52,17 +52,19 @@ static void print_python_unsupported_msg(void) "\n etc.\n"); } -static int python_start_script_unsupported(const char *script __unused, - int argc __unused, - const char **argv __unused) +static int python_start_script_unsupported(const char *script __maybe_unused, + int argc __maybe_unused, + const char **argv __maybe_unused) { print_python_unsupported_msg(); return -1; } -static int python_generate_script_unsupported(struct pevent *pevent __unused, - const char *outfile __unused) +static int python_generate_script_unsupported(struct pevent *pevent + __maybe_unused, + const char *outfile + __maybe_unused) { print_python_unsupported_msg(); @@ -114,17 +116,18 @@ static void print_perl_unsupported_msg(void) "\n etc.\n"); } -static int perl_start_script_unsupported(const char *script __unused, - int argc __unused, - const char **argv __unused) +static int perl_start_script_unsupported(const char *script __maybe_unused, + int argc __maybe_unused, + const char **argv __maybe_unused) { print_perl_unsupported_msg(); return -1; } -static int perl_generate_script_unsupported(struct pevent *pevent __unused, - const char *outfile __unused) +static int perl_generate_script_unsupported(struct pevent *pevent + __maybe_unused, + const char *outfile __maybe_unused) { print_perl_unsupported_msg(); diff --git a/tools/perf/util/unwind.c b/tools/perf/util/unwind.c index 00a42aa..958723b 100644 --- a/tools/perf/util/unwind.c +++ b/tools/perf/util/unwind.c @@ -307,32 +307,36 @@ find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, need_unwind_info, arg); } -static int access_fpreg(unw_addr_space_t __used as, unw_regnum_t __used num, - unw_fpreg_t __used *val, int __used __write, - void __used *arg) +static int access_fpreg(unw_addr_space_t __maybe_unused as, + unw_regnum_t __maybe_unused num, + unw_fpreg_t __maybe_unused *val, + int __maybe_unused __write, + void __maybe_unused *arg) { pr_err("unwind: access_fpreg unsupported\n"); return -UNW_EINVAL; } -static int get_dyn_info_list_addr(unw_addr_space_t __used as, - unw_word_t __used *dil_addr, - void __used *arg) +static int get_dyn_info_list_addr(unw_addr_space_t __maybe_unused as, + unw_word_t __maybe_unused *dil_addr, + void __maybe_unused *arg) { return -UNW_ENOINFO; } -static int resume(unw_addr_space_t __used as, unw_cursor_t __used *cu, - void __used *arg) +static int resume(unw_addr_space_t __maybe_unused as, + unw_cursor_t __maybe_unused *cu, + void __maybe_unused *arg) { pr_err("unwind: resume unsupported\n"); return -UNW_EINVAL; } static int -get_proc_name(unw_addr_space_t __used as, unw_word_t __used addr, - char __used *bufp, size_t __used buf_len, - unw_word_t __used *offp, void __used *arg) +get_proc_name(unw_addr_space_t __maybe_unused as, + unw_word_t __maybe_unused addr, + char __maybe_unused *bufp, size_t __maybe_unused buf_len, + unw_word_t __maybe_unused *offp, void __maybe_unused *arg) { pr_err("unwind: get_proc_name unsupported\n"); return -UNW_EINVAL; @@ -377,7 +381,7 @@ static int reg_value(unw_word_t *valp, struct regs_dump *regs, int id, return 0; } -static int access_mem(unw_addr_space_t __used as, +static int access_mem(unw_addr_space_t __maybe_unused as, unw_word_t addr, unw_word_t *valp, int __write, void *arg) { @@ -422,7 +426,7 @@ static int access_mem(unw_addr_space_t __used as, return 0; } -static int access_reg(unw_addr_space_t __used as, +static int access_reg(unw_addr_space_t __maybe_unused as, unw_regnum_t regnum, unw_word_t *valp, int __write, void *arg) { @@ -454,9 +458,9 @@ static int access_reg(unw_addr_space_t __used as, return 0; } -static void put_unwind_info(unw_addr_space_t __used as, - unw_proc_info_t *pi __used, - void *arg __used) +static void put_unwind_info(unw_addr_space_t __maybe_unused as, + unw_proc_info_t *pi __maybe_unused, + void *arg __maybe_unused) { pr_debug("unwind: put_unwind_info called\n"); } diff --git a/tools/perf/util/unwind.h b/tools/perf/util/unwind.h index 919bd6a..a78c8b3 100644 --- a/tools/perf/util/unwind.h +++ b/tools/perf/util/unwind.h @@ -22,11 +22,12 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg, int unwind__arch_reg_id(int regnum); #else static inline int -unwind__get_entries(unwind_entry_cb_t cb __used, void *arg __used, - struct machine *machine __used, - struct thread *thread __used, - u64 sample_uregs __used, - struct perf_sample *data __used) +unwind__get_entries(unwind_entry_cb_t cb __maybe_unused, + void *arg __maybe_unused, + struct machine *machine __maybe_unused, + struct thread *thread __maybe_unused, + u64 sample_uregs __maybe_unused, + struct perf_sample *data __maybe_unused) { return 0; } diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index 67a3713..70fa70b 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h @@ -70,7 +70,7 @@ #include <sys/socket.h> #include <sys/ioctl.h> #include <inttypes.h> -#include "../../../include/linux/magic.h" +#include <linux/magic.h> #include "types.h" #include <sys/ttydefaults.h> diff --git a/tools/perf/util/vdso.c b/tools/perf/util/vdso.c new file mode 100644 index 0000000..e60951f --- /dev/null +++ b/tools/perf/util/vdso.c @@ -0,0 +1,111 @@ + +#include <unistd.h> +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdlib.h> +#include <linux/kernel.h> + +#include "vdso.h" +#include "util.h" +#include "symbol.h" +#include "linux/string.h" + +static bool vdso_found; +static char vdso_file[] = "/tmp/perf-vdso.so-XXXXXX"; + +static int find_vdso_map(void **start, void **end) +{ + FILE *maps; + char line[128]; + int found = 0; + + maps = fopen("/proc/self/maps", "r"); + if (!maps) { + pr_err("vdso: cannot open maps\n"); + return -1; + } + + while (!found && fgets(line, sizeof(line), maps)) { + int m = -1; + + /* We care only about private r-x mappings. */ + if (2 != sscanf(line, "%p-%p r-xp %*x %*x:%*x %*u %n", + start, end, &m)) + continue; + if (m < 0) + continue; + + if (!strncmp(&line[m], VDSO__MAP_NAME, + sizeof(VDSO__MAP_NAME) - 1)) + found = 1; + } + + fclose(maps); + return !found; +} + +static char *get_file(void) +{ + char *vdso = NULL; + char *buf = NULL; + void *start, *end; + size_t size; + int fd; + + if (vdso_found) + return vdso_file; + + if (find_vdso_map(&start, &end)) + return NULL; + + size = end - start; + + buf = memdup(start, size); + if (!buf) + return NULL; + + fd = mkstemp(vdso_file); + if (fd < 0) + goto out; + + if (size == (size_t) write(fd, buf, size)) + vdso = vdso_file; + + close(fd); + + out: + free(buf); + + vdso_found = (vdso != NULL); + return vdso; +} + +void vdso__exit(void) +{ + if (vdso_found) + unlink(vdso_file); +} + +struct dso *vdso__dso_findnew(struct list_head *head) +{ + struct dso *dso = dsos__find(head, VDSO__MAP_NAME); + + if (!dso) { + char *file; + + file = get_file(); + if (!file) + return NULL; + + dso = dso__new(VDSO__MAP_NAME); + if (dso != NULL) { + dsos__add(head, dso); + dso__set_long_name(dso, file); + } + } + + return dso; +} diff --git a/tools/perf/util/vdso.h b/tools/perf/util/vdso.h new file mode 100644 index 0000000..0f76e7c --- /dev/null +++ b/tools/perf/util/vdso.h @@ -0,0 +1,18 @@ +#ifndef __PERF_VDSO__ +#define __PERF_VDSO__ + +#include <linux/types.h> +#include <string.h> +#include <stdbool.h> + +#define VDSO__MAP_NAME "[vdso]" + +static inline bool is_vdso_map(const char *filename) +{ + return !strcmp(filename, VDSO__MAP_NAME); +} + +struct dso *vdso__dso_findnew(struct list_head *head); +void vdso__exit(void); + +#endif /* __PERF_VDSO__ */ diff --git a/tools/perf/util/wrapper.c b/tools/perf/util/wrapper.c index 73e900e..19f15b6 100644 --- a/tools/perf/util/wrapper.c +++ b/tools/perf/util/wrapper.c @@ -7,7 +7,8 @@ * There's no pack memory to release - but stay close to the Git * version so wrap this away: */ -static inline void release_pack_memory(size_t size __used, int flag __used) +static inline void release_pack_memory(size_t size __maybe_unused, + int flag __maybe_unused) { } |