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 struct lock_stat *lock_stat_find(u64 addr); 69 struct lock_stat *lock_stat_findnew(u64 addr, const char *name, int flags); 70 71 bool match_callstack_filter(struct machine *machine, u64 *callstack); 72 73 /* 74 * struct lock_seq_stat: 75 * Place to put on state of one lock sequence 76 * 1) acquire -> acquired -> release 77 * 2) acquire -> contended -> acquired -> release 78 * 3) acquire (with read or try) -> release 79 * 4) Are there other patterns? 80 */ 81 struct lock_seq_stat { 82 struct list_head list; 83 int state; 84 u64 prev_event_time; 85 u64 addr; 86 87 int read_count; 88 }; 89 90 struct thread_stat { 91 struct rb_node rb; 92 93 u32 tid; 94 struct list_head seq_list; 95 }; 96 97 /* 98 * CONTENTION_STACK_DEPTH 99 * Number of stack trace entries to find callers 100 */ 101 #define CONTENTION_STACK_DEPTH 8 102 103 /* 104 * CONTENTION_STACK_SKIP 105 * Number of stack trace entries to skip when finding callers. 106 * The first few entries belong to the locking implementation itself. 107 */ 108 #define CONTENTION_STACK_SKIP 4 109 110 /* 111 * flags for lock:contention_begin 112 * Imported from include/trace/events/lock.h. 113 */ 114 #define LCB_F_SPIN (1U << 0) 115 #define LCB_F_READ (1U << 1) 116 #define LCB_F_WRITE (1U << 2) 117 #define LCB_F_RT (1U << 3) 118 #define LCB_F_PERCPU (1U << 4) 119 #define LCB_F_MUTEX (1U << 5) 120 121 struct evlist; 122 struct machine; 123 struct target; 124 125 struct lock_contention_fails { 126 int task; 127 int stack; 128 int time; 129 }; 130 131 struct lock_contention { 132 struct evlist *evlist; 133 struct target *target; 134 struct machine *machine; 135 struct hlist_head *result; 136 struct lock_filter *filters; 137 struct lock_contention_fails fails; 138 unsigned long map_nr_entries; 139 int max_stack; 140 int stack_skip; 141 int aggr_mode; 142 int owner; 143 bool save_callstack; 144 }; 145 146 #ifdef HAVE_BPF_SKEL 147 148 int lock_contention_prepare(struct lock_contention *con); 149 int lock_contention_start(void); 150 int lock_contention_stop(void); 151 int lock_contention_read(struct lock_contention *con); 152 int lock_contention_finish(void); 153 154 #else /* !HAVE_BPF_SKEL */ 155 156 static inline int lock_contention_prepare(struct lock_contention *con __maybe_unused) 157 { 158 return 0; 159 } 160 161 static inline int lock_contention_start(void) { return 0; } 162 static inline int lock_contention_stop(void) { return 0; } 163 static inline int lock_contention_finish(void) { return 0; } 164 165 static inline int lock_contention_read(struct lock_contention *con __maybe_unused) 166 { 167 return 0; 168 } 169 170 #endif /* HAVE_BPF_SKEL */ 171 172 #endif /* PERF_LOCK_CONTENTION_H */ 173