xref: /openbmc/linux/tools/perf/builtin-lock.c (revision 476ec641)
1 // SPDX-License-Identifier: GPL-2.0
2 #include <errno.h>
3 #include <inttypes.h>
4 #include "builtin.h"
5 #include "perf.h"
6 
7 #include "util/evlist.h" // for struct evsel_str_handler
8 #include "util/evsel.h"
9 #include "util/symbol.h"
10 #include "util/thread.h"
11 #include "util/header.h"
12 #include "util/target.h"
13 #include "util/callchain.h"
14 #include "util/lock-contention.h"
15 #include "util/bpf_skel/lock_data.h"
16 
17 #include <subcmd/pager.h>
18 #include <subcmd/parse-options.h>
19 #include "util/trace-event.h"
20 #include "util/tracepoint.h"
21 
22 #include "util/debug.h"
23 #include "util/session.h"
24 #include "util/tool.h"
25 #include "util/data.h"
26 #include "util/string2.h"
27 #include "util/map.h"
28 #include "util/util.h"
29 
30 #include <stdio.h>
31 #include <sys/types.h>
32 #include <sys/prctl.h>
33 #include <semaphore.h>
34 #include <math.h>
35 #include <limits.h>
36 #include <ctype.h>
37 
38 #include <linux/list.h>
39 #include <linux/hash.h>
40 #include <linux/kernel.h>
41 #include <linux/zalloc.h>
42 #include <linux/err.h>
43 #include <linux/stringify.h>
44 
45 static struct perf_session *session;
46 static struct target target;
47 
48 /* based on kernel/lockdep.c */
49 #define LOCKHASH_BITS		12
50 #define LOCKHASH_SIZE		(1UL << LOCKHASH_BITS)
51 
52 static struct hlist_head *lockhash_table;
53 
54 #define __lockhashfn(key)	hash_long((unsigned long)key, LOCKHASH_BITS)
55 #define lockhashentry(key)	(lockhash_table + __lockhashfn((key)))
56 
57 static struct rb_root		thread_stats;
58 
59 static bool combine_locks;
60 static bool show_thread_stats;
61 static bool show_lock_addrs;
62 static bool show_lock_owner;
63 static bool use_bpf;
64 static unsigned long bpf_map_entries = MAX_ENTRIES;
65 static int max_stack_depth = CONTENTION_STACK_DEPTH;
66 static int stack_skip = CONTENTION_STACK_SKIP;
67 static int print_nr_entries = INT_MAX / 2;
68 static LIST_HEAD(callstack_filters);
69 static const char *output_name = NULL;
70 static FILE *lock_output;
71 
72 struct callstack_filter {
73 	struct list_head list;
74 	char name[];
75 };
76 
77 static struct lock_filter filters;
78 
79 static enum lock_aggr_mode aggr_mode = LOCK_AGGR_ADDR;
80 
81 static bool needs_callstack(void)
82 {
83 	return !list_empty(&callstack_filters);
84 }
85 
86 static struct thread_stat *thread_stat_find(u32 tid)
87 {
88 	struct rb_node *node;
89 	struct thread_stat *st;
90 
91 	node = thread_stats.rb_node;
92 	while (node) {
93 		st = container_of(node, struct thread_stat, rb);
94 		if (st->tid == tid)
95 			return st;
96 		else if (tid < st->tid)
97 			node = node->rb_left;
98 		else
99 			node = node->rb_right;
100 	}
101 
102 	return NULL;
103 }
104 
105 static void thread_stat_insert(struct thread_stat *new)
106 {
107 	struct rb_node **rb = &thread_stats.rb_node;
108 	struct rb_node *parent = NULL;
109 	struct thread_stat *p;
110 
111 	while (*rb) {
112 		p = container_of(*rb, struct thread_stat, rb);
113 		parent = *rb;
114 
115 		if (new->tid < p->tid)
116 			rb = &(*rb)->rb_left;
117 		else if (new->tid > p->tid)
118 			rb = &(*rb)->rb_right;
119 		else
120 			BUG_ON("inserting invalid thread_stat\n");
121 	}
122 
123 	rb_link_node(&new->rb, parent, rb);
124 	rb_insert_color(&new->rb, &thread_stats);
125 }
126 
127 static struct thread_stat *thread_stat_findnew_after_first(u32 tid)
128 {
129 	struct thread_stat *st;
130 
131 	st = thread_stat_find(tid);
132 	if (st)
133 		return st;
134 
135 	st = zalloc(sizeof(struct thread_stat));
136 	if (!st) {
137 		pr_err("memory allocation failed\n");
138 		return NULL;
139 	}
140 
141 	st->tid = tid;
142 	INIT_LIST_HEAD(&st->seq_list);
143 
144 	thread_stat_insert(st);
145 
146 	return st;
147 }
148 
149 static struct thread_stat *thread_stat_findnew_first(u32 tid);
150 static struct thread_stat *(*thread_stat_findnew)(u32 tid) =
151 	thread_stat_findnew_first;
152 
153 static struct thread_stat *thread_stat_findnew_first(u32 tid)
154 {
155 	struct thread_stat *st;
156 
157 	st = zalloc(sizeof(struct thread_stat));
158 	if (!st) {
159 		pr_err("memory allocation failed\n");
160 		return NULL;
161 	}
162 	st->tid = tid;
163 	INIT_LIST_HEAD(&st->seq_list);
164 
165 	rb_link_node(&st->rb, NULL, &thread_stats.rb_node);
166 	rb_insert_color(&st->rb, &thread_stats);
167 
168 	thread_stat_findnew = thread_stat_findnew_after_first;
169 	return st;
170 }
171 
172 /* build simple key function one is bigger than two */
173 #define SINGLE_KEY(member)						\
174 	static int lock_stat_key_ ## member(struct lock_stat *one,	\
175 					 struct lock_stat *two)		\
176 	{								\
177 		return one->member > two->member;			\
178 	}
179 
180 SINGLE_KEY(nr_acquired)
181 SINGLE_KEY(nr_contended)
182 SINGLE_KEY(avg_wait_time)
183 SINGLE_KEY(wait_time_total)
184 SINGLE_KEY(wait_time_max)
185 
186 static int lock_stat_key_wait_time_min(struct lock_stat *one,
187 					struct lock_stat *two)
188 {
189 	u64 s1 = one->wait_time_min;
190 	u64 s2 = two->wait_time_min;
191 	if (s1 == ULLONG_MAX)
192 		s1 = 0;
193 	if (s2 == ULLONG_MAX)
194 		s2 = 0;
195 	return s1 > s2;
196 }
197 
198 struct lock_key {
199 	/*
200 	 * name: the value for specify by user
201 	 * this should be simpler than raw name of member
202 	 * e.g. nr_acquired -> acquired, wait_time_total -> wait_total
203 	 */
204 	const char		*name;
205 	/* header: the string printed on the header line */
206 	const char		*header;
207 	/* len: the printing width of the field */
208 	int			len;
209 	/* key: a pointer to function to compare two lock stats for sorting */
210 	int			(*key)(struct lock_stat*, struct lock_stat*);
211 	/* print: a pointer to function to print a given lock stats */
212 	void			(*print)(struct lock_key*, struct lock_stat*);
213 	/* list: list entry to link this */
214 	struct list_head	list;
215 };
216 
217 static void lock_stat_key_print_time(unsigned long long nsec, int len)
218 {
219 	static const struct {
220 		float base;
221 		const char *unit;
222 	} table[] = {
223 		{ 1e9 * 3600, "h " },
224 		{ 1e9 * 60, "m " },
225 		{ 1e9, "s " },
226 		{ 1e6, "ms" },
227 		{ 1e3, "us" },
228 		{ 0, NULL },
229 	};
230 
231 	/* for CSV output */
232 	if (len == 0) {
233 		fprintf(lock_output, "%llu", nsec);
234 		return;
235 	}
236 
237 	for (int i = 0; table[i].unit; i++) {
238 		if (nsec < table[i].base)
239 			continue;
240 
241 		fprintf(lock_output, "%*.2f %s", len - 3, nsec / table[i].base, table[i].unit);
242 		return;
243 	}
244 
245 	fprintf(lock_output, "%*llu %s", len - 3, nsec, "ns");
246 }
247 
248 #define PRINT_KEY(member)						\
249 static void lock_stat_key_print_ ## member(struct lock_key *key,	\
250 					   struct lock_stat *ls)	\
251 {									\
252 	fprintf(lock_output, "%*llu", key->len, (unsigned long long)ls->member);\
253 }
254 
255 #define PRINT_TIME(member)						\
256 static void lock_stat_key_print_ ## member(struct lock_key *key,	\
257 					   struct lock_stat *ls)	\
258 {									\
259 	lock_stat_key_print_time((unsigned long long)ls->member, key->len);	\
260 }
261 
262 PRINT_KEY(nr_acquired)
263 PRINT_KEY(nr_contended)
264 PRINT_TIME(avg_wait_time)
265 PRINT_TIME(wait_time_total)
266 PRINT_TIME(wait_time_max)
267 
268 static void lock_stat_key_print_wait_time_min(struct lock_key *key,
269 					      struct lock_stat *ls)
270 {
271 	u64 wait_time = ls->wait_time_min;
272 
273 	if (wait_time == ULLONG_MAX)
274 		wait_time = 0;
275 
276 	lock_stat_key_print_time(wait_time, key->len);
277 }
278 
279 
280 static const char		*sort_key = "acquired";
281 
282 static int			(*compare)(struct lock_stat *, struct lock_stat *);
283 
284 static struct rb_root		sorted; /* place to store intermediate data */
285 static struct rb_root		result;	/* place to store sorted data */
286 
287 static LIST_HEAD(lock_keys);
288 static const char		*output_fields;
289 
290 #define DEF_KEY_LOCK(name, header, fn_suffix, len)			\
291 	{ #name, header, len, lock_stat_key_ ## fn_suffix, lock_stat_key_print_ ## fn_suffix, {} }
292 static struct lock_key report_keys[] = {
293 	DEF_KEY_LOCK(acquired, "acquired", nr_acquired, 10),
294 	DEF_KEY_LOCK(contended, "contended", nr_contended, 10),
295 	DEF_KEY_LOCK(avg_wait, "avg wait", avg_wait_time, 12),
296 	DEF_KEY_LOCK(wait_total, "total wait", wait_time_total, 12),
297 	DEF_KEY_LOCK(wait_max, "max wait", wait_time_max, 12),
298 	DEF_KEY_LOCK(wait_min, "min wait", wait_time_min, 12),
299 
300 	/* extra comparisons much complicated should be here */
301 	{ }
302 };
303 
304 static struct lock_key contention_keys[] = {
305 	DEF_KEY_LOCK(contended, "contended", nr_contended, 10),
306 	DEF_KEY_LOCK(wait_total, "total wait", wait_time_total, 12),
307 	DEF_KEY_LOCK(wait_max, "max wait", wait_time_max, 12),
308 	DEF_KEY_LOCK(wait_min, "min wait", wait_time_min, 12),
309 	DEF_KEY_LOCK(avg_wait, "avg wait", avg_wait_time, 12),
310 
311 	/* extra comparisons much complicated should be here */
312 	{ }
313 };
314 
315 static int select_key(bool contention)
316 {
317 	int i;
318 	struct lock_key *keys = report_keys;
319 
320 	if (contention)
321 		keys = contention_keys;
322 
323 	for (i = 0; keys[i].name; i++) {
324 		if (!strcmp(keys[i].name, sort_key)) {
325 			compare = keys[i].key;
326 
327 			/* selected key should be in the output fields */
328 			if (list_empty(&keys[i].list))
329 				list_add_tail(&keys[i].list, &lock_keys);
330 
331 			return 0;
332 		}
333 	}
334 
335 	pr_err("Unknown compare key: %s\n", sort_key);
336 	return -1;
337 }
338 
339 static int add_output_field(bool contention, char *name)
340 {
341 	int i;
342 	struct lock_key *keys = report_keys;
343 
344 	if (contention)
345 		keys = contention_keys;
346 
347 	for (i = 0; keys[i].name; i++) {
348 		if (strcmp(keys[i].name, name))
349 			continue;
350 
351 		/* prevent double link */
352 		if (list_empty(&keys[i].list))
353 			list_add_tail(&keys[i].list, &lock_keys);
354 
355 		return 0;
356 	}
357 
358 	pr_err("Unknown output field: %s\n", name);
359 	return -1;
360 }
361 
362 static int setup_output_field(bool contention, const char *str)
363 {
364 	char *tok, *tmp, *orig;
365 	int i, ret = 0;
366 	struct lock_key *keys = report_keys;
367 
368 	if (contention)
369 		keys = contention_keys;
370 
371 	/* no output field given: use all of them */
372 	if (str == NULL) {
373 		for (i = 0; keys[i].name; i++)
374 			list_add_tail(&keys[i].list, &lock_keys);
375 		return 0;
376 	}
377 
378 	for (i = 0; keys[i].name; i++)
379 		INIT_LIST_HEAD(&keys[i].list);
380 
381 	orig = tmp = strdup(str);
382 	if (orig == NULL)
383 		return -ENOMEM;
384 
385 	while ((tok = strsep(&tmp, ",")) != NULL){
386 		ret = add_output_field(contention, tok);
387 		if (ret < 0)
388 			break;
389 	}
390 	free(orig);
391 
392 	return ret;
393 }
394 
395 static void combine_lock_stats(struct lock_stat *st)
396 {
397 	struct rb_node **rb = &sorted.rb_node;
398 	struct rb_node *parent = NULL;
399 	struct lock_stat *p;
400 	int ret;
401 
402 	while (*rb) {
403 		p = container_of(*rb, struct lock_stat, rb);
404 		parent = *rb;
405 
406 		if (st->name && p->name)
407 			ret = strcmp(st->name, p->name);
408 		else
409 			ret = !!st->name - !!p->name;
410 
411 		if (ret == 0) {
412 			p->nr_acquired += st->nr_acquired;
413 			p->nr_contended += st->nr_contended;
414 			p->wait_time_total += st->wait_time_total;
415 
416 			if (p->nr_contended)
417 				p->avg_wait_time = p->wait_time_total / p->nr_contended;
418 
419 			if (p->wait_time_min > st->wait_time_min)
420 				p->wait_time_min = st->wait_time_min;
421 			if (p->wait_time_max < st->wait_time_max)
422 				p->wait_time_max = st->wait_time_max;
423 
424 			p->broken |= st->broken;
425 			st->combined = 1;
426 			return;
427 		}
428 
429 		if (ret < 0)
430 			rb = &(*rb)->rb_left;
431 		else
432 			rb = &(*rb)->rb_right;
433 	}
434 
435 	rb_link_node(&st->rb, parent, rb);
436 	rb_insert_color(&st->rb, &sorted);
437 }
438 
439 static void insert_to_result(struct lock_stat *st,
440 			     int (*bigger)(struct lock_stat *, struct lock_stat *))
441 {
442 	struct rb_node **rb = &result.rb_node;
443 	struct rb_node *parent = NULL;
444 	struct lock_stat *p;
445 
446 	if (combine_locks && st->combined)
447 		return;
448 
449 	while (*rb) {
450 		p = container_of(*rb, struct lock_stat, rb);
451 		parent = *rb;
452 
453 		if (bigger(st, p))
454 			rb = &(*rb)->rb_left;
455 		else
456 			rb = &(*rb)->rb_right;
457 	}
458 
459 	rb_link_node(&st->rb, parent, rb);
460 	rb_insert_color(&st->rb, &result);
461 }
462 
463 /* returns left most element of result, and erase it */
464 static struct lock_stat *pop_from_result(void)
465 {
466 	struct rb_node *node = result.rb_node;
467 
468 	if (!node)
469 		return NULL;
470 
471 	while (node->rb_left)
472 		node = node->rb_left;
473 
474 	rb_erase(node, &result);
475 	return container_of(node, struct lock_stat, rb);
476 }
477 
478 struct lock_stat *lock_stat_find(u64 addr)
479 {
480 	struct hlist_head *entry = lockhashentry(addr);
481 	struct lock_stat *ret;
482 
483 	hlist_for_each_entry(ret, entry, hash_entry) {
484 		if (ret->addr == addr)
485 			return ret;
486 	}
487 	return NULL;
488 }
489 
490 struct lock_stat *lock_stat_findnew(u64 addr, const char *name, int flags)
491 {
492 	struct hlist_head *entry = lockhashentry(addr);
493 	struct lock_stat *ret, *new;
494 
495 	hlist_for_each_entry(ret, entry, hash_entry) {
496 		if (ret->addr == addr)
497 			return ret;
498 	}
499 
500 	new = zalloc(sizeof(struct lock_stat));
501 	if (!new)
502 		goto alloc_failed;
503 
504 	new->addr = addr;
505 	new->name = strdup(name);
506 	if (!new->name) {
507 		free(new);
508 		goto alloc_failed;
509 	}
510 
511 	new->flags = flags;
512 	new->wait_time_min = ULLONG_MAX;
513 
514 	hlist_add_head(&new->hash_entry, entry);
515 	return new;
516 
517 alloc_failed:
518 	pr_err("memory allocation failed\n");
519 	return NULL;
520 }
521 
522 bool match_callstack_filter(struct machine *machine, u64 *callstack)
523 {
524 	struct map *kmap;
525 	struct symbol *sym;
526 	u64 ip;
527 
528 	if (list_empty(&callstack_filters))
529 		return true;
530 
531 	for (int i = 0; i < max_stack_depth; i++) {
532 		struct callstack_filter *filter;
533 
534 		if (!callstack || !callstack[i])
535 			break;
536 
537 		ip = callstack[i];
538 		sym = machine__find_kernel_symbol(machine, ip, &kmap);
539 		if (sym == NULL)
540 			continue;
541 
542 		list_for_each_entry(filter, &callstack_filters, list) {
543 			if (strstr(sym->name, filter->name))
544 				return true;
545 		}
546 	}
547 	return false;
548 }
549 
550 struct trace_lock_handler {
551 	/* it's used on CONFIG_LOCKDEP */
552 	int (*acquire_event)(struct evsel *evsel,
553 			     struct perf_sample *sample);
554 
555 	/* it's used on CONFIG_LOCKDEP && CONFIG_LOCK_STAT */
556 	int (*acquired_event)(struct evsel *evsel,
557 			      struct perf_sample *sample);
558 
559 	/* it's used on CONFIG_LOCKDEP && CONFIG_LOCK_STAT */
560 	int (*contended_event)(struct evsel *evsel,
561 			       struct perf_sample *sample);
562 
563 	/* it's used on CONFIG_LOCKDEP */
564 	int (*release_event)(struct evsel *evsel,
565 			     struct perf_sample *sample);
566 
567 	/* it's used when CONFIG_LOCKDEP is off */
568 	int (*contention_begin_event)(struct evsel *evsel,
569 				      struct perf_sample *sample);
570 
571 	/* it's used when CONFIG_LOCKDEP is off */
572 	int (*contention_end_event)(struct evsel *evsel,
573 				    struct perf_sample *sample);
574 };
575 
576 static struct lock_seq_stat *get_seq(struct thread_stat *ts, u64 addr)
577 {
578 	struct lock_seq_stat *seq;
579 
580 	list_for_each_entry(seq, &ts->seq_list, list) {
581 		if (seq->addr == addr)
582 			return seq;
583 	}
584 
585 	seq = zalloc(sizeof(struct lock_seq_stat));
586 	if (!seq) {
587 		pr_err("memory allocation failed\n");
588 		return NULL;
589 	}
590 	seq->state = SEQ_STATE_UNINITIALIZED;
591 	seq->addr = addr;
592 
593 	list_add(&seq->list, &ts->seq_list);
594 	return seq;
595 }
596 
597 enum broken_state {
598 	BROKEN_ACQUIRE,
599 	BROKEN_ACQUIRED,
600 	BROKEN_CONTENDED,
601 	BROKEN_RELEASE,
602 	BROKEN_MAX,
603 };
604 
605 static int bad_hist[BROKEN_MAX];
606 
607 enum acquire_flags {
608 	TRY_LOCK = 1,
609 	READ_LOCK = 2,
610 };
611 
612 static int get_key_by_aggr_mode_simple(u64 *key, u64 addr, u32 tid)
613 {
614 	switch (aggr_mode) {
615 	case LOCK_AGGR_ADDR:
616 		*key = addr;
617 		break;
618 	case LOCK_AGGR_TASK:
619 		*key = tid;
620 		break;
621 	case LOCK_AGGR_CALLER:
622 	default:
623 		pr_err("Invalid aggregation mode: %d\n", aggr_mode);
624 		return -EINVAL;
625 	}
626 	return 0;
627 }
628 
629 static u64 callchain_id(struct evsel *evsel, struct perf_sample *sample);
630 
631 static int get_key_by_aggr_mode(u64 *key, u64 addr, struct evsel *evsel,
632 				 struct perf_sample *sample)
633 {
634 	if (aggr_mode == LOCK_AGGR_CALLER) {
635 		*key = callchain_id(evsel, sample);
636 		return 0;
637 	}
638 	return get_key_by_aggr_mode_simple(key, addr, sample->tid);
639 }
640 
641 static int report_lock_acquire_event(struct evsel *evsel,
642 				     struct perf_sample *sample)
643 {
644 	struct lock_stat *ls;
645 	struct thread_stat *ts;
646 	struct lock_seq_stat *seq;
647 	const char *name = evsel__strval(evsel, sample, "name");
648 	u64 addr = evsel__intval(evsel, sample, "lockdep_addr");
649 	int flag = evsel__intval(evsel, sample, "flags");
650 	u64 key;
651 	int ret;
652 
653 	ret = get_key_by_aggr_mode_simple(&key, addr, sample->tid);
654 	if (ret < 0)
655 		return ret;
656 
657 	ls = lock_stat_findnew(key, name, 0);
658 	if (!ls)
659 		return -ENOMEM;
660 
661 	ts = thread_stat_findnew(sample->tid);
662 	if (!ts)
663 		return -ENOMEM;
664 
665 	seq = get_seq(ts, addr);
666 	if (!seq)
667 		return -ENOMEM;
668 
669 	switch (seq->state) {
670 	case SEQ_STATE_UNINITIALIZED:
671 	case SEQ_STATE_RELEASED:
672 		if (!flag) {
673 			seq->state = SEQ_STATE_ACQUIRING;
674 		} else {
675 			if (flag & TRY_LOCK)
676 				ls->nr_trylock++;
677 			if (flag & READ_LOCK)
678 				ls->nr_readlock++;
679 			seq->state = SEQ_STATE_READ_ACQUIRED;
680 			seq->read_count = 1;
681 			ls->nr_acquired++;
682 		}
683 		break;
684 	case SEQ_STATE_READ_ACQUIRED:
685 		if (flag & READ_LOCK) {
686 			seq->read_count++;
687 			ls->nr_acquired++;
688 			goto end;
689 		} else {
690 			goto broken;
691 		}
692 		break;
693 	case SEQ_STATE_ACQUIRED:
694 	case SEQ_STATE_ACQUIRING:
695 	case SEQ_STATE_CONTENDED:
696 broken:
697 		/* broken lock sequence */
698 		if (!ls->broken) {
699 			ls->broken = 1;
700 			bad_hist[BROKEN_ACQUIRE]++;
701 		}
702 		list_del_init(&seq->list);
703 		free(seq);
704 		goto end;
705 	default:
706 		BUG_ON("Unknown state of lock sequence found!\n");
707 		break;
708 	}
709 
710 	ls->nr_acquire++;
711 	seq->prev_event_time = sample->time;
712 end:
713 	return 0;
714 }
715 
716 static int report_lock_acquired_event(struct evsel *evsel,
717 				      struct perf_sample *sample)
718 {
719 	struct lock_stat *ls;
720 	struct thread_stat *ts;
721 	struct lock_seq_stat *seq;
722 	u64 contended_term;
723 	const char *name = evsel__strval(evsel, sample, "name");
724 	u64 addr = evsel__intval(evsel, sample, "lockdep_addr");
725 	u64 key;
726 	int ret;
727 
728 	ret = get_key_by_aggr_mode_simple(&key, addr, sample->tid);
729 	if (ret < 0)
730 		return ret;
731 
732 	ls = lock_stat_findnew(key, name, 0);
733 	if (!ls)
734 		return -ENOMEM;
735 
736 	ts = thread_stat_findnew(sample->tid);
737 	if (!ts)
738 		return -ENOMEM;
739 
740 	seq = get_seq(ts, addr);
741 	if (!seq)
742 		return -ENOMEM;
743 
744 	switch (seq->state) {
745 	case SEQ_STATE_UNINITIALIZED:
746 		/* orphan event, do nothing */
747 		return 0;
748 	case SEQ_STATE_ACQUIRING:
749 		break;
750 	case SEQ_STATE_CONTENDED:
751 		contended_term = sample->time - seq->prev_event_time;
752 		ls->wait_time_total += contended_term;
753 		if (contended_term < ls->wait_time_min)
754 			ls->wait_time_min = contended_term;
755 		if (ls->wait_time_max < contended_term)
756 			ls->wait_time_max = contended_term;
757 		break;
758 	case SEQ_STATE_RELEASED:
759 	case SEQ_STATE_ACQUIRED:
760 	case SEQ_STATE_READ_ACQUIRED:
761 		/* broken lock sequence */
762 		if (!ls->broken) {
763 			ls->broken = 1;
764 			bad_hist[BROKEN_ACQUIRED]++;
765 		}
766 		list_del_init(&seq->list);
767 		free(seq);
768 		goto end;
769 	default:
770 		BUG_ON("Unknown state of lock sequence found!\n");
771 		break;
772 	}
773 
774 	seq->state = SEQ_STATE_ACQUIRED;
775 	ls->nr_acquired++;
776 	ls->avg_wait_time = ls->nr_contended ? ls->wait_time_total/ls->nr_contended : 0;
777 	seq->prev_event_time = sample->time;
778 end:
779 	return 0;
780 }
781 
782 static int report_lock_contended_event(struct evsel *evsel,
783 				       struct perf_sample *sample)
784 {
785 	struct lock_stat *ls;
786 	struct thread_stat *ts;
787 	struct lock_seq_stat *seq;
788 	const char *name = evsel__strval(evsel, sample, "name");
789 	u64 addr = evsel__intval(evsel, sample, "lockdep_addr");
790 	u64 key;
791 	int ret;
792 
793 	ret = get_key_by_aggr_mode_simple(&key, addr, sample->tid);
794 	if (ret < 0)
795 		return ret;
796 
797 	ls = lock_stat_findnew(key, name, 0);
798 	if (!ls)
799 		return -ENOMEM;
800 
801 	ts = thread_stat_findnew(sample->tid);
802 	if (!ts)
803 		return -ENOMEM;
804 
805 	seq = get_seq(ts, addr);
806 	if (!seq)
807 		return -ENOMEM;
808 
809 	switch (seq->state) {
810 	case SEQ_STATE_UNINITIALIZED:
811 		/* orphan event, do nothing */
812 		return 0;
813 	case SEQ_STATE_ACQUIRING:
814 		break;
815 	case SEQ_STATE_RELEASED:
816 	case SEQ_STATE_ACQUIRED:
817 	case SEQ_STATE_READ_ACQUIRED:
818 	case SEQ_STATE_CONTENDED:
819 		/* broken lock sequence */
820 		if (!ls->broken) {
821 			ls->broken = 1;
822 			bad_hist[BROKEN_CONTENDED]++;
823 		}
824 		list_del_init(&seq->list);
825 		free(seq);
826 		goto end;
827 	default:
828 		BUG_ON("Unknown state of lock sequence found!\n");
829 		break;
830 	}
831 
832 	seq->state = SEQ_STATE_CONTENDED;
833 	ls->nr_contended++;
834 	ls->avg_wait_time = ls->wait_time_total/ls->nr_contended;
835 	seq->prev_event_time = sample->time;
836 end:
837 	return 0;
838 }
839 
840 static int report_lock_release_event(struct evsel *evsel,
841 				     struct perf_sample *sample)
842 {
843 	struct lock_stat *ls;
844 	struct thread_stat *ts;
845 	struct lock_seq_stat *seq;
846 	const char *name = evsel__strval(evsel, sample, "name");
847 	u64 addr = evsel__intval(evsel, sample, "lockdep_addr");
848 	u64 key;
849 	int ret;
850 
851 	ret = get_key_by_aggr_mode_simple(&key, addr, sample->tid);
852 	if (ret < 0)
853 		return ret;
854 
855 	ls = lock_stat_findnew(key, name, 0);
856 	if (!ls)
857 		return -ENOMEM;
858 
859 	ts = thread_stat_findnew(sample->tid);
860 	if (!ts)
861 		return -ENOMEM;
862 
863 	seq = get_seq(ts, addr);
864 	if (!seq)
865 		return -ENOMEM;
866 
867 	switch (seq->state) {
868 	case SEQ_STATE_UNINITIALIZED:
869 		goto end;
870 	case SEQ_STATE_ACQUIRED:
871 		break;
872 	case SEQ_STATE_READ_ACQUIRED:
873 		seq->read_count--;
874 		BUG_ON(seq->read_count < 0);
875 		if (seq->read_count) {
876 			ls->nr_release++;
877 			goto end;
878 		}
879 		break;
880 	case SEQ_STATE_ACQUIRING:
881 	case SEQ_STATE_CONTENDED:
882 	case SEQ_STATE_RELEASED:
883 		/* broken lock sequence */
884 		if (!ls->broken) {
885 			ls->broken = 1;
886 			bad_hist[BROKEN_RELEASE]++;
887 		}
888 		goto free_seq;
889 	default:
890 		BUG_ON("Unknown state of lock sequence found!\n");
891 		break;
892 	}
893 
894 	ls->nr_release++;
895 free_seq:
896 	list_del_init(&seq->list);
897 	free(seq);
898 end:
899 	return 0;
900 }
901 
902 static int get_symbol_name_offset(struct map *map, struct symbol *sym, u64 ip,
903 				  char *buf, int size)
904 {
905 	u64 offset;
906 
907 	if (map == NULL || sym == NULL) {
908 		buf[0] = '\0';
909 		return 0;
910 	}
911 
912 	offset = map__map_ip(map, ip) - sym->start;
913 
914 	if (offset)
915 		return scnprintf(buf, size, "%s+%#lx", sym->name, offset);
916 	else
917 		return strlcpy(buf, sym->name, size);
918 }
919 static int lock_contention_caller(struct evsel *evsel, struct perf_sample *sample,
920 				  char *buf, int size)
921 {
922 	struct thread *thread;
923 	struct callchain_cursor *cursor;
924 	struct machine *machine = &session->machines.host;
925 	struct symbol *sym;
926 	int skip = 0;
927 	int ret;
928 
929 	/* lock names will be replaced to task name later */
930 	if (show_thread_stats)
931 		return -1;
932 
933 	thread = machine__findnew_thread(machine, -1, sample->pid);
934 	if (thread == NULL)
935 		return -1;
936 
937 	cursor = get_tls_callchain_cursor();
938 
939 	/* use caller function name from the callchain */
940 	ret = thread__resolve_callchain(thread, cursor, evsel, sample,
941 					NULL, NULL, max_stack_depth);
942 	if (ret != 0) {
943 		thread__put(thread);
944 		return -1;
945 	}
946 
947 	callchain_cursor_commit(cursor);
948 	thread__put(thread);
949 
950 	while (true) {
951 		struct callchain_cursor_node *node;
952 
953 		node = callchain_cursor_current(cursor);
954 		if (node == NULL)
955 			break;
956 
957 		/* skip first few entries - for lock functions */
958 		if (++skip <= stack_skip)
959 			goto next;
960 
961 		sym = node->ms.sym;
962 		if (sym && !machine__is_lock_function(machine, node->ip)) {
963 			get_symbol_name_offset(node->ms.map, sym, node->ip,
964 					       buf, size);
965 			return 0;
966 		}
967 
968 next:
969 		callchain_cursor_advance(cursor);
970 	}
971 	return -1;
972 }
973 
974 static u64 callchain_id(struct evsel *evsel, struct perf_sample *sample)
975 {
976 	struct callchain_cursor *cursor;
977 	struct machine *machine = &session->machines.host;
978 	struct thread *thread;
979 	u64 hash = 0;
980 	int skip = 0;
981 	int ret;
982 
983 	thread = machine__findnew_thread(machine, -1, sample->pid);
984 	if (thread == NULL)
985 		return -1;
986 
987 	cursor = get_tls_callchain_cursor();
988 	/* use caller function name from the callchain */
989 	ret = thread__resolve_callchain(thread, cursor, evsel, sample,
990 					NULL, NULL, max_stack_depth);
991 	thread__put(thread);
992 
993 	if (ret != 0)
994 		return -1;
995 
996 	callchain_cursor_commit(cursor);
997 
998 	while (true) {
999 		struct callchain_cursor_node *node;
1000 
1001 		node = callchain_cursor_current(cursor);
1002 		if (node == NULL)
1003 			break;
1004 
1005 		/* skip first few entries - for lock functions */
1006 		if (++skip <= stack_skip)
1007 			goto next;
1008 
1009 		if (node->ms.sym && machine__is_lock_function(machine, node->ip))
1010 			goto next;
1011 
1012 		hash ^= hash_long((unsigned long)node->ip, 64);
1013 
1014 next:
1015 		callchain_cursor_advance(cursor);
1016 	}
1017 	return hash;
1018 }
1019 
1020 static u64 *get_callstack(struct perf_sample *sample, int max_stack)
1021 {
1022 	u64 *callstack;
1023 	u64 i;
1024 	int c;
1025 
1026 	callstack = calloc(max_stack, sizeof(*callstack));
1027 	if (callstack == NULL)
1028 		return NULL;
1029 
1030 	for (i = 0, c = 0; i < sample->callchain->nr && c < max_stack; i++) {
1031 		u64 ip = sample->callchain->ips[i];
1032 
1033 		if (ip >= PERF_CONTEXT_MAX)
1034 			continue;
1035 
1036 		callstack[c++] = ip;
1037 	}
1038 	return callstack;
1039 }
1040 
1041 static int report_lock_contention_begin_event(struct evsel *evsel,
1042 					      struct perf_sample *sample)
1043 {
1044 	struct lock_stat *ls;
1045 	struct thread_stat *ts;
1046 	struct lock_seq_stat *seq;
1047 	u64 addr = evsel__intval(evsel, sample, "lock_addr");
1048 	unsigned int flags = evsel__intval(evsel, sample, "flags");
1049 	u64 key;
1050 	int i, ret;
1051 	static bool kmap_loaded;
1052 	struct machine *machine = &session->machines.host;
1053 	struct map *kmap;
1054 	struct symbol *sym;
1055 
1056 	ret = get_key_by_aggr_mode(&key, addr, evsel, sample);
1057 	if (ret < 0)
1058 		return ret;
1059 
1060 	if (!kmap_loaded) {
1061 		unsigned long *addrs;
1062 
1063 		/* make sure it loads the kernel map to find lock symbols */
1064 		map__load(machine__kernel_map(machine));
1065 		kmap_loaded = true;
1066 
1067 		/* convert (kernel) symbols to addresses */
1068 		for (i = 0; i < filters.nr_syms; i++) {
1069 			sym = machine__find_kernel_symbol_by_name(machine,
1070 								  filters.syms[i],
1071 								  &kmap);
1072 			if (sym == NULL) {
1073 				pr_warning("ignore unknown symbol: %s\n",
1074 					   filters.syms[i]);
1075 				continue;
1076 			}
1077 
1078 			addrs = realloc(filters.addrs,
1079 					(filters.nr_addrs + 1) * sizeof(*addrs));
1080 			if (addrs == NULL) {
1081 				pr_warning("memory allocation failure\n");
1082 				return -ENOMEM;
1083 			}
1084 
1085 			addrs[filters.nr_addrs++] = map__unmap_ip(kmap, sym->start);
1086 			filters.addrs = addrs;
1087 		}
1088 	}
1089 
1090 	ls = lock_stat_find(key);
1091 	if (!ls) {
1092 		char buf[128];
1093 		const char *name = "";
1094 
1095 		switch (aggr_mode) {
1096 		case LOCK_AGGR_ADDR:
1097 			sym = machine__find_kernel_symbol(machine, key, &kmap);
1098 			if (sym)
1099 				name = sym->name;
1100 			break;
1101 		case LOCK_AGGR_CALLER:
1102 			name = buf;
1103 			if (lock_contention_caller(evsel, sample, buf, sizeof(buf)) < 0)
1104 				name = "Unknown";
1105 			break;
1106 		case LOCK_AGGR_TASK:
1107 		default:
1108 			break;
1109 		}
1110 
1111 		ls = lock_stat_findnew(key, name, flags);
1112 		if (!ls)
1113 			return -ENOMEM;
1114 	}
1115 
1116 	if (filters.nr_types) {
1117 		bool found = false;
1118 
1119 		for (i = 0; i < filters.nr_types; i++) {
1120 			if (flags == filters.types[i]) {
1121 				found = true;
1122 				break;
1123 			}
1124 		}
1125 
1126 		if (!found)
1127 			return 0;
1128 	}
1129 
1130 	if (filters.nr_addrs) {
1131 		bool found = false;
1132 
1133 		for (i = 0; i < filters.nr_addrs; i++) {
1134 			if (addr == filters.addrs[i]) {
1135 				found = true;
1136 				break;
1137 			}
1138 		}
1139 
1140 		if (!found)
1141 			return 0;
1142 	}
1143 
1144 	if (needs_callstack()) {
1145 		u64 *callstack = get_callstack(sample, max_stack_depth);
1146 		if (callstack == NULL)
1147 			return -ENOMEM;
1148 
1149 		if (!match_callstack_filter(machine, callstack)) {
1150 			free(callstack);
1151 			return 0;
1152 		}
1153 
1154 		if (ls->callstack == NULL)
1155 			ls->callstack = callstack;
1156 		else
1157 			free(callstack);
1158 	}
1159 
1160 	ts = thread_stat_findnew(sample->tid);
1161 	if (!ts)
1162 		return -ENOMEM;
1163 
1164 	seq = get_seq(ts, addr);
1165 	if (!seq)
1166 		return -ENOMEM;
1167 
1168 	switch (seq->state) {
1169 	case SEQ_STATE_UNINITIALIZED:
1170 	case SEQ_STATE_ACQUIRED:
1171 		break;
1172 	case SEQ_STATE_CONTENDED:
1173 		/*
1174 		 * It can have nested contention begin with mutex spinning,
1175 		 * then we would use the original contention begin event and
1176 		 * ignore the second one.
1177 		 */
1178 		goto end;
1179 	case SEQ_STATE_ACQUIRING:
1180 	case SEQ_STATE_READ_ACQUIRED:
1181 	case SEQ_STATE_RELEASED:
1182 		/* broken lock sequence */
1183 		if (!ls->broken) {
1184 			ls->broken = 1;
1185 			bad_hist[BROKEN_CONTENDED]++;
1186 		}
1187 		list_del_init(&seq->list);
1188 		free(seq);
1189 		goto end;
1190 	default:
1191 		BUG_ON("Unknown state of lock sequence found!\n");
1192 		break;
1193 	}
1194 
1195 	if (seq->state != SEQ_STATE_CONTENDED) {
1196 		seq->state = SEQ_STATE_CONTENDED;
1197 		seq->prev_event_time = sample->time;
1198 		ls->nr_contended++;
1199 	}
1200 end:
1201 	return 0;
1202 }
1203 
1204 static int report_lock_contention_end_event(struct evsel *evsel,
1205 					    struct perf_sample *sample)
1206 {
1207 	struct lock_stat *ls;
1208 	struct thread_stat *ts;
1209 	struct lock_seq_stat *seq;
1210 	u64 contended_term;
1211 	u64 addr = evsel__intval(evsel, sample, "lock_addr");
1212 	u64 key;
1213 	int ret;
1214 
1215 	ret = get_key_by_aggr_mode(&key, addr, evsel, sample);
1216 	if (ret < 0)
1217 		return ret;
1218 
1219 	ls = lock_stat_find(key);
1220 	if (!ls)
1221 		return 0;
1222 
1223 	ts = thread_stat_find(sample->tid);
1224 	if (!ts)
1225 		return 0;
1226 
1227 	seq = get_seq(ts, addr);
1228 	if (!seq)
1229 		return -ENOMEM;
1230 
1231 	switch (seq->state) {
1232 	case SEQ_STATE_UNINITIALIZED:
1233 		goto end;
1234 	case SEQ_STATE_CONTENDED:
1235 		contended_term = sample->time - seq->prev_event_time;
1236 		ls->wait_time_total += contended_term;
1237 		if (contended_term < ls->wait_time_min)
1238 			ls->wait_time_min = contended_term;
1239 		if (ls->wait_time_max < contended_term)
1240 			ls->wait_time_max = contended_term;
1241 		break;
1242 	case SEQ_STATE_ACQUIRING:
1243 	case SEQ_STATE_ACQUIRED:
1244 	case SEQ_STATE_READ_ACQUIRED:
1245 	case SEQ_STATE_RELEASED:
1246 		/* broken lock sequence */
1247 		if (!ls->broken) {
1248 			ls->broken = 1;
1249 			bad_hist[BROKEN_ACQUIRED]++;
1250 		}
1251 		list_del_init(&seq->list);
1252 		free(seq);
1253 		goto end;
1254 	default:
1255 		BUG_ON("Unknown state of lock sequence found!\n");
1256 		break;
1257 	}
1258 
1259 	seq->state = SEQ_STATE_ACQUIRED;
1260 	ls->nr_acquired++;
1261 	ls->avg_wait_time = ls->wait_time_total/ls->nr_acquired;
1262 end:
1263 	return 0;
1264 }
1265 
1266 /* lock oriented handlers */
1267 /* TODO: handlers for CPU oriented, thread oriented */
1268 static struct trace_lock_handler report_lock_ops  = {
1269 	.acquire_event		= report_lock_acquire_event,
1270 	.acquired_event		= report_lock_acquired_event,
1271 	.contended_event	= report_lock_contended_event,
1272 	.release_event		= report_lock_release_event,
1273 	.contention_begin_event	= report_lock_contention_begin_event,
1274 	.contention_end_event	= report_lock_contention_end_event,
1275 };
1276 
1277 static struct trace_lock_handler contention_lock_ops  = {
1278 	.contention_begin_event	= report_lock_contention_begin_event,
1279 	.contention_end_event	= report_lock_contention_end_event,
1280 };
1281 
1282 
1283 static struct trace_lock_handler *trace_handler;
1284 
1285 static int evsel__process_lock_acquire(struct evsel *evsel, struct perf_sample *sample)
1286 {
1287 	if (trace_handler->acquire_event)
1288 		return trace_handler->acquire_event(evsel, sample);
1289 	return 0;
1290 }
1291 
1292 static int evsel__process_lock_acquired(struct evsel *evsel, struct perf_sample *sample)
1293 {
1294 	if (trace_handler->acquired_event)
1295 		return trace_handler->acquired_event(evsel, sample);
1296 	return 0;
1297 }
1298 
1299 static int evsel__process_lock_contended(struct evsel *evsel, struct perf_sample *sample)
1300 {
1301 	if (trace_handler->contended_event)
1302 		return trace_handler->contended_event(evsel, sample);
1303 	return 0;
1304 }
1305 
1306 static int evsel__process_lock_release(struct evsel *evsel, struct perf_sample *sample)
1307 {
1308 	if (trace_handler->release_event)
1309 		return trace_handler->release_event(evsel, sample);
1310 	return 0;
1311 }
1312 
1313 static int evsel__process_contention_begin(struct evsel *evsel, struct perf_sample *sample)
1314 {
1315 	if (trace_handler->contention_begin_event)
1316 		return trace_handler->contention_begin_event(evsel, sample);
1317 	return 0;
1318 }
1319 
1320 static int evsel__process_contention_end(struct evsel *evsel, struct perf_sample *sample)
1321 {
1322 	if (trace_handler->contention_end_event)
1323 		return trace_handler->contention_end_event(evsel, sample);
1324 	return 0;
1325 }
1326 
1327 static void print_bad_events(int bad, int total)
1328 {
1329 	/* Output for debug, this have to be removed */
1330 	int i;
1331 	int broken = 0;
1332 	const char *name[4] =
1333 		{ "acquire", "acquired", "contended", "release" };
1334 
1335 	for (i = 0; i < BROKEN_MAX; i++)
1336 		broken += bad_hist[i];
1337 
1338 	if (quiet || total == 0 || (broken == 0 && verbose <= 0))
1339 		return;
1340 
1341 	fprintf(lock_output, "\n=== output for debug ===\n\n");
1342 	fprintf(lock_output, "bad: %d, total: %d\n", bad, total);
1343 	fprintf(lock_output, "bad rate: %.2f %%\n", (double)bad / (double)total * 100);
1344 	fprintf(lock_output, "histogram of events caused bad sequence\n");
1345 	for (i = 0; i < BROKEN_MAX; i++)
1346 		fprintf(lock_output, " %10s: %d\n", name[i], bad_hist[i]);
1347 }
1348 
1349 /* TODO: various way to print, coloring, nano or milli sec */
1350 static void print_result(void)
1351 {
1352 	struct lock_stat *st;
1353 	struct lock_key *key;
1354 	char cut_name[20];
1355 	int bad, total, printed;
1356 
1357 	if (!quiet) {
1358 		fprintf(lock_output, "%20s ", "Name");
1359 		list_for_each_entry(key, &lock_keys, list)
1360 			fprintf(lock_output, "%*s ", key->len, key->header);
1361 		fprintf(lock_output, "\n\n");
1362 	}
1363 
1364 	bad = total = printed = 0;
1365 	while ((st = pop_from_result())) {
1366 		total++;
1367 		if (st->broken)
1368 			bad++;
1369 		if (!st->nr_acquired)
1370 			continue;
1371 
1372 		bzero(cut_name, 20);
1373 
1374 		if (strlen(st->name) < 20) {
1375 			/* output raw name */
1376 			const char *name = st->name;
1377 
1378 			if (show_thread_stats) {
1379 				struct thread *t;
1380 
1381 				/* st->addr contains tid of thread */
1382 				t = perf_session__findnew(session, st->addr);
1383 				name = thread__comm_str(t);
1384 			}
1385 
1386 			fprintf(lock_output, "%20s ", name);
1387 		} else {
1388 			strncpy(cut_name, st->name, 16);
1389 			cut_name[16] = '.';
1390 			cut_name[17] = '.';
1391 			cut_name[18] = '.';
1392 			cut_name[19] = '\0';
1393 			/* cut off name for saving output style */
1394 			fprintf(lock_output, "%20s ", cut_name);
1395 		}
1396 
1397 		list_for_each_entry(key, &lock_keys, list) {
1398 			key->print(key, st);
1399 			fprintf(lock_output, " ");
1400 		}
1401 		fprintf(lock_output, "\n");
1402 
1403 		if (++printed >= print_nr_entries)
1404 			break;
1405 	}
1406 
1407 	print_bad_events(bad, total);
1408 }
1409 
1410 static bool info_threads, info_map;
1411 
1412 static void dump_threads(void)
1413 {
1414 	struct thread_stat *st;
1415 	struct rb_node *node;
1416 	struct thread *t;
1417 
1418 	fprintf(lock_output, "%10s: comm\n", "Thread ID");
1419 
1420 	node = rb_first(&thread_stats);
1421 	while (node) {
1422 		st = container_of(node, struct thread_stat, rb);
1423 		t = perf_session__findnew(session, st->tid);
1424 		fprintf(lock_output, "%10d: %s\n", st->tid, thread__comm_str(t));
1425 		node = rb_next(node);
1426 		thread__put(t);
1427 	}
1428 }
1429 
1430 static int compare_maps(struct lock_stat *a, struct lock_stat *b)
1431 {
1432 	int ret;
1433 
1434 	if (a->name && b->name)
1435 		ret = strcmp(a->name, b->name);
1436 	else
1437 		ret = !!a->name - !!b->name;
1438 
1439 	if (!ret)
1440 		return a->addr < b->addr;
1441 	else
1442 		return ret < 0;
1443 }
1444 
1445 static void dump_map(void)
1446 {
1447 	unsigned int i;
1448 	struct lock_stat *st;
1449 
1450 	fprintf(lock_output, "Address of instance: name of class\n");
1451 	for (i = 0; i < LOCKHASH_SIZE; i++) {
1452 		hlist_for_each_entry(st, &lockhash_table[i], hash_entry) {
1453 			insert_to_result(st, compare_maps);
1454 		}
1455 	}
1456 
1457 	while ((st = pop_from_result()))
1458 		fprintf(lock_output, " %#llx: %s\n", (unsigned long long)st->addr, st->name);
1459 }
1460 
1461 static int dump_info(void)
1462 {
1463 	int rc = 0;
1464 
1465 	if (info_threads)
1466 		dump_threads();
1467 	else if (info_map)
1468 		dump_map();
1469 	else {
1470 		rc = -1;
1471 		pr_err("Unknown type of information\n");
1472 	}
1473 
1474 	return rc;
1475 }
1476 
1477 static const struct evsel_str_handler lock_tracepoints[] = {
1478 	{ "lock:lock_acquire",	 evsel__process_lock_acquire,   }, /* CONFIG_LOCKDEP */
1479 	{ "lock:lock_acquired",	 evsel__process_lock_acquired,  }, /* CONFIG_LOCKDEP, CONFIG_LOCK_STAT */
1480 	{ "lock:lock_contended", evsel__process_lock_contended, }, /* CONFIG_LOCKDEP, CONFIG_LOCK_STAT */
1481 	{ "lock:lock_release",	 evsel__process_lock_release,   }, /* CONFIG_LOCKDEP */
1482 };
1483 
1484 static const struct evsel_str_handler contention_tracepoints[] = {
1485 	{ "lock:contention_begin", evsel__process_contention_begin, },
1486 	{ "lock:contention_end",   evsel__process_contention_end,   },
1487 };
1488 
1489 static int process_event_update(struct perf_tool *tool,
1490 				union perf_event *event,
1491 				struct evlist **pevlist)
1492 {
1493 	int ret;
1494 
1495 	ret = perf_event__process_event_update(tool, event, pevlist);
1496 	if (ret < 0)
1497 		return ret;
1498 
1499 	/* this can return -EEXIST since we call it for each evsel */
1500 	perf_session__set_tracepoints_handlers(session, lock_tracepoints);
1501 	perf_session__set_tracepoints_handlers(session, contention_tracepoints);
1502 	return 0;
1503 }
1504 
1505 typedef int (*tracepoint_handler)(struct evsel *evsel,
1506 				  struct perf_sample *sample);
1507 
1508 static int process_sample_event(struct perf_tool *tool __maybe_unused,
1509 				union perf_event *event,
1510 				struct perf_sample *sample,
1511 				struct evsel *evsel,
1512 				struct machine *machine)
1513 {
1514 	int err = 0;
1515 	struct thread *thread = machine__findnew_thread(machine, sample->pid,
1516 							sample->tid);
1517 
1518 	if (thread == NULL) {
1519 		pr_debug("problem processing %d event, skipping it.\n",
1520 			event->header.type);
1521 		return -1;
1522 	}
1523 
1524 	if (evsel->handler != NULL) {
1525 		tracepoint_handler f = evsel->handler;
1526 		err = f(evsel, sample);
1527 	}
1528 
1529 	thread__put(thread);
1530 
1531 	return err;
1532 }
1533 
1534 static void combine_result(void)
1535 {
1536 	unsigned int i;
1537 	struct lock_stat *st;
1538 
1539 	if (!combine_locks)
1540 		return;
1541 
1542 	for (i = 0; i < LOCKHASH_SIZE; i++) {
1543 		hlist_for_each_entry(st, &lockhash_table[i], hash_entry) {
1544 			combine_lock_stats(st);
1545 		}
1546 	}
1547 }
1548 
1549 static void sort_result(void)
1550 {
1551 	unsigned int i;
1552 	struct lock_stat *st;
1553 
1554 	for (i = 0; i < LOCKHASH_SIZE; i++) {
1555 		hlist_for_each_entry(st, &lockhash_table[i], hash_entry) {
1556 			insert_to_result(st, compare);
1557 		}
1558 	}
1559 }
1560 
1561 static const struct {
1562 	unsigned int flags;
1563 	const char *str;
1564 	const char *name;
1565 } lock_type_table[] = {
1566 	{ 0,				"semaphore",	"semaphore" },
1567 	{ LCB_F_SPIN,			"spinlock",	"spinlock" },
1568 	{ LCB_F_SPIN | LCB_F_READ,	"rwlock:R",	"rwlock" },
1569 	{ LCB_F_SPIN | LCB_F_WRITE,	"rwlock:W",	"rwlock" },
1570 	{ LCB_F_READ,			"rwsem:R",	"rwsem" },
1571 	{ LCB_F_WRITE,			"rwsem:W",	"rwsem" },
1572 	{ LCB_F_RT,			"rt-mutex",	"rt-mutex" },
1573 	{ LCB_F_RT | LCB_F_READ,	"rwlock-rt:R",	"rwlock-rt" },
1574 	{ LCB_F_RT | LCB_F_WRITE,	"rwlock-rt:W",	"rwlock-rt" },
1575 	{ LCB_F_PERCPU | LCB_F_READ,	"pcpu-sem:R",	"percpu-rwsem" },
1576 	{ LCB_F_PERCPU | LCB_F_WRITE,	"pcpu-sem:W",	"percpu-rwsem" },
1577 	{ LCB_F_MUTEX,			"mutex",	"mutex" },
1578 	{ LCB_F_MUTEX | LCB_F_SPIN,	"mutex",	"mutex" },
1579 	/* alias for get_type_flag() */
1580 	{ LCB_F_MUTEX | LCB_F_SPIN,	"mutex-spin",	"mutex" },
1581 };
1582 
1583 static const char *get_type_str(unsigned int flags)
1584 {
1585 	flags &= LCB_F_MAX_FLAGS - 1;
1586 
1587 	for (unsigned int i = 0; i < ARRAY_SIZE(lock_type_table); i++) {
1588 		if (lock_type_table[i].flags == flags)
1589 			return lock_type_table[i].str;
1590 	}
1591 	return "unknown";
1592 }
1593 
1594 static const char *get_type_name(unsigned int flags)
1595 {
1596 	flags &= LCB_F_MAX_FLAGS - 1;
1597 
1598 	for (unsigned int i = 0; i < ARRAY_SIZE(lock_type_table); i++) {
1599 		if (lock_type_table[i].flags == flags)
1600 			return lock_type_table[i].name;
1601 	}
1602 	return "unknown";
1603 }
1604 
1605 static unsigned int get_type_flag(const char *str)
1606 {
1607 	for (unsigned int i = 0; i < ARRAY_SIZE(lock_type_table); i++) {
1608 		if (!strcmp(lock_type_table[i].name, str))
1609 			return lock_type_table[i].flags;
1610 	}
1611 	for (unsigned int i = 0; i < ARRAY_SIZE(lock_type_table); i++) {
1612 		if (!strcmp(lock_type_table[i].str, str))
1613 			return lock_type_table[i].flags;
1614 	}
1615 	return UINT_MAX;
1616 }
1617 
1618 static void lock_filter_finish(void)
1619 {
1620 	zfree(&filters.types);
1621 	filters.nr_types = 0;
1622 
1623 	zfree(&filters.addrs);
1624 	filters.nr_addrs = 0;
1625 
1626 	for (int i = 0; i < filters.nr_syms; i++)
1627 		free(filters.syms[i]);
1628 
1629 	zfree(&filters.syms);
1630 	filters.nr_syms = 0;
1631 }
1632 
1633 static void sort_contention_result(void)
1634 {
1635 	sort_result();
1636 }
1637 
1638 static void print_header_stdio(void)
1639 {
1640 	struct lock_key *key;
1641 
1642 	list_for_each_entry(key, &lock_keys, list)
1643 		fprintf(lock_output, "%*s ", key->len, key->header);
1644 
1645 	switch (aggr_mode) {
1646 	case LOCK_AGGR_TASK:
1647 		fprintf(lock_output, "  %10s   %s\n\n", "pid",
1648 			show_lock_owner ? "owner" : "comm");
1649 		break;
1650 	case LOCK_AGGR_CALLER:
1651 		fprintf(lock_output, "  %10s   %s\n\n", "type", "caller");
1652 		break;
1653 	case LOCK_AGGR_ADDR:
1654 		fprintf(lock_output, "  %16s   %s\n\n", "address", "symbol");
1655 		break;
1656 	default:
1657 		break;
1658 	}
1659 }
1660 
1661 static void print_header_csv(const char *sep)
1662 {
1663 	struct lock_key *key;
1664 
1665 	fprintf(lock_output, "# output: ");
1666 	list_for_each_entry(key, &lock_keys, list)
1667 		fprintf(lock_output, "%s%s ", key->header, sep);
1668 
1669 	switch (aggr_mode) {
1670 	case LOCK_AGGR_TASK:
1671 		fprintf(lock_output, "%s%s %s\n", "pid", sep,
1672 			show_lock_owner ? "owner" : "comm");
1673 		break;
1674 	case LOCK_AGGR_CALLER:
1675 		fprintf(lock_output, "%s%s %s", "type", sep, "caller");
1676 		if (verbose > 0)
1677 			fprintf(lock_output, "%s %s", sep, "stacktrace");
1678 		fprintf(lock_output, "\n");
1679 		break;
1680 	case LOCK_AGGR_ADDR:
1681 		fprintf(lock_output, "%s%s %s%s %s\n", "address", sep, "symbol", sep, "type");
1682 		break;
1683 	default:
1684 		break;
1685 	}
1686 }
1687 
1688 static void print_header(void)
1689 {
1690 	if (!quiet) {
1691 		if (symbol_conf.field_sep)
1692 			print_header_csv(symbol_conf.field_sep);
1693 		else
1694 			print_header_stdio();
1695 	}
1696 }
1697 
1698 static void print_lock_stat_stdio(struct lock_contention *con, struct lock_stat *st)
1699 {
1700 	struct lock_key *key;
1701 	struct thread *t;
1702 	int pid;
1703 
1704 	list_for_each_entry(key, &lock_keys, list) {
1705 		key->print(key, st);
1706 		fprintf(lock_output, " ");
1707 	}
1708 
1709 	switch (aggr_mode) {
1710 	case LOCK_AGGR_CALLER:
1711 		fprintf(lock_output, "  %10s   %s\n", get_type_str(st->flags), st->name);
1712 		break;
1713 	case LOCK_AGGR_TASK:
1714 		pid = st->addr;
1715 		t = perf_session__findnew(session, pid);
1716 		fprintf(lock_output, "  %10d   %s\n",
1717 			pid, pid == -1 ? "Unknown" : thread__comm_str(t));
1718 		break;
1719 	case LOCK_AGGR_ADDR:
1720 		fprintf(lock_output, "  %016llx   %s (%s)\n", (unsigned long long)st->addr,
1721 			st->name, get_type_name(st->flags));
1722 		break;
1723 	default:
1724 		break;
1725 	}
1726 
1727 	if (aggr_mode == LOCK_AGGR_CALLER && verbose > 0) {
1728 		struct map *kmap;
1729 		struct symbol *sym;
1730 		char buf[128];
1731 		u64 ip;
1732 
1733 		for (int i = 0; i < max_stack_depth; i++) {
1734 			if (!st->callstack || !st->callstack[i])
1735 				break;
1736 
1737 			ip = st->callstack[i];
1738 			sym = machine__find_kernel_symbol(con->machine, ip, &kmap);
1739 			get_symbol_name_offset(kmap, sym, ip, buf, sizeof(buf));
1740 			fprintf(lock_output, "\t\t\t%#lx  %s\n", (unsigned long)ip, buf);
1741 		}
1742 	}
1743 }
1744 
1745 static void print_lock_stat_csv(struct lock_contention *con, struct lock_stat *st,
1746 				const char *sep)
1747 {
1748 	struct lock_key *key;
1749 	struct thread *t;
1750 	int pid;
1751 
1752 	list_for_each_entry(key, &lock_keys, list) {
1753 		key->print(key, st);
1754 		fprintf(lock_output, "%s ", sep);
1755 	}
1756 
1757 	switch (aggr_mode) {
1758 	case LOCK_AGGR_CALLER:
1759 		fprintf(lock_output, "%s%s %s", get_type_str(st->flags), sep, st->name);
1760 		if (verbose <= 0)
1761 			fprintf(lock_output, "\n");
1762 		break;
1763 	case LOCK_AGGR_TASK:
1764 		pid = st->addr;
1765 		t = perf_session__findnew(session, pid);
1766 		fprintf(lock_output, "%d%s %s\n", pid, sep,
1767 			pid == -1 ? "Unknown" : thread__comm_str(t));
1768 		break;
1769 	case LOCK_AGGR_ADDR:
1770 		fprintf(lock_output, "%llx%s %s%s %s\n", (unsigned long long)st->addr, sep,
1771 			st->name, sep, get_type_name(st->flags));
1772 		break;
1773 	default:
1774 		break;
1775 	}
1776 
1777 	if (aggr_mode == LOCK_AGGR_CALLER && verbose > 0) {
1778 		struct map *kmap;
1779 		struct symbol *sym;
1780 		char buf[128];
1781 		u64 ip;
1782 
1783 		for (int i = 0; i < max_stack_depth; i++) {
1784 			if (!st->callstack || !st->callstack[i])
1785 				break;
1786 
1787 			ip = st->callstack[i];
1788 			sym = machine__find_kernel_symbol(con->machine, ip, &kmap);
1789 			get_symbol_name_offset(kmap, sym, ip, buf, sizeof(buf));
1790 			fprintf(lock_output, "%s %#lx %s", i ? ":" : sep, (unsigned long) ip, buf);
1791 		}
1792 		fprintf(lock_output, "\n");
1793 	}
1794 }
1795 
1796 static void print_lock_stat(struct lock_contention *con, struct lock_stat *st)
1797 {
1798 	if (symbol_conf.field_sep)
1799 		print_lock_stat_csv(con, st, symbol_conf.field_sep);
1800 	else
1801 		print_lock_stat_stdio(con, st);
1802 }
1803 
1804 static void print_footer_stdio(int total, int bad, struct lock_contention_fails *fails)
1805 {
1806 	/* Output for debug, this have to be removed */
1807 	int broken = fails->task + fails->stack + fails->time + fails->data;
1808 
1809 	if (!use_bpf)
1810 		print_bad_events(bad, total);
1811 
1812 	if (quiet || total == 0 || (broken == 0 && verbose <= 0))
1813 		return;
1814 
1815 	total += broken;
1816 	fprintf(lock_output, "\n=== output for debug ===\n\n");
1817 	fprintf(lock_output, "bad: %d, total: %d\n", broken, total);
1818 	fprintf(lock_output, "bad rate: %.2f %%\n", 100.0 * broken / total);
1819 
1820 	fprintf(lock_output, "histogram of failure reasons\n");
1821 	fprintf(lock_output, " %10s: %d\n", "task", fails->task);
1822 	fprintf(lock_output, " %10s: %d\n", "stack", fails->stack);
1823 	fprintf(lock_output, " %10s: %d\n", "time", fails->time);
1824 	fprintf(lock_output, " %10s: %d\n", "data", fails->data);
1825 }
1826 
1827 static void print_footer_csv(int total, int bad, struct lock_contention_fails *fails,
1828 			     const char *sep)
1829 {
1830 	/* Output for debug, this have to be removed */
1831 	if (use_bpf)
1832 		bad = fails->task + fails->stack + fails->time + fails->data;
1833 
1834 	if (quiet || total == 0 || (bad == 0 && verbose <= 0))
1835 		return;
1836 
1837 	total += bad;
1838 	fprintf(lock_output, "# debug: total=%d%s bad=%d", total, sep, bad);
1839 
1840 	if (use_bpf) {
1841 		fprintf(lock_output, "%s bad_%s=%d", sep, "task", fails->task);
1842 		fprintf(lock_output, "%s bad_%s=%d", sep, "stack", fails->stack);
1843 		fprintf(lock_output, "%s bad_%s=%d", sep, "time", fails->time);
1844 		fprintf(lock_output, "%s bad_%s=%d", sep, "data", fails->data);
1845 	} else {
1846 		int i;
1847 		const char *name[4] = { "acquire", "acquired", "contended", "release" };
1848 
1849 		for (i = 0; i < BROKEN_MAX; i++)
1850 			fprintf(lock_output, "%s bad_%s=%d", sep, name[i], bad_hist[i]);
1851 	}
1852 	fprintf(lock_output, "\n");
1853 }
1854 
1855 static void print_footer(int total, int bad, struct lock_contention_fails *fails)
1856 {
1857 	if (symbol_conf.field_sep)
1858 		print_footer_csv(total, bad, fails, symbol_conf.field_sep);
1859 	else
1860 		print_footer_stdio(total, bad, fails);
1861 }
1862 
1863 static void print_contention_result(struct lock_contention *con)
1864 {
1865 	struct lock_stat *st;
1866 	int bad, total, printed;
1867 
1868 	if (!quiet)
1869 		print_header();
1870 
1871 	bad = total = printed = 0;
1872 
1873 	while ((st = pop_from_result())) {
1874 		total += use_bpf ? st->nr_contended : 1;
1875 		if (st->broken)
1876 			bad++;
1877 
1878 		if (!st->wait_time_total)
1879 			continue;
1880 
1881 		print_lock_stat(con, st);
1882 
1883 		if (++printed >= print_nr_entries)
1884 			break;
1885 	}
1886 
1887 	if (print_nr_entries) {
1888 		/* update the total/bad stats */
1889 		while ((st = pop_from_result())) {
1890 			total += use_bpf ? st->nr_contended : 1;
1891 			if (st->broken)
1892 				bad++;
1893 		}
1894 	}
1895 	/* some entries are collected but hidden by the callstack filter */
1896 	total += con->nr_filtered;
1897 
1898 	print_footer(total, bad, &con->fails);
1899 }
1900 
1901 static bool force;
1902 
1903 static int __cmd_report(bool display_info)
1904 {
1905 	int err = -EINVAL;
1906 	struct perf_tool eops = {
1907 		.attr		 = perf_event__process_attr,
1908 		.event_update	 = process_event_update,
1909 		.sample		 = process_sample_event,
1910 		.comm		 = perf_event__process_comm,
1911 		.mmap		 = perf_event__process_mmap,
1912 		.namespaces	 = perf_event__process_namespaces,
1913 		.tracing_data	 = perf_event__process_tracing_data,
1914 		.ordered_events	 = true,
1915 	};
1916 	struct perf_data data = {
1917 		.path  = input_name,
1918 		.mode  = PERF_DATA_MODE_READ,
1919 		.force = force,
1920 	};
1921 
1922 	session = perf_session__new(&data, &eops);
1923 	if (IS_ERR(session)) {
1924 		pr_err("Initializing perf session failed\n");
1925 		return PTR_ERR(session);
1926 	}
1927 
1928 	symbol_conf.allow_aliases = true;
1929 	symbol__init(&session->header.env);
1930 
1931 	if (!data.is_pipe) {
1932 		if (!perf_session__has_traces(session, "lock record"))
1933 			goto out_delete;
1934 
1935 		if (perf_session__set_tracepoints_handlers(session, lock_tracepoints)) {
1936 			pr_err("Initializing perf session tracepoint handlers failed\n");
1937 			goto out_delete;
1938 		}
1939 
1940 		if (perf_session__set_tracepoints_handlers(session, contention_tracepoints)) {
1941 			pr_err("Initializing perf session tracepoint handlers failed\n");
1942 			goto out_delete;
1943 		}
1944 	}
1945 
1946 	if (setup_output_field(false, output_fields))
1947 		goto out_delete;
1948 
1949 	if (select_key(false))
1950 		goto out_delete;
1951 
1952 	if (show_thread_stats)
1953 		aggr_mode = LOCK_AGGR_TASK;
1954 
1955 	err = perf_session__process_events(session);
1956 	if (err)
1957 		goto out_delete;
1958 
1959 	setup_pager();
1960 	if (display_info) /* used for info subcommand */
1961 		err = dump_info();
1962 	else {
1963 		combine_result();
1964 		sort_result();
1965 		print_result();
1966 	}
1967 
1968 out_delete:
1969 	perf_session__delete(session);
1970 	return err;
1971 }
1972 
1973 static void sighandler(int sig __maybe_unused)
1974 {
1975 }
1976 
1977 static int check_lock_contention_options(const struct option *options,
1978 					 const char * const *usage)
1979 
1980 {
1981 	if (show_thread_stats && show_lock_addrs) {
1982 		pr_err("Cannot use thread and addr mode together\n");
1983 		parse_options_usage(usage, options, "threads", 0);
1984 		parse_options_usage(NULL, options, "lock-addr", 0);
1985 		return -1;
1986 	}
1987 
1988 	if (show_lock_owner && !use_bpf) {
1989 		pr_err("Lock owners are available only with BPF\n");
1990 		parse_options_usage(usage, options, "lock-owner", 0);
1991 		parse_options_usage(NULL, options, "use-bpf", 0);
1992 		return -1;
1993 	}
1994 
1995 	if (show_lock_owner && show_lock_addrs) {
1996 		pr_err("Cannot use owner and addr mode together\n");
1997 		parse_options_usage(usage, options, "lock-owner", 0);
1998 		parse_options_usage(NULL, options, "lock-addr", 0);
1999 		return -1;
2000 	}
2001 
2002 	if (symbol_conf.field_sep) {
2003 		if (strstr(symbol_conf.field_sep, ":") || /* part of type flags */
2004 		    strstr(symbol_conf.field_sep, "+") || /* part of caller offset */
2005 		    strstr(symbol_conf.field_sep, ".")) { /* can be in a symbol name */
2006 			pr_err("Cannot use the separator that is already used\n");
2007 			parse_options_usage(usage, options, "x", 1);
2008 			return -1;
2009 		}
2010 	}
2011 
2012 	if (show_lock_owner)
2013 		show_thread_stats = true;
2014 
2015 	return 0;
2016 }
2017 
2018 static int __cmd_contention(int argc, const char **argv)
2019 {
2020 	int err = -EINVAL;
2021 	struct perf_tool eops = {
2022 		.attr		 = perf_event__process_attr,
2023 		.event_update	 = process_event_update,
2024 		.sample		 = process_sample_event,
2025 		.comm		 = perf_event__process_comm,
2026 		.mmap		 = perf_event__process_mmap,
2027 		.tracing_data	 = perf_event__process_tracing_data,
2028 		.ordered_events	 = true,
2029 	};
2030 	struct perf_data data = {
2031 		.path  = input_name,
2032 		.mode  = PERF_DATA_MODE_READ,
2033 		.force = force,
2034 	};
2035 	struct lock_contention con = {
2036 		.target = &target,
2037 		.map_nr_entries = bpf_map_entries,
2038 		.max_stack = max_stack_depth,
2039 		.stack_skip = stack_skip,
2040 		.filters = &filters,
2041 		.save_callstack = needs_callstack(),
2042 		.owner = show_lock_owner,
2043 	};
2044 
2045 	lockhash_table = calloc(LOCKHASH_SIZE, sizeof(*lockhash_table));
2046 	if (!lockhash_table)
2047 		return -ENOMEM;
2048 
2049 	con.result = &lockhash_table[0];
2050 
2051 	session = perf_session__new(use_bpf ? NULL : &data, &eops);
2052 	if (IS_ERR(session)) {
2053 		pr_err("Initializing perf session failed\n");
2054 		err = PTR_ERR(session);
2055 		goto out_delete;
2056 	}
2057 
2058 	con.machine = &session->machines.host;
2059 
2060 	con.aggr_mode = aggr_mode = show_thread_stats ? LOCK_AGGR_TASK :
2061 		show_lock_addrs ? LOCK_AGGR_ADDR : LOCK_AGGR_CALLER;
2062 
2063 	if (con.aggr_mode == LOCK_AGGR_CALLER)
2064 		con.save_callstack = true;
2065 
2066 	symbol_conf.allow_aliases = true;
2067 	symbol__init(&session->header.env);
2068 
2069 	if (use_bpf) {
2070 		err = target__validate(&target);
2071 		if (err) {
2072 			char errbuf[512];
2073 
2074 			target__strerror(&target, err, errbuf, 512);
2075 			pr_err("%s\n", errbuf);
2076 			goto out_delete;
2077 		}
2078 
2079 		signal(SIGINT, sighandler);
2080 		signal(SIGCHLD, sighandler);
2081 		signal(SIGTERM, sighandler);
2082 
2083 		con.evlist = evlist__new();
2084 		if (con.evlist == NULL) {
2085 			err = -ENOMEM;
2086 			goto out_delete;
2087 		}
2088 
2089 		err = evlist__create_maps(con.evlist, &target);
2090 		if (err < 0)
2091 			goto out_delete;
2092 
2093 		if (argc) {
2094 			err = evlist__prepare_workload(con.evlist, &target,
2095 						       argv, false, NULL);
2096 			if (err < 0)
2097 				goto out_delete;
2098 		}
2099 
2100 		if (lock_contention_prepare(&con) < 0) {
2101 			pr_err("lock contention BPF setup failed\n");
2102 			goto out_delete;
2103 		}
2104 	} else if (!data.is_pipe) {
2105 		if (!perf_session__has_traces(session, "lock record"))
2106 			goto out_delete;
2107 
2108 		if (!evlist__find_evsel_by_str(session->evlist,
2109 					       "lock:contention_begin")) {
2110 			pr_err("lock contention evsel not found\n");
2111 			goto out_delete;
2112 		}
2113 
2114 		if (perf_session__set_tracepoints_handlers(session,
2115 						contention_tracepoints)) {
2116 			pr_err("Initializing perf session tracepoint handlers failed\n");
2117 			goto out_delete;
2118 		}
2119 	}
2120 
2121 	if (setup_output_field(true, output_fields))
2122 		goto out_delete;
2123 
2124 	if (select_key(true))
2125 		goto out_delete;
2126 
2127 	if (symbol_conf.field_sep) {
2128 		int i;
2129 		struct lock_key *keys = contention_keys;
2130 
2131 		/* do not align output in CSV format */
2132 		for (i = 0; keys[i].name; i++)
2133 			keys[i].len = 0;
2134 	}
2135 
2136 	if (use_bpf) {
2137 		lock_contention_start();
2138 		if (argc)
2139 			evlist__start_workload(con.evlist);
2140 
2141 		/* wait for signal */
2142 		pause();
2143 
2144 		lock_contention_stop();
2145 		lock_contention_read(&con);
2146 	} else {
2147 		err = perf_session__process_events(session);
2148 		if (err)
2149 			goto out_delete;
2150 	}
2151 
2152 	setup_pager();
2153 
2154 	sort_contention_result();
2155 	print_contention_result(&con);
2156 
2157 out_delete:
2158 	lock_filter_finish();
2159 	evlist__delete(con.evlist);
2160 	lock_contention_finish();
2161 	perf_session__delete(session);
2162 	zfree(&lockhash_table);
2163 	return err;
2164 }
2165 
2166 
2167 static int __cmd_record(int argc, const char **argv)
2168 {
2169 	const char *record_args[] = {
2170 		"record", "-R", "-m", "1024", "-c", "1", "--synth", "task",
2171 	};
2172 	const char *callgraph_args[] = {
2173 		"--call-graph", "fp," __stringify(CONTENTION_STACK_DEPTH),
2174 	};
2175 	unsigned int rec_argc, i, j, ret;
2176 	unsigned int nr_tracepoints;
2177 	unsigned int nr_callgraph_args = 0;
2178 	const char **rec_argv;
2179 	bool has_lock_stat = true;
2180 
2181 	for (i = 0; i < ARRAY_SIZE(lock_tracepoints); i++) {
2182 		if (!is_valid_tracepoint(lock_tracepoints[i].name)) {
2183 			pr_debug("tracepoint %s is not enabled. "
2184 				 "Are CONFIG_LOCKDEP and CONFIG_LOCK_STAT enabled?\n",
2185 				 lock_tracepoints[i].name);
2186 			has_lock_stat = false;
2187 			break;
2188 		}
2189 	}
2190 
2191 	if (has_lock_stat)
2192 		goto setup_args;
2193 
2194 	for (i = 0; i < ARRAY_SIZE(contention_tracepoints); i++) {
2195 		if (!is_valid_tracepoint(contention_tracepoints[i].name)) {
2196 			pr_err("tracepoint %s is not enabled.\n",
2197 			       contention_tracepoints[i].name);
2198 			return 1;
2199 		}
2200 	}
2201 
2202 	nr_callgraph_args = ARRAY_SIZE(callgraph_args);
2203 
2204 setup_args:
2205 	rec_argc = ARRAY_SIZE(record_args) + nr_callgraph_args + argc - 1;
2206 
2207 	if (has_lock_stat)
2208 		nr_tracepoints = ARRAY_SIZE(lock_tracepoints);
2209 	else
2210 		nr_tracepoints = ARRAY_SIZE(contention_tracepoints);
2211 
2212 	/* factor of 2 is for -e in front of each tracepoint */
2213 	rec_argc += 2 * nr_tracepoints;
2214 
2215 	rec_argv = calloc(rec_argc + 1, sizeof(char *));
2216 	if (!rec_argv)
2217 		return -ENOMEM;
2218 
2219 	for (i = 0; i < ARRAY_SIZE(record_args); i++)
2220 		rec_argv[i] = strdup(record_args[i]);
2221 
2222 	for (j = 0; j < nr_tracepoints; j++) {
2223 		const char *ev_name;
2224 
2225 		if (has_lock_stat)
2226 			ev_name = strdup(lock_tracepoints[j].name);
2227 		else
2228 			ev_name = strdup(contention_tracepoints[j].name);
2229 
2230 		if (!ev_name)
2231 			return -ENOMEM;
2232 
2233 		rec_argv[i++] = "-e";
2234 		rec_argv[i++] = ev_name;
2235 	}
2236 
2237 	for (j = 0; j < nr_callgraph_args; j++, i++)
2238 		rec_argv[i] = callgraph_args[j];
2239 
2240 	for (j = 1; j < (unsigned int)argc; j++, i++)
2241 		rec_argv[i] = argv[j];
2242 
2243 	BUG_ON(i != rec_argc);
2244 
2245 	ret = cmd_record(i, rec_argv);
2246 	free(rec_argv);
2247 	return ret;
2248 }
2249 
2250 static int parse_map_entry(const struct option *opt, const char *str,
2251 			    int unset __maybe_unused)
2252 {
2253 	unsigned long *len = (unsigned long *)opt->value;
2254 	unsigned long val;
2255 	char *endptr;
2256 
2257 	errno = 0;
2258 	val = strtoul(str, &endptr, 0);
2259 	if (*endptr != '\0' || errno != 0) {
2260 		pr_err("invalid BPF map length: %s\n", str);
2261 		return -1;
2262 	}
2263 
2264 	*len = val;
2265 	return 0;
2266 }
2267 
2268 static int parse_max_stack(const struct option *opt, const char *str,
2269 			   int unset __maybe_unused)
2270 {
2271 	unsigned long *len = (unsigned long *)opt->value;
2272 	long val;
2273 	char *endptr;
2274 
2275 	errno = 0;
2276 	val = strtol(str, &endptr, 0);
2277 	if (*endptr != '\0' || errno != 0) {
2278 		pr_err("invalid max stack depth: %s\n", str);
2279 		return -1;
2280 	}
2281 
2282 	if (val < 0 || val > sysctl__max_stack()) {
2283 		pr_err("invalid max stack depth: %ld\n", val);
2284 		return -1;
2285 	}
2286 
2287 	*len = val;
2288 	return 0;
2289 }
2290 
2291 static bool add_lock_type(unsigned int flags)
2292 {
2293 	unsigned int *tmp;
2294 
2295 	tmp = realloc(filters.types, (filters.nr_types + 1) * sizeof(*filters.types));
2296 	if (tmp == NULL)
2297 		return false;
2298 
2299 	tmp[filters.nr_types++] = flags;
2300 	filters.types = tmp;
2301 	return true;
2302 }
2303 
2304 static int parse_lock_type(const struct option *opt __maybe_unused, const char *str,
2305 			   int unset __maybe_unused)
2306 {
2307 	char *s, *tmp, *tok;
2308 	int ret = 0;
2309 
2310 	s = strdup(str);
2311 	if (s == NULL)
2312 		return -1;
2313 
2314 	for (tok = strtok_r(s, ", ", &tmp); tok; tok = strtok_r(NULL, ", ", &tmp)) {
2315 		unsigned int flags = get_type_flag(tok);
2316 
2317 		if (flags == -1U) {
2318 			pr_err("Unknown lock flags: %s\n", tok);
2319 			ret = -1;
2320 			break;
2321 		}
2322 
2323 		if (!add_lock_type(flags)) {
2324 			ret = -1;
2325 			break;
2326 		}
2327 	}
2328 
2329 	free(s);
2330 	return ret;
2331 }
2332 
2333 static bool add_lock_addr(unsigned long addr)
2334 {
2335 	unsigned long *tmp;
2336 
2337 	tmp = realloc(filters.addrs, (filters.nr_addrs + 1) * sizeof(*filters.addrs));
2338 	if (tmp == NULL) {
2339 		pr_err("Memory allocation failure\n");
2340 		return false;
2341 	}
2342 
2343 	tmp[filters.nr_addrs++] = addr;
2344 	filters.addrs = tmp;
2345 	return true;
2346 }
2347 
2348 static bool add_lock_sym(char *name)
2349 {
2350 	char **tmp;
2351 	char *sym = strdup(name);
2352 
2353 	if (sym == NULL) {
2354 		pr_err("Memory allocation failure\n");
2355 		return false;
2356 	}
2357 
2358 	tmp = realloc(filters.syms, (filters.nr_syms + 1) * sizeof(*filters.syms));
2359 	if (tmp == NULL) {
2360 		pr_err("Memory allocation failure\n");
2361 		free(sym);
2362 		return false;
2363 	}
2364 
2365 	tmp[filters.nr_syms++] = sym;
2366 	filters.syms = tmp;
2367 	return true;
2368 }
2369 
2370 static int parse_lock_addr(const struct option *opt __maybe_unused, const char *str,
2371 			   int unset __maybe_unused)
2372 {
2373 	char *s, *tmp, *tok;
2374 	int ret = 0;
2375 	u64 addr;
2376 
2377 	s = strdup(str);
2378 	if (s == NULL)
2379 		return -1;
2380 
2381 	for (tok = strtok_r(s, ", ", &tmp); tok; tok = strtok_r(NULL, ", ", &tmp)) {
2382 		char *end;
2383 
2384 		addr = strtoul(tok, &end, 16);
2385 		if (*end == '\0') {
2386 			if (!add_lock_addr(addr)) {
2387 				ret = -1;
2388 				break;
2389 			}
2390 			continue;
2391 		}
2392 
2393 		/*
2394 		 * At this moment, we don't have kernel symbols.  Save the symbols
2395 		 * in a separate list and resolve them to addresses later.
2396 		 */
2397 		if (!add_lock_sym(tok)) {
2398 			ret = -1;
2399 			break;
2400 		}
2401 	}
2402 
2403 	free(s);
2404 	return ret;
2405 }
2406 
2407 static int parse_call_stack(const struct option *opt __maybe_unused, const char *str,
2408 			   int unset __maybe_unused)
2409 {
2410 	char *s, *tmp, *tok;
2411 	int ret = 0;
2412 
2413 	s = strdup(str);
2414 	if (s == NULL)
2415 		return -1;
2416 
2417 	for (tok = strtok_r(s, ", ", &tmp); tok; tok = strtok_r(NULL, ", ", &tmp)) {
2418 		struct callstack_filter *entry;
2419 
2420 		entry = malloc(sizeof(*entry) + strlen(tok) + 1);
2421 		if (entry == NULL) {
2422 			pr_err("Memory allocation failure\n");
2423 			return -1;
2424 		}
2425 
2426 		strcpy(entry->name, tok);
2427 		list_add_tail(&entry->list, &callstack_filters);
2428 	}
2429 
2430 	free(s);
2431 	return ret;
2432 }
2433 
2434 static int parse_output(const struct option *opt __maybe_unused, const char *str,
2435 			int unset __maybe_unused)
2436 {
2437 	const char **name = (const char **)opt->value;
2438 
2439 	if (str == NULL)
2440 		return -1;
2441 
2442 	lock_output = fopen(str, "w");
2443 	if (lock_output == NULL) {
2444 		pr_err("Cannot open %s\n", str);
2445 		return -1;
2446 	}
2447 
2448 	*name = str;
2449 	return 0;
2450 }
2451 
2452 int cmd_lock(int argc, const char **argv)
2453 {
2454 	const struct option lock_options[] = {
2455 	OPT_STRING('i', "input", &input_name, "file", "input file name"),
2456 	OPT_CALLBACK(0, "output", &output_name, "file", "output file name", parse_output),
2457 	OPT_INCR('v', "verbose", &verbose, "be more verbose (show symbol address, etc)"),
2458 	OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, "dump raw trace in ASCII"),
2459 	OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
2460 	OPT_STRING(0, "vmlinux", &symbol_conf.vmlinux_name,
2461 		   "file", "vmlinux pathname"),
2462 	OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
2463 		   "file", "kallsyms pathname"),
2464 	OPT_BOOLEAN('q', "quiet", &quiet, "Do not show any warnings or messages"),
2465 	OPT_END()
2466 	};
2467 
2468 	const struct option info_options[] = {
2469 	OPT_BOOLEAN('t', "threads", &info_threads,
2470 		    "dump thread list in perf.data"),
2471 	OPT_BOOLEAN('m', "map", &info_map,
2472 		    "map of lock instances (address:name table)"),
2473 	OPT_PARENT(lock_options)
2474 	};
2475 
2476 	const struct option report_options[] = {
2477 	OPT_STRING('k', "key", &sort_key, "acquired",
2478 		    "key for sorting (acquired / contended / avg_wait / wait_total / wait_max / wait_min)"),
2479 	OPT_STRING('F', "field", &output_fields, NULL,
2480 		    "output fields (acquired / contended / avg_wait / wait_total / wait_max / wait_min)"),
2481 	/* TODO: type */
2482 	OPT_BOOLEAN('c', "combine-locks", &combine_locks,
2483 		    "combine locks in the same class"),
2484 	OPT_BOOLEAN('t', "threads", &show_thread_stats,
2485 		    "show per-thread lock stats"),
2486 	OPT_INTEGER('E', "entries", &print_nr_entries, "display this many functions"),
2487 	OPT_PARENT(lock_options)
2488 	};
2489 
2490 	struct option contention_options[] = {
2491 	OPT_STRING('k', "key", &sort_key, "wait_total",
2492 		    "key for sorting (contended / wait_total / wait_max / wait_min / avg_wait)"),
2493 	OPT_STRING('F', "field", &output_fields, "contended,wait_total,wait_max,avg_wait",
2494 		    "output fields (contended / wait_total / wait_max / wait_min / avg_wait)"),
2495 	OPT_BOOLEAN('t', "threads", &show_thread_stats,
2496 		    "show per-thread lock stats"),
2497 	OPT_BOOLEAN('b', "use-bpf", &use_bpf, "use BPF program to collect lock contention stats"),
2498 	OPT_BOOLEAN('a', "all-cpus", &target.system_wide,
2499 		    "System-wide collection from all CPUs"),
2500 	OPT_STRING('C', "cpu", &target.cpu_list, "cpu",
2501 		    "List of cpus to monitor"),
2502 	OPT_STRING('p', "pid", &target.pid, "pid",
2503 		   "Trace on existing process id"),
2504 	OPT_STRING(0, "tid", &target.tid, "tid",
2505 		   "Trace on existing thread id (exclusive to --pid)"),
2506 	OPT_CALLBACK('M', "map-nr-entries", &bpf_map_entries, "num",
2507 		     "Max number of BPF map entries", parse_map_entry),
2508 	OPT_CALLBACK(0, "max-stack", &max_stack_depth, "num",
2509 		     "Set the maximum stack depth when collecting lopck contention, "
2510 		     "Default: " __stringify(CONTENTION_STACK_DEPTH), parse_max_stack),
2511 	OPT_INTEGER(0, "stack-skip", &stack_skip,
2512 		    "Set the number of stack depth to skip when finding a lock caller, "
2513 		    "Default: " __stringify(CONTENTION_STACK_SKIP)),
2514 	OPT_INTEGER('E', "entries", &print_nr_entries, "display this many functions"),
2515 	OPT_BOOLEAN('l', "lock-addr", &show_lock_addrs, "show lock stats by address"),
2516 	OPT_CALLBACK('Y', "type-filter", NULL, "FLAGS",
2517 		     "Filter specific type of locks", parse_lock_type),
2518 	OPT_CALLBACK('L', "lock-filter", NULL, "ADDRS/NAMES",
2519 		     "Filter specific address/symbol of locks", parse_lock_addr),
2520 	OPT_CALLBACK('S', "callstack-filter", NULL, "NAMES",
2521 		     "Filter specific function in the callstack", parse_call_stack),
2522 	OPT_BOOLEAN('o', "lock-owner", &show_lock_owner, "show lock owners instead of waiters"),
2523 	OPT_STRING_NOEMPTY('x', "field-separator", &symbol_conf.field_sep, "separator",
2524 		   "print result in CSV format with custom separator"),
2525 	OPT_PARENT(lock_options)
2526 	};
2527 
2528 	const char * const info_usage[] = {
2529 		"perf lock info [<options>]",
2530 		NULL
2531 	};
2532 	const char *const lock_subcommands[] = { "record", "report", "script",
2533 						 "info", "contention", NULL };
2534 	const char *lock_usage[] = {
2535 		NULL,
2536 		NULL
2537 	};
2538 	const char * const report_usage[] = {
2539 		"perf lock report [<options>]",
2540 		NULL
2541 	};
2542 	const char * const contention_usage[] = {
2543 		"perf lock contention [<options>]",
2544 		NULL
2545 	};
2546 	unsigned int i;
2547 	int rc = 0;
2548 
2549 	lockhash_table = calloc(LOCKHASH_SIZE, sizeof(*lockhash_table));
2550 	if (!lockhash_table)
2551 		return -ENOMEM;
2552 
2553 	for (i = 0; i < LOCKHASH_SIZE; i++)
2554 		INIT_HLIST_HEAD(lockhash_table + i);
2555 
2556 	lock_output = stderr;
2557 	argc = parse_options_subcommand(argc, argv, lock_options, lock_subcommands,
2558 					lock_usage, PARSE_OPT_STOP_AT_NON_OPTION);
2559 	if (!argc)
2560 		usage_with_options(lock_usage, lock_options);
2561 
2562 	if (strlen(argv[0]) > 2 && strstarts("record", argv[0])) {
2563 		return __cmd_record(argc, argv);
2564 	} else if (strlen(argv[0]) > 2 && strstarts("report", argv[0])) {
2565 		trace_handler = &report_lock_ops;
2566 		if (argc) {
2567 			argc = parse_options(argc, argv,
2568 					     report_options, report_usage, 0);
2569 			if (argc)
2570 				usage_with_options(report_usage, report_options);
2571 		}
2572 		rc = __cmd_report(false);
2573 	} else if (!strcmp(argv[0], "script")) {
2574 		/* Aliased to 'perf script' */
2575 		rc = cmd_script(argc, argv);
2576 	} else if (!strcmp(argv[0], "info")) {
2577 		if (argc) {
2578 			argc = parse_options(argc, argv,
2579 					     info_options, info_usage, 0);
2580 			if (argc)
2581 				usage_with_options(info_usage, info_options);
2582 		}
2583 		/* recycling report_lock_ops */
2584 		trace_handler = &report_lock_ops;
2585 		rc = __cmd_report(true);
2586 	} else if (strlen(argv[0]) > 2 && strstarts("contention", argv[0])) {
2587 		trace_handler = &contention_lock_ops;
2588 		sort_key = "wait_total";
2589 		output_fields = "contended,wait_total,wait_max,avg_wait";
2590 
2591 #ifndef HAVE_BPF_SKEL
2592 		set_option_nobuild(contention_options, 'b', "use-bpf",
2593 				   "no BUILD_BPF_SKEL=1", false);
2594 #endif
2595 		if (argc) {
2596 			argc = parse_options(argc, argv, contention_options,
2597 					     contention_usage, 0);
2598 		}
2599 
2600 		if (check_lock_contention_options(contention_options,
2601 						  contention_usage) < 0)
2602 			return -1;
2603 
2604 		rc = __cmd_contention(argc, argv);
2605 	} else {
2606 		usage_with_options(lock_usage, lock_options);
2607 	}
2608 
2609 	zfree(&lockhash_table);
2610 	return rc;
2611 }
2612