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