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