xref: /linux/tools/perf/util/kwork.h (revision 390d5ea26622f794c2d29cefd5a01ef116b4fe1d)
1 #ifndef PERF_UTIL_KWORK_H
2 #define PERF_UTIL_KWORK_H
3 
4 #include "perf.h"
5 #include "util/tool.h"
6 #include "util/time-utils.h"
7 
8 #include <stdlib.h>
9 #include <linux/bitmap.h>
10 #include <linux/list.h>
11 #include <linux/rbtree.h>
12 #include <linux/types.h>
13 
14 struct perf_sample;
15 struct perf_session;
16 
17 enum kwork_class_type {
18 	KWORK_CLASS_IRQ,
19 	KWORK_CLASS_SOFTIRQ,
20 	KWORK_CLASS_WORKQUEUE,
21 	KWORK_CLASS_SCHED,
22 	KWORK_CLASS_MAX,
23 };
24 
25 enum kwork_report_type {
26 	KWORK_REPORT_RUNTIME,
27 	KWORK_REPORT_LATENCY,
28 	KWORK_REPORT_TIMEHIST,
29 	KWORK_REPORT_TOP,
30 };
31 
32 enum kwork_trace_type {
33 	KWORK_TRACE_RAISE,
34 	KWORK_TRACE_ENTRY,
35 	KWORK_TRACE_EXIT,
36 	KWORK_TRACE_MAX,
37 };
38 
39 /*
40  * data structure:
41  *
42  *                 +==================+ +============+ +======================+
43  *                 |      class       | |    work    | |         atom         |
44  *                 +==================+ +============+ +======================+
45  * +------------+  |  +-----+         | |  +------+  | |  +-------+   +-----+ |
46  * | perf_kwork | +-> | irq | --------|+-> | eth0 | --+-> | raise | - | ... | --+   +-----------+
47  * +-----+------+ ||  +-----+         |||  +------+  |||  +-------+   +-----+ | |   |           |
48  *       |        ||                  |||            |||                      | +-> | atom_page |
49  *       |        ||                  |||            |||  +-------+   +-----+ |     |           |
50  *       |  class_list                |||            |+-> | entry | - | ... | ----> |           |
51  *       |        ||                  |||            |||  +-------+   +-----+ |     |           |
52  *       |        ||                  |||            |||                      | +-> |           |
53  *       |        ||                  |||            |||  +-------+   +-----+ | |   |           |
54  *       |        ||                  |||            |+-> | exit  | - | ... | --+   +-----+-----+
55  *       |        ||                  |||            | |  +-------+   +-----+ |           |
56  *       |        ||                  |||            | |                      |           |
57  *       |        ||                  |||  +-----+   | |                      |           |
58  *       |        ||                  |+-> | ... |   | |                      |           |
59  *       |        ||                  | |  +-----+   | |                      |           |
60  *       |        ||                  | |            | |                      |           |
61  *       |        ||  +---------+     | |  +-----+   | |  +-------+   +-----+ |           |
62  *       |        +-> | softirq | -------> | RCU | ---+-> | raise | - | ... | --+   +-----+-----+
63  *       |        ||  +---------+     | |  +-----+   |||  +-------+   +-----+ | |   |           |
64  *       |        ||                  | |            |||                      | +-> | atom_page |
65  *       |        ||                  | |            |||  +-------+   +-----+ |     |           |
66  *       |        ||                  | |            |+-> | entry | - | ... | ----> |           |
67  *       |        ||                  | |            |||  +-------+   +-----+ |     |           |
68  *       |        ||                  | |            |||                      | +-> |           |
69  *       |        ||                  | |            |||  +-------+   +-----+ | |   |           |
70  *       |        ||                  | |            |+-> | exit  | - | ... | --+   +-----+-----+
71  *       |        ||                  | |            | |  +-------+   +-----+ |           |
72  *       |        ||                  | |            | |                      |           |
73  *       |        ||  +-----------+   | |  +-----+   | |                      |           |
74  *       |        +-> | workqueue | -----> | ... |   | |                      |           |
75  *       |         |  +-----------+   | |  +-----+   | |                      |           |
76  *       |         +==================+ +============+ +======================+           |
77  *       |                                                                                |
78  *       +---->  atom_page_list  ---------------------------------------------------------+
79  *
80  */
81 
82 struct kwork_atom {
83 	struct list_head list;
84 	u64 time;
85 	struct kwork_atom *prev;
86 
87 	void *page_addr;
88 	unsigned long bit_inpage;
89 };
90 
91 #define NR_ATOM_PER_PAGE 128
92 struct kwork_atom_page {
93 	struct list_head list;
94 	struct kwork_atom atoms[NR_ATOM_PER_PAGE];
95 	DECLARE_BITMAP(bitmap, NR_ATOM_PER_PAGE);
96 };
97 
98 struct perf_kwork;
99 struct kwork_class;
100 struct kwork_work {
101 	/*
102 	 * class field
103 	 */
104 	struct rb_node node;
105 	struct kwork_class *class;
106 
107 	/*
108 	 * work field
109 	 */
110 	u64 id;
111 	int cpu;
112 	char *name;
113 
114 	/*
115 	 * atom field
116 	 */
117 	u64 nr_atoms;
118 	struct list_head atom_list[KWORK_TRACE_MAX];
119 
120 	/*
121 	 * runtime report
122 	 */
123 	u64 max_runtime;
124 	u64 max_runtime_start;
125 	u64 max_runtime_end;
126 	u64 total_runtime;
127 
128 	/*
129 	 * latency report
130 	 */
131 	u64 max_latency;
132 	u64 max_latency_start;
133 	u64 max_latency_end;
134 	u64 total_latency;
135 
136 	/*
137 	 * top report
138 	 */
139 	u32 cpu_usage;
140 	u32 tgid;
141 	bool is_kthread;
142 };
143 
144 struct kwork_class {
145 	struct list_head list;
146 	const char *name;
147 	enum kwork_class_type type;
148 
149 	unsigned int nr_tracepoints;
150 	const struct evsel_str_handler *tp_handlers;
151 
152 	struct rb_root_cached work_root;
153 
154 	int (*class_init)(struct kwork_class *class,
155 			  struct perf_session *session);
156 
157 	void (*work_init)(struct perf_kwork *kwork,
158 			  struct kwork_class *class,
159 			  struct kwork_work *work,
160 			  enum kwork_trace_type src_type,
161 			  struct perf_sample *sample,
162 			  struct machine *machine);
163 
164 	void (*work_name)(struct kwork_work *work,
165 			  char *buf, int len);
166 };
167 
168 static inline void work_exit(struct kwork_work *work)
169 {
170 	if (work) {
171 		free(work->name);
172 		work->name = NULL;
173 	}
174 }
175 
176 struct trace_kwork_handler {
177 	int (*raise_event)(struct perf_kwork *kwork,
178 			   struct kwork_class *class,
179 			   struct perf_sample *sample, struct machine *machine);
180 
181 	int (*entry_event)(struct perf_kwork *kwork,
182 			   struct kwork_class *class,
183 			   struct perf_sample *sample, struct machine *machine);
184 
185 	int (*exit_event)(struct perf_kwork *kwork,
186 			  struct kwork_class *class,
187 			  struct perf_sample *sample, struct machine *machine);
188 
189 	int (*sched_switch_event)(struct perf_kwork *kwork,
190 				  struct kwork_class *class,
191 				  struct perf_sample *sample, struct machine *machine);
192 };
193 
194 struct __top_cpus_runtime {
195 	u64 load;
196 	u64 idle;
197 	u64 irq;
198 	u64 softirq;
199 	u64 total;
200 };
201 
202 struct kwork_top_stat {
203 	DECLARE_BITMAP(all_cpus_bitmap, MAX_NR_CPUS);
204 	struct __top_cpus_runtime *cpus_runtime;
205 };
206 
207 struct perf_kwork {
208 	/*
209 	 * metadata
210 	 */
211 	struct perf_tool tool;
212 	struct list_head class_list;
213 	struct list_head atom_page_list;
214 	struct list_head sort_list, cmp_id;
215 	struct rb_root_cached sorted_work_root;
216 	const struct trace_kwork_handler *tp_handler;
217 
218 	/*
219 	 * profile filters
220 	 */
221 	const char *profile_name;
222 
223 	const char *cpu_list;
224 	DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
225 
226 	const char *time_str;
227 	struct perf_time_interval ptime;
228 
229 	/*
230 	 * options for command
231 	 */
232 	bool force;
233 	const char *event_list_str;
234 	enum kwork_report_type report;
235 
236 	/*
237 	 * options for subcommand
238 	 */
239 	bool summary;
240 	const char *sort_order;
241 	bool show_callchain;
242 	unsigned int max_stack;
243 	bool use_bpf;
244 
245 	/*
246 	 * statistics
247 	 */
248 	u64 timestart;
249 	u64 timeend;
250 
251 	unsigned long nr_events;
252 	unsigned long nr_lost_chunks;
253 	unsigned long nr_lost_events;
254 
255 	u64 all_runtime;
256 	u64 all_count;
257 	u64 nr_skipped_events[KWORK_TRACE_MAX + 1];
258 
259 	/*
260 	 * perf kwork top data
261 	 */
262 	struct kwork_top_stat top_stat;
263 
264 	/* Add work callback. */
265 	struct kwork_work *(*add_work)(struct perf_kwork *kwork,
266 				       struct kwork_class *class,
267 				       struct kwork_work *key);
268 
269 };
270 
271 #ifdef HAVE_BPF_SKEL
272 
273 int perf_kwork__trace_prepare_bpf(struct perf_kwork *kwork);
274 int perf_kwork__report_read_bpf(struct perf_kwork *kwork);
275 void perf_kwork__report_cleanup_bpf(void);
276 
277 void perf_kwork__trace_start(void);
278 void perf_kwork__trace_finish(void);
279 
280 int perf_kwork__top_prepare_bpf(struct perf_kwork *kwork);
281 int perf_kwork__top_read_bpf(struct perf_kwork *kwork);
282 void perf_kwork__top_cleanup_bpf(void);
283 
284 void perf_kwork__top_start(void);
285 void perf_kwork__top_finish(void);
286 
287 #else  /* !HAVE_BPF_SKEL */
288 
289 static inline int
290 perf_kwork__trace_prepare_bpf(struct perf_kwork *kwork __maybe_unused)
291 {
292 	return -1;
293 }
294 
295 static inline int
296 perf_kwork__report_read_bpf(struct perf_kwork *kwork __maybe_unused)
297 {
298 	return -1;
299 }
300 
301 static inline void perf_kwork__report_cleanup_bpf(void) {}
302 
303 static inline void perf_kwork__trace_start(void) {}
304 static inline void perf_kwork__trace_finish(void) {}
305 
306 static inline int
307 perf_kwork__top_prepare_bpf(struct perf_kwork *kwork __maybe_unused)
308 {
309 	return -1;
310 }
311 
312 static inline int
313 perf_kwork__top_read_bpf(struct perf_kwork *kwork __maybe_unused)
314 {
315 	return -1;
316 }
317 
318 static inline void perf_kwork__top_cleanup_bpf(void) {}
319 
320 static inline void perf_kwork__top_start(void) {}
321 static inline void perf_kwork__top_finish(void) {}
322 
323 #endif  /* HAVE_BPF_SKEL */
324 
325 #endif  /* PERF_UTIL_KWORK_H */
326