xref: /linux/tools/perf/util/kwork.h (revision c16ce856e422e73a54c41131e0332de1afe09b8b)
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 	unsigned int nr_skipped_cpu;
206 };
207 
208 struct perf_kwork {
209 	/*
210 	 * metadata
211 	 */
212 	struct perf_tool tool;
213 	struct list_head class_list;
214 	struct list_head atom_page_list;
215 	struct list_head sort_list, cmp_id;
216 	struct rb_root_cached sorted_work_root;
217 	const struct trace_kwork_handler *tp_handler;
218 
219 	/*
220 	 * profile filters
221 	 */
222 	const char *profile_name;
223 
224 	const char *cpu_list;
225 	DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
226 
227 	const char *time_str;
228 	struct perf_time_interval ptime;
229 
230 	/*
231 	 * options for command
232 	 */
233 	bool force;
234 	const char *event_list_str;
235 	enum kwork_report_type report;
236 
237 	/*
238 	 * options for subcommand
239 	 */
240 	bool summary;
241 	const char *sort_order;
242 	bool show_callchain;
243 	unsigned int max_stack;
244 	bool use_bpf;
245 
246 	/*
247 	 * statistics
248 	 */
249 	u64 timestart;
250 	u64 timeend;
251 
252 	unsigned long nr_events;
253 	unsigned long nr_lost_chunks;
254 	unsigned long nr_lost_events;
255 
256 	u64 all_runtime;
257 	u64 all_count;
258 	u64 nr_skipped_events[KWORK_TRACE_MAX + 1];
259 
260 	/*
261 	 * perf kwork top data
262 	 */
263 	struct kwork_top_stat top_stat;
264 
265 	/* Add work callback. */
266 	struct kwork_work *(*add_work)(struct perf_kwork *kwork,
267 				       struct kwork_class *class,
268 				       struct kwork_work *key);
269 
270 };
271 
272 #ifdef HAVE_BPF_SKEL
273 
274 int perf_kwork__trace_prepare_bpf(struct perf_kwork *kwork);
275 int perf_kwork__report_read_bpf(struct perf_kwork *kwork);
276 void perf_kwork__report_cleanup_bpf(void);
277 
278 void perf_kwork__trace_start(void);
279 void perf_kwork__trace_finish(void);
280 
281 int perf_kwork__top_prepare_bpf(struct perf_kwork *kwork);
282 int perf_kwork__top_read_bpf(struct perf_kwork *kwork);
283 void perf_kwork__top_cleanup_bpf(void);
284 
285 void perf_kwork__top_start(void);
286 void perf_kwork__top_finish(void);
287 
288 #else  /* !HAVE_BPF_SKEL */
289 
290 static inline int
291 perf_kwork__trace_prepare_bpf(struct perf_kwork *kwork __maybe_unused)
292 {
293 	return -1;
294 }
295 
296 static inline int
297 perf_kwork__report_read_bpf(struct perf_kwork *kwork __maybe_unused)
298 {
299 	return -1;
300 }
301 
302 static inline void perf_kwork__report_cleanup_bpf(void) {}
303 
304 static inline void perf_kwork__trace_start(void) {}
305 static inline void perf_kwork__trace_finish(void) {}
306 
307 static inline int
308 perf_kwork__top_prepare_bpf(struct perf_kwork *kwork __maybe_unused)
309 {
310 	return -1;
311 }
312 
313 static inline int
314 perf_kwork__top_read_bpf(struct perf_kwork *kwork __maybe_unused)
315 {
316 	return -1;
317 }
318 
319 static inline void perf_kwork__top_cleanup_bpf(void) {}
320 
321 static inline void perf_kwork__top_start(void) {}
322 static inline void perf_kwork__top_finish(void) {}
323 
324 #endif  /* HAVE_BPF_SKEL */
325 
326 #endif  /* PERF_UTIL_KWORK_H */
327