diff options
| author | Dmitry Torokhov <[email protected]> | 2023-08-30 16:06:38 -0700 | 
|---|---|---|
| committer | Dmitry Torokhov <[email protected]> | 2023-08-30 16:06:38 -0700 | 
| commit | 1ac731c529cd4d6adbce134754b51ff7d822b145 (patch) | |
| tree | 143ab3f35ca5f3b69f583c84e6964b17139c2ec1 /tools/perf/builtin-lock.c | |
| parent | 07b4c950f27bef0362dc6ad7ee713aab61d58149 (diff) | |
| parent | 54116d442e001e1b6bd482122043b1870998a1f3 (diff) | |
Merge branch 'next' into for-linus
Prepare input updates for 6.6 merge window.
Diffstat (limited to 'tools/perf/builtin-lock.c')
| -rw-r--r-- | tools/perf/builtin-lock.c | 142 | 
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, "  |