1 #ifndef PERF_UTIL_KWORK_H 2 #define PERF_UTIL_KWORK_H 3 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 12 struct perf_sample; 13 struct perf_session; 14 15 enum 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 23 enum kwork_report_type { 24 KWORK_REPORT_RUNTIME, 25 KWORK_REPORT_LATENCY, 26 KWORK_REPORT_TIMEHIST, 27 KWORK_REPORT_TOP, 28 }; 29 30 enum 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 80 struct 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 128 90 struct 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 96 struct perf_kwork; 97 struct kwork_class; 98 struct kwork_work { 99 /* 100 * class field 101 */ 102 struct rb_node node; 103 struct kwork_class *class; 104 105 /* 106 * work field 107 */ 108 u64 id; 109 int cpu; 110 char *name; 111 112 /* 113 * atom field 114 */ 115 u64 nr_atoms; 116 struct list_head atom_list[KWORK_TRACE_MAX]; 117 118 /* 119 * runtime report 120 */ 121 u64 max_runtime; 122 u64 max_runtime_start; 123 u64 max_runtime_end; 124 u64 total_runtime; 125 126 /* 127 * latency report 128 */ 129 u64 max_latency; 130 u64 max_latency_start; 131 u64 max_latency_end; 132 u64 total_latency; 133 134 /* 135 * top report 136 */ 137 u32 cpu_usage; 138 u32 tgid; 139 bool is_kthread; 140 }; 141 142 struct 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 167 struct 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 185 struct __top_cpus_runtime { 186 u64 load; 187 u64 idle; 188 u64 irq; 189 u64 softirq; 190 u64 total; 191 }; 192 193 struct kwork_top_stat { 194 DECLARE_BITMAP(all_cpus_bitmap, MAX_NR_CPUS); 195 struct __top_cpus_runtime *cpus_runtime; 196 }; 197 198 struct perf_kwork { 199 /* 200 * metadata 201 */ 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 filters 211 */ 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 command 222 */ 223 bool force; 224 const char *event_list_str; 225 enum kwork_report_type report; 226 227 /* 228 * options for subcommand 229 */ 230 bool summary; 231 const char *sort_order; 232 bool show_callchain; 233 unsigned int max_stack; 234 bool use_bpf; 235 236 /* 237 * statistics 238 */ 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 data 252 */ 253 struct kwork_top_stat top_stat; 254 }; 255 256 struct 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_SKEL 261 262 int perf_kwork__trace_prepare_bpf(struct perf_kwork *kwork); 263 int perf_kwork__report_read_bpf(struct perf_kwork *kwork); 264 void perf_kwork__report_cleanup_bpf(void); 265 266 void perf_kwork__trace_start(void); 267 void perf_kwork__trace_finish(void); 268 269 int perf_kwork__top_prepare_bpf(struct perf_kwork *kwork); 270 int perf_kwork__top_read_bpf(struct perf_kwork *kwork); 271 void perf_kwork__top_cleanup_bpf(void); 272 273 void perf_kwork__top_start(void); 274 void perf_kwork__top_finish(void); 275 276 #else /* !HAVE_BPF_SKEL */ 277 278 static inline int 279 perf_kwork__trace_prepare_bpf(struct perf_kwork *kwork __maybe_unused) 280 { 281 return -1; 282 } 283 284 static inline int 285 perf_kwork__report_read_bpf(struct perf_kwork *kwork __maybe_unused) 286 { 287 return -1; 288 } 289 290 static inline void perf_kwork__report_cleanup_bpf(void) {} 291 292 static inline void perf_kwork__trace_start(void) {} 293 static inline void perf_kwork__trace_finish(void) {} 294 295 static inline int 296 perf_kwork__top_prepare_bpf(struct perf_kwork *kwork __maybe_unused) 297 { 298 return -1; 299 } 300 301 static inline int 302 perf_kwork__top_read_bpf(struct perf_kwork *kwork __maybe_unused) 303 { 304 return -1; 305 } 306 307 static inline void perf_kwork__top_cleanup_bpf(void) {} 308 309 static inline void perf_kwork__top_start(void) {} 310 static inline void perf_kwork__top_finish(void) {} 311 312 #endif /* HAVE_BPF_SKEL */ 313 314 #endif /* PERF_UTIL_KWORK_H */ 315