aboutsummaryrefslogtreecommitdiff
path: root/tools/perf/builtin-lock.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-lock.c')
-rw-r--r--tools/perf/builtin-lock.c142
1 files changed, 79 insertions, 63 deletions
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index 054997edd98b..70b14ba5fdd5 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -60,7 +60,7 @@ static bool show_thread_stats;
static bool show_lock_addrs;
static bool show_lock_owner;
static bool use_bpf;
-static unsigned long bpf_map_entries = 10240;
+static unsigned long bpf_map_entries = MAX_ENTRIES;
static int max_stack_depth = CONTENTION_STACK_DEPTH;
static int stack_skip = CONTENTION_STACK_SKIP;
static int print_nr_entries = INT_MAX / 2;
@@ -77,7 +77,7 @@ static enum lock_aggr_mode aggr_mode = LOCK_AGGR_ADDR;
static bool needs_callstack(void)
{
- return verbose > 0 || !list_empty(&callstack_filters);
+ return !list_empty(&callstack_filters);
}
static struct thread_stat *thread_stat_find(u32 tid)
@@ -900,7 +900,7 @@ static int get_symbol_name_offset(struct map *map, struct symbol *sym, u64 ip,
return 0;
}
- offset = map->map_ip(map, ip) - sym->start;
+ offset = map__map_ip(map, ip) - sym->start;
if (offset)
return scnprintf(buf, size, "%s+%#lx", sym->name, offset);
@@ -1070,7 +1070,7 @@ static int report_lock_contention_begin_event(struct evsel *evsel,
return -ENOMEM;
}
- addrs[filters.nr_addrs++] = kmap->unmap_ip(kmap, sym->start);
+ addrs[filters.nr_addrs++] = map__unmap_ip(kmap, sym->start);
filters.addrs = addrs;
}
}
@@ -1323,10 +1323,10 @@ static void print_bad_events(int bad, int total)
for (i = 0; i < BROKEN_MAX; i++)
broken += bad_hist[i];
- if (quiet || (broken == 0 && verbose <= 0))
+ if (quiet || total == 0 || (broken == 0 && verbose <= 0))
return;
- pr_info("\n=== output for debug===\n\n");
+ 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("histogram of events caused bad sequence\n");
@@ -1548,27 +1548,41 @@ static void sort_result(void)
static const struct {
unsigned int flags;
+ const char *str;
const char *name;
} lock_type_table[] = {
- { 0, "semaphore" },
- { LCB_F_SPIN, "spinlock" },
- { LCB_F_SPIN | LCB_F_READ, "rwlock:R" },
- { LCB_F_SPIN | LCB_F_WRITE, "rwlock:W"},
- { LCB_F_READ, "rwsem:R" },
- { LCB_F_WRITE, "rwsem:W" },
- { LCB_F_RT, "rtmutex" },
- { LCB_F_RT | LCB_F_READ, "rwlock-rt:R" },
- { LCB_F_RT | LCB_F_WRITE, "rwlock-rt:W"},
- { LCB_F_PERCPU | LCB_F_READ, "pcpu-sem:R" },
- { LCB_F_PERCPU | LCB_F_WRITE, "pcpu-sem:W" },
- { LCB_F_MUTEX, "mutex" },
- { LCB_F_MUTEX | LCB_F_SPIN, "mutex" },
+ { 0, "semaphore", "semaphore" },
+ { LCB_F_SPIN, "spinlock", "spinlock" },
+ { LCB_F_SPIN | LCB_F_READ, "rwlock:R", "rwlock" },
+ { LCB_F_SPIN | LCB_F_WRITE, "rwlock:W", "rwlock" },
+ { LCB_F_READ, "rwsem:R", "rwsem" },
+ { LCB_F_WRITE, "rwsem:W", "rwsem" },
+ { LCB_F_RT, "rt-mutex", "rt-mutex" },
+ { LCB_F_RT | LCB_F_READ, "rwlock-rt:R", "rwlock-rt" },
+ { LCB_F_RT | LCB_F_WRITE, "rwlock-rt:W", "rwlock-rt" },
+ { LCB_F_PERCPU | LCB_F_READ, "pcpu-sem:R", "percpu-rwsem" },
+ { LCB_F_PERCPU | LCB_F_WRITE, "pcpu-sem:W", "percpu-rwsem" },
+ { LCB_F_MUTEX, "mutex", "mutex" },
+ { LCB_F_MUTEX | LCB_F_SPIN, "mutex", "mutex" },
/* alias for get_type_flag() */
- { LCB_F_MUTEX | LCB_F_SPIN, "mutex-spin" },
+ { LCB_F_MUTEX | LCB_F_SPIN, "mutex-spin", "mutex" },
};
static const char *get_type_str(unsigned int flags)
{
+ flags &= LCB_F_MAX_FLAGS - 1;
+
+ for (unsigned int i = 0; i < ARRAY_SIZE(lock_type_table); i++) {
+ if (lock_type_table[i].flags == flags)
+ return lock_type_table[i].str;
+ }
+ return "unknown";
+}
+
+static const char *get_type_name(unsigned int flags)
+{
+ flags &= LCB_F_MAX_FLAGS - 1;
+
for (unsigned int i = 0; i < ARRAY_SIZE(lock_type_table); i++) {
if (lock_type_table[i].flags == flags)
return lock_type_table[i].name;
@@ -1582,6 +1596,10 @@ static unsigned int get_type_flag(const char *str)
if (!strcmp(lock_type_table[i].name, str))
return lock_type_table[i].flags;
}
+ for (unsigned int i = 0; i < ARRAY_SIZE(lock_type_table); i++) {
+ if (!strcmp(lock_type_table[i].str, str))
+ return lock_type_table[i].flags;
+ }
return UINT_MAX;
}
@@ -1605,6 +1623,26 @@ static void sort_contention_result(void)
sort_result();
}
+static void print_bpf_events(int total, struct lock_contention_fails *fails)
+{
+ /* Output for debug, this have to be removed */
+ int broken = fails->task + fails->stack + fails->time + fails->data;
+
+ if (quiet || total == 0 || (broken == 0 && verbose <= 0))
+ return;
+
+ total += broken;
+ pr_info("\n=== output for debug ===\n\n");
+ pr_info("bad: %d, total: %d\n", broken, total);
+ pr_info("bad rate: %.2f %%\n", (double)broken / (double)total * 100);
+
+ pr_info("histogram of failure reasons\n");
+ pr_info(" %10s: %d\n", "task", fails->task);
+ pr_info(" %10s: %d\n", "stack", fails->stack);
+ pr_info(" %10s: %d\n", "time", fails->time);
+ pr_info(" %10s: %d\n", "data", fails->data);
+}
+
static void print_contention_result(struct lock_contention *con)
{
struct lock_stat *st;
@@ -1632,8 +1670,6 @@ static void print_contention_result(struct lock_contention *con)
}
bad = total = printed = 0;
- if (use_bpf)
- bad = bad_hist[BROKEN_CONTENDED];
while ((st = pop_from_result())) {
struct thread *t;
@@ -1662,8 +1698,8 @@ static void print_contention_result(struct lock_contention *con)
pid, pid == -1 ? "Unknown" : thread__comm_str(t));
break;
case LOCK_AGGR_ADDR:
- pr_info(" %016llx %s\n", (unsigned long long)st->addr,
- st->name ? : "");
+ pr_info(" %016llx %s (%s)\n", (unsigned long long)st->addr,
+ st->name, get_type_name(st->flags));
break;
default:
break;
@@ -1690,7 +1726,21 @@ static void print_contention_result(struct lock_contention *con)
break;
}
- print_bad_events(bad, total);
+ if (print_nr_entries) {
+ /* update the total/bad stats */
+ while ((st = pop_from_result())) {
+ total += use_bpf ? st->nr_contended : 1;
+ if (st->broken)
+ bad++;
+ }
+ }
+ /* some entries are collected but hidden by the callstack filter */
+ total += con->nr_filtered;
+
+ if (use_bpf)
+ print_bpf_events(total, &con->fails);
+ else
+ print_bad_events(bad, total);
}
static bool force;
@@ -1917,9 +1967,6 @@ static int __cmd_contention(int argc, const char **argv)
lock_contention_stop();
lock_contention_read(&con);
-
- /* abuse bad hist stats for lost entries */
- bad_hist[BROKEN_CONTENDED] = con.lost;
} else {
err = perf_session__process_events(session);
if (err)
@@ -2091,46 +2138,15 @@ static int parse_lock_type(const struct option *opt __maybe_unused, const char *
unsigned int flags = get_type_flag(tok);
if (flags == -1U) {
- char buf[32];
-
- if (strchr(tok, ':'))
- continue;
-
- /* try :R and :W suffixes for rwlock, rwsem, ... */
- scnprintf(buf, sizeof(buf), "%s:R", tok);
- flags = get_type_flag(buf);
- if (flags != UINT_MAX) {
- if (!add_lock_type(flags)) {
- ret = -1;
- break;
- }
- }
-
- scnprintf(buf, sizeof(buf), "%s:W", tok);
- flags = get_type_flag(buf);
- if (flags != UINT_MAX) {
- if (!add_lock_type(flags)) {
- ret = -1;
- break;
- }
- }
- continue;
+ pr_err("Unknown lock flags: %s\n", tok);
+ ret = -1;
+ break;
}
if (!add_lock_type(flags)) {
ret = -1;
break;
}
-
- if (!strcmp(tok, "mutex")) {
- flags = get_type_flag("mutex-spin");
- if (flags != UINT_MAX) {
- if (!add_lock_type(flags)) {
- ret = -1;
- break;
- }
- }
- }
}
free(s);
@@ -2291,7 +2307,7 @@ int cmd_lock(int argc, const char **argv)
"Trace on existing process id"),
OPT_STRING(0, "tid", &target.tid, "tid",
"Trace on existing thread id (exclusive to --pid)"),
- OPT_CALLBACK(0, "map-nr-entries", &bpf_map_entries, "num",
+ OPT_CALLBACK('M', "map-nr-entries", &bpf_map_entries, "num",
"Max number of BPF map entries", parse_map_entry),
OPT_CALLBACK(0, "max-stack", &max_stack_depth, "num",
"Set the maximum stack depth when collecting lopck contention, "