Commit | Line | Data |
---|---|---|
b2441318 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
8b40f521 JK |
2 | #ifndef __PERF_THREAD_H |
3 | #define __PERF_THREAD_H | |
4 | ||
e34f5b11 | 5 | #include <linux/refcount.h> |
1902efe7 | 6 | #include <linux/list.h> |
e22c1c75 | 7 | #include <stdio.h> |
6baa0a5a | 8 | #include <unistd.h> |
9d2f8e22 | 9 | #include <sys/types.h> |
4fed0726 | 10 | #include "srccode.h" |
e22c1c75 | 11 | #include "symbol_conf.h" |
1f3878c1 | 12 | #include <strlist.h> |
e03eaa40 | 13 | #include <intlist.h> |
b32ee9e5 | 14 | #include "rwsem.h" |
7f1d3931 | 15 | #include "callchain.h" |
f6005caf | 16 | #include <internal/rc_check.h> |
6baa0a5a | 17 | |
e22c1c75 ACM |
18 | struct addr_location; |
19 | struct map; | |
69d81f09 | 20 | struct perf_record_namespaces; |
00447ccd | 21 | struct thread_stack; |
f83c0415 | 22 | struct unwind_libunwind_ops; |
00447ccd | 23 | |
9c6c3f47 | 24 | struct lbr_stitch { |
ff165628 KL |
25 | struct list_head lists; |
26 | struct list_head free_lists; | |
9c6c3f47 | 27 | struct perf_sample prev_sample; |
7f1d3931 | 28 | struct callchain_cursor_node *prev_lbr_cursor; |
9c6c3f47 KL |
29 | }; |
30 | ||
f6005caf | 31 | DECLARE_RC_STRUCT(thread) { |
9ffa6c75 | 32 | /** @maps: mmaps associated with this thread. */ |
fe87797d | 33 | struct maps *maps; |
99d725fc | 34 | pid_t pid_; /* Not all tools update this */ |
9ffa6c75 | 35 | /** @tid: thread ID number unique to a machine. */ |
38051234 | 36 | pid_t tid; |
9ffa6c75 | 37 | /** @ppid: parent process of the process this thread belongs to. */ |
70c57efb | 38 | pid_t ppid; |
bf49c35f | 39 | int cpu; |
797efbc5 | 40 | int guest_cpu; /* For QEMU thread */ |
e34f5b11 | 41 | refcount_t refcnt; |
9ffa6c75 IR |
42 | /** |
43 | * @exited: Has the thread had an exit event. Such threads are usually | |
44 | * removed from the machine's threads but some events/tools require | |
45 | * access to dead threads. | |
46 | */ | |
47 | bool exited; | |
faa5c5c3 | 48 | bool comm_set; |
86066064 | 49 | int comm_len; |
f3b3614a | 50 | struct list_head namespaces_list; |
b32ee9e5 | 51 | struct rw_semaphore namespaces_lock; |
1902efe7 | 52 | struct list_head comm_list; |
b32ee9e5 | 53 | struct rw_semaphore comm_lock; |
0db15b1e | 54 | u64 db_id; |
bcf6edcd XG |
55 | |
56 | void *priv; | |
00447ccd | 57 | struct thread_stack *ts; |
843ff37b | 58 | struct nsinfo *nsinfo; |
dd2e18e9 | 59 | struct srccode_state srccode_state; |
99f753f0 AK |
60 | bool filter; |
61 | int filter_entry_depth; | |
771fd155 KL |
62 | |
63 | /* LBR call stack stitch */ | |
64 | bool lbr_stitch_enable; | |
9c6c3f47 | 65 | struct lbr_stitch *lbr_stitch; |
6baa0a5a FW |
66 | }; |
67 | ||
743eb868 | 68 | struct machine; |
f3b3614a | 69 | struct namespaces; |
4dfced35 | 70 | struct comm; |
4b8cf846 | 71 | |
99d725fc | 72 | struct thread *thread__new(pid_t pid, pid_t tid); |
79b6bb73 | 73 | int thread__init_maps(struct thread *thread, struct machine *machine); |
316c7136 | 74 | void thread__delete(struct thread *thread); |
f3b623b8 | 75 | |
04cb4fc4 ACM |
76 | void thread__set_priv_destructor(void (*destructor)(void *priv)); |
77 | ||
f3b623b8 ACM |
78 | struct thread *thread__get(struct thread *thread); |
79 | void thread__put(struct thread *thread); | |
80 | ||
81 | static inline void __thread__zput(struct thread **thread) | |
82 | { | |
83 | thread__put(*thread); | |
84 | *thread = NULL; | |
85 | } | |
86 | ||
87 | #define thread__zput(thread) __thread__zput(&thread) | |
88 | ||
7cb10a08 | 89 | struct namespaces *thread__namespaces(struct thread *thread); |
f3b3614a | 90 | int thread__set_namespaces(struct thread *thread, u64 timestamp, |
69d81f09 | 91 | struct perf_record_namespaces *event); |
f3b3614a | 92 | |
65de51f9 AH |
93 | int __thread__set_comm(struct thread *thread, const char *comm, u64 timestamp, |
94 | bool exec); | |
95 | static inline int thread__set_comm(struct thread *thread, const char *comm, | |
96 | u64 timestamp) | |
97 | { | |
98 | return __thread__set_comm(thread, comm, timestamp, false); | |
99 | } | |
100 | ||
2f3027ac ACM |
101 | int thread__set_comm_from_proc(struct thread *thread); |
102 | ||
316c7136 | 103 | int thread__comm_len(struct thread *thread); |
ee84a303 IR |
104 | struct comm *thread__comm(struct thread *thread); |
105 | struct comm *thread__exec_comm(struct thread *thread); | |
7cb10a08 | 106 | const char *thread__comm_str(struct thread *thread); |
8132a2a8 | 107 | int thread__insert_map(struct thread *thread, struct map *map); |
4f8f382e | 108 | int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp, bool do_maps_clone); |
3f067dca | 109 | size_t thread__fprintf(struct thread *thread, FILE *fp); |
8b40f521 | 110 | |
480ca357 AK |
111 | struct thread *thread__main_thread(struct machine *machine, struct thread *thread); |
112 | ||
404eb5a4 ACM |
113 | struct map *thread__find_map(struct thread *thread, u8 cpumode, u64 addr, |
114 | struct addr_location *al); | |
8e80ad99 AH |
115 | struct map *thread__find_map_fb(struct thread *thread, u8 cpumode, u64 addr, |
116 | struct addr_location *al); | |
59ee68ec | 117 | |
117d3c24 ACM |
118 | struct symbol *thread__find_symbol(struct thread *thread, u8 cpumode, |
119 | u64 addr, struct addr_location *al); | |
8e80ad99 AH |
120 | struct symbol *thread__find_symbol_fb(struct thread *thread, u8 cpumode, |
121 | u64 addr, struct addr_location *al); | |
ba58041a | 122 | |
26bd9331 | 123 | void thread__find_cpumode_addr_location(struct thread *thread, u64 addr, |
52a3cb8c ACM |
124 | struct addr_location *al); |
125 | ||
15325938 AK |
126 | int thread__memcpy(struct thread *thread, struct machine *machine, |
127 | void *buf, u64 ip, int len, bool *is64bit); | |
128 | ||
ee84a303 IR |
129 | static inline struct maps *thread__maps(struct thread *thread) |
130 | { | |
f6005caf | 131 | return RC_CHK_ACCESS(thread)->maps; |
ee84a303 IR |
132 | } |
133 | ||
134 | static inline void thread__set_maps(struct thread *thread, struct maps *maps) | |
135 | { | |
f6005caf | 136 | RC_CHK_ACCESS(thread)->maps = maps; |
ee84a303 IR |
137 | } |
138 | ||
139 | static inline pid_t thread__pid(const struct thread *thread) | |
140 | { | |
f6005caf | 141 | return RC_CHK_ACCESS(thread)->pid_; |
ee84a303 IR |
142 | } |
143 | ||
144 | static inline void thread__set_pid(struct thread *thread, pid_t pid_) | |
145 | { | |
f6005caf | 146 | RC_CHK_ACCESS(thread)->pid_ = pid_; |
ee84a303 IR |
147 | } |
148 | ||
149 | static inline pid_t thread__tid(const struct thread *thread) | |
150 | { | |
f6005caf | 151 | return RC_CHK_ACCESS(thread)->tid; |
ee84a303 IR |
152 | } |
153 | ||
154 | static inline void thread__set_tid(struct thread *thread, pid_t tid) | |
155 | { | |
f6005caf | 156 | RC_CHK_ACCESS(thread)->tid = tid; |
ee84a303 IR |
157 | } |
158 | ||
159 | static inline pid_t thread__ppid(const struct thread *thread) | |
160 | { | |
f6005caf | 161 | return RC_CHK_ACCESS(thread)->ppid; |
ee84a303 IR |
162 | } |
163 | ||
164 | static inline void thread__set_ppid(struct thread *thread, pid_t ppid) | |
165 | { | |
f6005caf | 166 | RC_CHK_ACCESS(thread)->ppid = ppid; |
ee84a303 IR |
167 | } |
168 | ||
169 | static inline int thread__cpu(const struct thread *thread) | |
170 | { | |
f6005caf | 171 | return RC_CHK_ACCESS(thread)->cpu; |
ee84a303 IR |
172 | } |
173 | ||
174 | static inline void thread__set_cpu(struct thread *thread, int cpu) | |
175 | { | |
f6005caf | 176 | RC_CHK_ACCESS(thread)->cpu = cpu; |
ee84a303 IR |
177 | } |
178 | ||
179 | static inline int thread__guest_cpu(const struct thread *thread) | |
180 | { | |
f6005caf | 181 | return RC_CHK_ACCESS(thread)->guest_cpu; |
ee84a303 IR |
182 | } |
183 | ||
184 | static inline void thread__set_guest_cpu(struct thread *thread, int guest_cpu) | |
185 | { | |
f6005caf | 186 | RC_CHK_ACCESS(thread)->guest_cpu = guest_cpu; |
ee84a303 IR |
187 | } |
188 | ||
189 | static inline refcount_t *thread__refcnt(struct thread *thread) | |
190 | { | |
f6005caf | 191 | return &RC_CHK_ACCESS(thread)->refcnt; |
ee84a303 IR |
192 | } |
193 | ||
9ffa6c75 IR |
194 | static inline void thread__set_exited(struct thread *thread, bool exited) |
195 | { | |
196 | RC_CHK_ACCESS(thread)->exited = exited; | |
197 | } | |
198 | ||
ee84a303 IR |
199 | static inline bool thread__comm_set(const struct thread *thread) |
200 | { | |
f6005caf | 201 | return RC_CHK_ACCESS(thread)->comm_set; |
ee84a303 IR |
202 | } |
203 | ||
204 | static inline void thread__set_comm_set(struct thread *thread, bool set) | |
205 | { | |
f6005caf | 206 | RC_CHK_ACCESS(thread)->comm_set = set; |
ee84a303 IR |
207 | } |
208 | ||
209 | static inline int thread__var_comm_len(const struct thread *thread) | |
210 | { | |
f6005caf | 211 | return RC_CHK_ACCESS(thread)->comm_len; |
ee84a303 IR |
212 | } |
213 | ||
214 | static inline void thread__set_comm_len(struct thread *thread, int len) | |
215 | { | |
f6005caf | 216 | RC_CHK_ACCESS(thread)->comm_len = len; |
ee84a303 IR |
217 | } |
218 | ||
219 | static inline struct list_head *thread__namespaces_list(struct thread *thread) | |
220 | { | |
f6005caf | 221 | return &RC_CHK_ACCESS(thread)->namespaces_list; |
ee84a303 IR |
222 | } |
223 | ||
224 | static inline int thread__namespaces_list_empty(const struct thread *thread) | |
225 | { | |
f6005caf | 226 | return list_empty(&RC_CHK_ACCESS(thread)->namespaces_list); |
ee84a303 IR |
227 | } |
228 | ||
229 | static inline struct rw_semaphore *thread__namespaces_lock(struct thread *thread) | |
230 | { | |
f6005caf | 231 | return &RC_CHK_ACCESS(thread)->namespaces_lock; |
ee84a303 IR |
232 | } |
233 | ||
234 | static inline struct list_head *thread__comm_list(struct thread *thread) | |
235 | { | |
f6005caf | 236 | return &RC_CHK_ACCESS(thread)->comm_list; |
ee84a303 IR |
237 | } |
238 | ||
239 | static inline struct rw_semaphore *thread__comm_lock(struct thread *thread) | |
240 | { | |
f6005caf | 241 | return &RC_CHK_ACCESS(thread)->comm_lock; |
ee84a303 IR |
242 | } |
243 | ||
244 | static inline u64 thread__db_id(const struct thread *thread) | |
245 | { | |
f6005caf | 246 | return RC_CHK_ACCESS(thread)->db_id; |
ee84a303 IR |
247 | } |
248 | ||
249 | static inline void thread__set_db_id(struct thread *thread, u64 db_id) | |
250 | { | |
f6005caf | 251 | RC_CHK_ACCESS(thread)->db_id = db_id; |
ee84a303 IR |
252 | } |
253 | ||
ba58041a DA |
254 | static inline void *thread__priv(struct thread *thread) |
255 | { | |
f6005caf | 256 | return RC_CHK_ACCESS(thread)->priv; |
ba58041a DA |
257 | } |
258 | ||
259 | static inline void thread__set_priv(struct thread *thread, void *p) | |
260 | { | |
f6005caf | 261 | RC_CHK_ACCESS(thread)->priv = p; |
ba58041a | 262 | } |
1f3878c1 | 263 | |
ee84a303 IR |
264 | static inline struct thread_stack *thread__ts(struct thread *thread) |
265 | { | |
f6005caf | 266 | return RC_CHK_ACCESS(thread)->ts; |
ee84a303 IR |
267 | } |
268 | ||
269 | static inline void thread__set_ts(struct thread *thread, struct thread_stack *ts) | |
270 | { | |
f6005caf | 271 | RC_CHK_ACCESS(thread)->ts = ts; |
ee84a303 IR |
272 | } |
273 | ||
274 | static inline struct nsinfo *thread__nsinfo(struct thread *thread) | |
275 | { | |
f6005caf | 276 | return RC_CHK_ACCESS(thread)->nsinfo; |
ee84a303 IR |
277 | } |
278 | ||
279 | static inline struct srccode_state *thread__srccode_state(struct thread *thread) | |
280 | { | |
f6005caf | 281 | return &RC_CHK_ACCESS(thread)->srccode_state; |
ee84a303 IR |
282 | } |
283 | ||
284 | static inline bool thread__filter(const struct thread *thread) | |
285 | { | |
f6005caf | 286 | return RC_CHK_ACCESS(thread)->filter; |
ee84a303 IR |
287 | } |
288 | ||
289 | static inline void thread__set_filter(struct thread *thread, bool filter) | |
290 | { | |
f6005caf | 291 | RC_CHK_ACCESS(thread)->filter = filter; |
ee84a303 IR |
292 | } |
293 | ||
294 | static inline int thread__filter_entry_depth(const struct thread *thread) | |
295 | { | |
f6005caf | 296 | return RC_CHK_ACCESS(thread)->filter_entry_depth; |
ee84a303 IR |
297 | } |
298 | ||
299 | static inline void thread__set_filter_entry_depth(struct thread *thread, int depth) | |
300 | { | |
f6005caf | 301 | RC_CHK_ACCESS(thread)->filter_entry_depth = depth; |
ee84a303 IR |
302 | } |
303 | ||
304 | static inline bool thread__lbr_stitch_enable(const struct thread *thread) | |
305 | { | |
f6005caf | 306 | return RC_CHK_ACCESS(thread)->lbr_stitch_enable; |
ee84a303 IR |
307 | } |
308 | ||
309 | static inline void thread__set_lbr_stitch_enable(struct thread *thread, bool en) | |
310 | { | |
f6005caf | 311 | RC_CHK_ACCESS(thread)->lbr_stitch_enable = en; |
ee84a303 IR |
312 | } |
313 | ||
314 | static inline struct lbr_stitch *thread__lbr_stitch(struct thread *thread) | |
315 | { | |
f6005caf | 316 | return RC_CHK_ACCESS(thread)->lbr_stitch; |
ee84a303 IR |
317 | } |
318 | ||
319 | static inline void thread__set_lbr_stitch(struct thread *thread, struct lbr_stitch *lbrs) | |
320 | { | |
f6005caf | 321 | RC_CHK_ACCESS(thread)->lbr_stitch = lbrs; |
ee84a303 IR |
322 | } |
323 | ||
1f3878c1 DA |
324 | static inline bool thread__is_filtered(struct thread *thread) |
325 | { | |
326 | if (symbol_conf.comm_list && | |
327 | !strlist__has_entry(symbol_conf.comm_list, thread__comm_str(thread))) { | |
328 | return true; | |
329 | } | |
330 | ||
e03eaa40 | 331 | if (symbol_conf.pid_list && |
ee84a303 | 332 | !intlist__has_entry(symbol_conf.pid_list, thread__pid(thread))) { |
e03eaa40 DA |
333 | return true; |
334 | } | |
335 | ||
336 | if (symbol_conf.tid_list && | |
ee84a303 | 337 | !intlist__has_entry(symbol_conf.tid_list, thread__tid(thread))) { |
e03eaa40 DA |
338 | return true; |
339 | } | |
340 | ||
1f3878c1 DA |
341 | return false; |
342 | } | |
343 | ||
ff165628 | 344 | void thread__free_stitch_list(struct thread *thread); |
9c6c3f47 | 345 | |
cde56712 ACM |
346 | void thread__resolve(struct thread *thread, struct addr_location *al, |
347 | struct perf_sample *sample); | |
348 | ||
8b40f521 | 349 | #endif /* __PERF_THREAD_H */ |