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