projects/linux·blob master · refs

326 lines · 8.8 KiB

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
14struct perf_sample;
15struct perf_session;
16
17enum 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
25enum kwork_report_type {
26 KWORK_REPORT_RUNTIME,
27 KWORK_REPORT_LATENCY,
28 KWORK_REPORT_TIMEHIST,
29 KWORK_REPORT_TOP,
30};
31
32enum 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
82struct 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
92struct 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
98struct perf_kwork;
99struct kwork_class;
100struct 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
144struct 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
168static inline void work_exit(struct kwork_work *work)
169{
170 if (work) {
171 free(work->name);
172 work->name = NULL;
173 }
174}
175
176struct 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
194struct __top_cpus_runtime {
195 u64 load;
196 u64 idle;
197 u64 irq;
198 u64 softirq;
199 u64 total;
200};
201
202struct 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
208struct 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
274int perf_kwork__trace_prepare_bpf(struct perf_kwork *kwork);
275int perf_kwork__report_read_bpf(struct perf_kwork *kwork);
276void perf_kwork__report_cleanup_bpf(void);
277
278void perf_kwork__trace_start(void);
279void perf_kwork__trace_finish(void);
280
281int perf_kwork__top_prepare_bpf(struct perf_kwork *kwork);
282int perf_kwork__top_read_bpf(struct perf_kwork *kwork);
283void perf_kwork__top_cleanup_bpf(void);
284
285void perf_kwork__top_start(void);
286void perf_kwork__top_finish(void);
287
288#else /* !HAVE_BPF_SKEL */
289
290static inline int
291perf_kwork__trace_prepare_bpf(struct perf_kwork *kwork __maybe_unused)
292{
293 return -1;
294}
295
296static inline int
297perf_kwork__report_read_bpf(struct perf_kwork *kwork __maybe_unused)
298{
299 return -1;
300}
301
302static inline void perf_kwork__report_cleanup_bpf(void) {}
303
304static inline void perf_kwork__trace_start(void) {}
305static inline void perf_kwork__trace_finish(void) {}
306
307static inline int
308perf_kwork__top_prepare_bpf(struct perf_kwork *kwork __maybe_unused)
309{
310 return -1;
311}
312
313static inline int
314perf_kwork__top_read_bpf(struct perf_kwork *kwork __maybe_unused)
315{
316 return -1;
317}
318
319static inline void perf_kwork__top_cleanup_bpf(void) {}
320
321static inline void perf_kwork__top_start(void) {}
322static inline void perf_kwork__top_finish(void) {}
323
324#endif /* HAVE_BPF_SKEL */
325
326#endif /* PERF_UTIL_KWORK_H */