diff options
Diffstat (limited to 'tools/perf/builtin-lock.c')
-rw-r--r-- | tools/perf/builtin-lock.c | 137 |
1 files changed, 61 insertions, 76 deletions
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c index c852c7a..ee33ba2 100644 --- a/tools/perf/builtin-lock.c +++ b/tools/perf/builtin-lock.c @@ -15,7 +15,6 @@ #include "util/debug.h" #include "util/session.h" #include "util/tool.h" -#include "util/data.h" #include <sys/types.h> #include <sys/prctl.h> @@ -57,9 +56,7 @@ struct lock_stat { unsigned int nr_readlock; unsigned int nr_trylock; - /* these times are in nano sec. */ - u64 avg_wait_time; u64 wait_time_total; u64 wait_time_min; u64 wait_time_max; @@ -211,7 +208,6 @@ static struct thread_stat *thread_stat_findnew_first(u32 tid) SINGLE_KEY(nr_acquired) SINGLE_KEY(nr_contended) -SINGLE_KEY(avg_wait_time) SINGLE_KEY(wait_time_total) SINGLE_KEY(wait_time_max) @@ -248,7 +244,6 @@ static struct rb_root result; /* place to store sorted data */ struct lock_key keys[] = { DEF_KEY_LOCK(acquired, nr_acquired), DEF_KEY_LOCK(contended, nr_contended), - DEF_KEY_LOCK(avg_wait, avg_wait_time), DEF_KEY_LOCK(wait_total, wait_time_total), DEF_KEY_LOCK(wait_min, wait_time_min), DEF_KEY_LOCK(wait_max, wait_time_max), @@ -326,12 +321,10 @@ static struct lock_stat *lock_stat_findnew(void *addr, const char *name) new->addr = addr; new->name = zalloc(sizeof(char) * strlen(name) + 1); - if (!new->name) { - free(new); + if (!new->name) goto alloc_failed; - } - strcpy(new->name, name); + new->wait_time_min = ULLONG_MAX; list_add(&new->hash_entry, entry); @@ -407,17 +400,17 @@ static int report_lock_acquire_event(struct perf_evsel *evsel, ls = lock_stat_findnew(addr, name); if (!ls) - return -ENOMEM; + return -1; if (ls->discard) return 0; ts = thread_stat_findnew(sample->tid); if (!ts) - return -ENOMEM; + return -1; seq = get_seq(ts, addr); if (!seq) - return -ENOMEM; + return -1; switch (seq->state) { case SEQ_STATE_UNINITIALIZED: @@ -453,6 +446,7 @@ broken: list_del(&seq->list); free(seq); goto end; + break; default: BUG_ON("Unknown state of lock sequence found!\n"); break; @@ -479,17 +473,17 @@ static int report_lock_acquired_event(struct perf_evsel *evsel, ls = lock_stat_findnew(addr, name); if (!ls) - return -ENOMEM; + return -1; if (ls->discard) return 0; ts = thread_stat_findnew(sample->tid); if (!ts) - return -ENOMEM; + return -1; seq = get_seq(ts, addr); if (!seq) - return -ENOMEM; + return -1; switch (seq->state) { case SEQ_STATE_UNINITIALIZED: @@ -514,6 +508,8 @@ static int report_lock_acquired_event(struct perf_evsel *evsel, list_del(&seq->list); free(seq); goto end; + break; + default: BUG_ON("Unknown state of lock sequence found!\n"); break; @@ -521,7 +517,6 @@ static int report_lock_acquired_event(struct perf_evsel *evsel, seq->state = SEQ_STATE_ACQUIRED; ls->nr_acquired++; - ls->avg_wait_time = ls->nr_contended ? ls->wait_time_total/ls->nr_contended : 0; seq->prev_event_time = sample->time; end: return 0; @@ -541,17 +536,17 @@ static int report_lock_contended_event(struct perf_evsel *evsel, ls = lock_stat_findnew(addr, name); if (!ls) - return -ENOMEM; + return -1; if (ls->discard) return 0; ts = thread_stat_findnew(sample->tid); if (!ts) - return -ENOMEM; + return -1; seq = get_seq(ts, addr); if (!seq) - return -ENOMEM; + return -1; switch (seq->state) { case SEQ_STATE_UNINITIALIZED: @@ -569,6 +564,7 @@ static int report_lock_contended_event(struct perf_evsel *evsel, list_del(&seq->list); free(seq); goto end; + break; default: BUG_ON("Unknown state of lock sequence found!\n"); break; @@ -576,7 +572,6 @@ static int report_lock_contended_event(struct perf_evsel *evsel, seq->state = SEQ_STATE_CONTENDED; ls->nr_contended++; - ls->avg_wait_time = ls->wait_time_total/ls->nr_contended; seq->prev_event_time = sample->time; end: return 0; @@ -596,21 +591,22 @@ static int report_lock_release_event(struct perf_evsel *evsel, ls = lock_stat_findnew(addr, name); if (!ls) - return -ENOMEM; + return -1; if (ls->discard) return 0; ts = thread_stat_findnew(sample->tid); if (!ts) - return -ENOMEM; + return -1; seq = get_seq(ts, addr); if (!seq) - return -ENOMEM; + return -1; switch (seq->state) { case SEQ_STATE_UNINITIALIZED: goto end; + break; case SEQ_STATE_ACQUIRED: break; case SEQ_STATE_READ_ACQUIRED: @@ -628,6 +624,7 @@ static int report_lock_release_event(struct perf_evsel *evsel, ls->discard = 1; bad_hist[BROKEN_RELEASE]++; goto free_seq; + break; default: BUG_ON("Unknown state of lock sequence found!\n"); break; @@ -693,7 +690,7 @@ static void print_bad_events(int bad, int total) pr_info("\n=== output for debug===\n\n"); pr_info("bad: %d, total: %d\n", bad, total); - pr_info("bad rate: %.2f %%\n", (double)bad / (double)total * 100); + pr_info("bad rate: %f %%\n", (double)bad / (double)total * 100); pr_info("histogram of events caused bad sequence\n"); for (i = 0; i < BROKEN_MAX; i++) pr_info(" %10s: %d\n", name[i], bad_hist[i]); @@ -710,7 +707,6 @@ static void print_result(void) pr_info("%10s ", "acquired"); pr_info("%10s ", "contended"); - pr_info("%15s ", "avg wait (ns)"); pr_info("%15s ", "total wait (ns)"); pr_info("%15s ", "max wait (ns)"); pr_info("%15s ", "min wait (ns)"); @@ -742,7 +738,6 @@ static void print_result(void) pr_info("%10u ", st->nr_acquired); pr_info("%10u ", st->nr_contended); - pr_info("%15" PRIu64 " ", st->avg_wait_time); pr_info("%15" PRIu64 " ", st->wait_time_total); pr_info("%15" PRIu64 " ", st->wait_time_max); pr_info("%15" PRIu64 " ", st->wait_time_min == ULLONG_MAX ? @@ -767,7 +762,7 @@ static void dump_threads(void) while (node) { st = container_of(node, struct thread_stat, rb); t = perf_session__findnew(session, st->tid); - pr_info("%10d: %s\n", st->tid, thread__comm_str(t)); + pr_info("%10d: %s\n", st->tid, t->comm); node = rb_next(node); }; } @@ -819,26 +814,14 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused, return -1; } - if (evsel->handler != NULL) { - tracepoint_handler f = evsel->handler; + if (evsel->handler.func != NULL) { + tracepoint_handler f = evsel->handler.func; return f(evsel, sample); } return 0; } -static void sort_result(void) -{ - unsigned int i; - struct lock_stat *st; - - for (i = 0; i < LOCKHASH_SIZE; i++) { - list_for_each_entry(st, &lockhash_table[i], hash_entry) { - insert_to_result(st, compare); - } - } -} - static const struct perf_evsel_str_handler lock_tracepoints[] = { { "lock:lock_acquire", perf_evsel__process_lock_acquire, }, /* CONFIG_LOCKDEP */ { "lock:lock_acquired", perf_evsel__process_lock_acquired, }, /* CONFIG_LOCKDEP, CONFIG_LOCK_STAT */ @@ -846,51 +829,51 @@ static const struct perf_evsel_str_handler lock_tracepoints[] = { { "lock:lock_release", perf_evsel__process_lock_release, }, /* CONFIG_LOCKDEP */ }; -static int __cmd_report(bool display_info) +static int read_events(void) { - int err = -EINVAL; struct perf_tool eops = { .sample = process_sample_event, .comm = perf_event__process_comm, .ordered_samples = true, }; - struct perf_data_file file = { - .path = input_name, - .mode = PERF_DATA_MODE_READ, - }; - - session = perf_session__new(&file, false, &eops); + session = perf_session__new(input_name, O_RDONLY, 0, false, &eops); if (!session) { pr_err("Initializing perf session failed\n"); - return -ENOMEM; + return -1; } - if (!perf_session__has_traces(session, "lock record")) - goto out_delete; - if (perf_session__set_tracepoints_handlers(session, lock_tracepoints)) { pr_err("Initializing perf session tracepoint handlers failed\n"); - goto out_delete; + return -1; } - if (select_key()) - goto out_delete; + return perf_session__process_events(session, &eops); +} + +static void sort_result(void) +{ + unsigned int i; + struct lock_stat *st; - err = perf_session__process_events(session, &eops); - if (err) - goto out_delete; + for (i = 0; i < LOCKHASH_SIZE; i++) { + list_for_each_entry(st, &lockhash_table[i], hash_entry) { + insert_to_result(st, compare); + } + } +} +static int __cmd_report(void) +{ setup_pager(); - if (display_info) /* used for info subcommand */ - err = dump_info(); - else { - sort_result(); - print_result(); - } -out_delete: - perf_session__delete(session); - return err; + if ((select_key() != 0) || + (read_events() != 0)) + return -1; + + sort_result(); + print_result(); + + return 0; } static int __cmd_record(int argc, const char **argv) @@ -898,7 +881,7 @@ static int __cmd_record(int argc, const char **argv) const char *record_args[] = { "record", "-R", "-m", "1024", "-c", "1", }; - unsigned int rec_argc, i, j, ret; + unsigned int rec_argc, i, j; const char **rec_argv; for (i = 0; i < ARRAY_SIZE(lock_tracepoints); i++) { @@ -915,7 +898,7 @@ static int __cmd_record(int argc, const char **argv) rec_argc += 2 * ARRAY_SIZE(lock_tracepoints); rec_argv = calloc(rec_argc + 1, sizeof(char *)); - if (!rec_argv) + if (rec_argv == NULL) return -ENOMEM; for (i = 0; i < ARRAY_SIZE(record_args); i++) @@ -931,9 +914,7 @@ static int __cmd_record(int argc, const char **argv) BUG_ON(i != rec_argc); - ret = cmd_record(i, rec_argv, NULL); - free(rec_argv); - return ret; + return cmd_record(i, rec_argv, NULL); } int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused) @@ -953,7 +934,7 @@ int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused) }; const struct option report_options[] = { OPT_STRING('k', "key", &sort_key, "acquired", - "key for sorting (acquired / contended / avg_wait / wait_total / wait_max / wait_min)"), + "key for sorting (acquired / contended / wait_total / wait_max / wait_min)"), /* TODO: type */ OPT_END() }; @@ -991,7 +972,7 @@ int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused) if (argc) usage_with_options(report_usage, report_options); } - rc = __cmd_report(false); + __cmd_report(); } else if (!strcmp(argv[0], "script")) { /* Aliased to 'perf script' */ return cmd_script(argc, argv, prefix); @@ -1004,7 +985,11 @@ int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused) } /* recycling report_lock_ops */ trace_handler = &report_lock_ops; - rc = __cmd_report(true); + setup_pager(); + if (read_events() != 0) + rc = -1; + else + rc = dump_info(); } else { usage_with_options(lock_usage, lock_options); } |