1 // SPDX-License-Identifier: GPL-2.0 2 #ifndef PERF_LOCK_CONTENTION_H 3 #define PERF_LOCK_CONTENTION_H 4 5 #include <linux/list.h> 6 #include <linux/rbtree.h> 7 8 struct lock_filter { 9 int nr_types; 10 int nr_addrs; 11 int nr_syms; 12 unsigned int *types; 13 unsigned long *addrs; 14 char **syms; 15 }; 16 17 struct lock_stat { 18 struct hlist_node hash_entry; 19 struct rb_node rb; /* used for sorting */ 20 21 u64 addr; /* address of lockdep_map, used as ID */ 22 char *name; /* for strcpy(), we cannot use const */ 23 u64 *callstack; 24 25 unsigned int nr_acquire; 26 unsigned int nr_acquired; 27 unsigned int nr_contended; 28 unsigned int nr_release; 29 30 union { 31 unsigned int nr_readlock; 32 unsigned int flags; 33 }; 34 unsigned int nr_trylock; 35 36 /* these times are in nano sec. */ 37 u64 avg_wait_time; 38 u64 wait_time_total; 39 u64 wait_time_min; 40 u64 wait_time_max; 41 42 int broken; /* flag of blacklist */ 43 int combined; 44 }; 45 46 /* 47 * States of lock_seq_stat 48 * 49 * UNINITIALIZED is required for detecting first event of acquire. 50 * As the nature of lock events, there is no guarantee 51 * that the first event for the locks are acquire, 52 * it can be acquired, contended or release. 53 */ 54 #define SEQ_STATE_UNINITIALIZED 0 /* initial state */ 55 #define SEQ_STATE_RELEASED 1 56 #define SEQ_STATE_ACQUIRING 2 57 #define SEQ_STATE_ACQUIRED 3 58 #define SEQ_STATE_READ_ACQUIRED 4 59 #define SEQ_STATE_CONTENDED 5 60 61 /* 62 * MAX_LOCK_DEPTH 63 * Imported from include/linux/sched.h. 64 * Should this be synchronized? 65 */ 66 #define MAX_LOCK_DEPTH 48 67 68 /* 69 * struct lock_seq_stat: 70 * Place to put on state of one lock sequence 71 * 1) acquire -> acquired -> release 72 * 2) acquire -> contended -> acquired -> release 73 * 3) acquire (with read or try) -> release 74 * 4) Are there other patterns? 75 */ 76 struct lock_seq_stat { 77 struct list_head list; 78 int state; 79 u64 prev_event_time; 80 u64 addr; 81 82 int read_count; 83 }; 84 85 struct thread_stat { 86 struct rb_node rb; 87 88 u32 tid; 89 struct list_head seq_list; 90 }; 91 92 /* 93 * CONTENTION_STACK_DEPTH 94 * Number of stack trace entries to find callers 95 */ 96 #define CONTENTION_STACK_DEPTH 8 97 98 /* 99 * CONTENTION_STACK_SKIP 100 * Number of stack trace entries to skip when finding callers. 101 * The first few entries belong to the locking implementation itself. 102 */ 103 #define CONTENTION_STACK_SKIP 4 104 105 /* 106 * flags for lock:contention_begin 107 * Imported from include/trace/events/lock.h. 108 */ 109 #define LCB_F_SPIN (1U << 0) 110 #define LCB_F_READ (1U << 1) 111 #define LCB_F_WRITE (1U << 2) 112 #define LCB_F_RT (1U << 3) 113 #define LCB_F_PERCPU (1U << 4) 114 #define LCB_F_MUTEX (1U << 5) 115 116 struct evlist; 117 struct machine; 118 struct target; 119 120 struct lock_contention { 121 struct evlist *evlist; 122 struct target *target; 123 struct machine *machine; 124 struct hlist_head *result; 125 struct lock_filter *filters; 126 unsigned long map_nr_entries; 127 int lost; 128 int max_stack; 129 int stack_skip; 130 int aggr_mode; 131 }; 132 133 #ifdef HAVE_BPF_SKEL 134 135 int lock_contention_prepare(struct lock_contention *con); 136 int lock_contention_start(void); 137 int lock_contention_stop(void); 138 int lock_contention_read(struct lock_contention *con); 139 int lock_contention_finish(void); 140 141 #else /* !HAVE_BPF_SKEL */ 142 143 static inline int lock_contention_prepare(struct lock_contention *con __maybe_unused) 144 { 145 return 0; 146 } 147 148 static inline int lock_contention_start(void) { return 0; } 149 static inline int lock_contention_stop(void) { return 0; } 150 static inline int lock_contention_finish(void) { return 0; } 151 152 static inline int lock_contention_read(struct lock_contention *con __maybe_unused) 153 { 154 return 0; 155 } 156 157 #endif /* HAVE_BPF_SKEL */ 158 159 #endif /* PERF_LOCK_CONTENTION_H */ 160