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