1 #ifndef PERF_UTIL_KWORK_H 2 #define PERF_UTIL_KWORK_H 3 4 #include "perf.h" 5 6 #include "util/tool.h" 7 #include "util/event.h" 8 #include "util/evlist.h" 9 #include "util/session.h" 10 #include "util/time-utils.h" 11 12 #include <linux/list.h> 13 #include <linux/bitmap.h> 14 15 enum kwork_class_type { 16 KWORK_CLASS_IRQ, 17 KWORK_CLASS_SOFTIRQ, 18 KWORK_CLASS_WORKQUEUE, 19 KWORK_CLASS_MAX, 20 }; 21 22 enum kwork_report_type { 23 KWORK_REPORT_RUNTIME, 24 KWORK_REPORT_LATENCY, 25 KWORK_REPORT_TIMEHIST, 26 }; 27 28 enum kwork_trace_type { 29 KWORK_TRACE_RAISE, 30 KWORK_TRACE_ENTRY, 31 KWORK_TRACE_EXIT, 32 KWORK_TRACE_MAX, 33 }; 34 35 /* 36 * data structure: 37 * 38 * +==================+ +============+ +======================+ 39 * | class | | work | | atom | 40 * +==================+ +============+ +======================+ 41 * +------------+ | +-----+ | | +------+ | | +-------+ +-----+ | 42 * | perf_kwork | +-> | irq | --------|+-> | eth0 | --+-> | raise | - | ... | --+ +-----------+ 43 * +-----+------+ || +-----+ ||| +------+ ||| +-------+ +-----+ | | | | 44 * | || ||| ||| | +-> | atom_page | 45 * | || ||| ||| +-------+ +-----+ | | | 46 * | class_list ||| |+-> | entry | - | ... | ----> | | 47 * | || ||| ||| +-------+ +-----+ | | | 48 * | || ||| ||| | +-> | | 49 * | || ||| ||| +-------+ +-----+ | | | | 50 * | || ||| |+-> | exit | - | ... | --+ +-----+-----+ 51 * | || ||| | | +-------+ +-----+ | | 52 * | || ||| | | | | 53 * | || ||| +-----+ | | | | 54 * | || |+-> | ... | | | | | 55 * | || | | +-----+ | | | | 56 * | || | | | | | | 57 * | || +---------+ | | +-----+ | | +-------+ +-----+ | | 58 * | +-> | softirq | -------> | RCU | ---+-> | raise | - | ... | --+ +-----+-----+ 59 * | || +---------+ | | +-----+ ||| +-------+ +-----+ | | | | 60 * | || | | ||| | +-> | atom_page | 61 * | || | | ||| +-------+ +-----+ | | | 62 * | || | | |+-> | entry | - | ... | ----> | | 63 * | || | | ||| +-------+ +-----+ | | | 64 * | || | | ||| | +-> | | 65 * | || | | ||| +-------+ +-----+ | | | | 66 * | || | | |+-> | exit | - | ... | --+ +-----+-----+ 67 * | || | | | | +-------+ +-----+ | | 68 * | || | | | | | | 69 * | || +-----------+ | | +-----+ | | | | 70 * | +-> | workqueue | -----> | ... | | | | | 71 * | | +-----------+ | | +-----+ | | | | 72 * | +==================+ +============+ +======================+ | 73 * | | 74 * +----> atom_page_list ---------------------------------------------------------+ 75 * 76 */ 77 78 struct kwork_atom { 79 struct list_head list; 80 u64 time; 81 struct kwork_atom *prev; 82 83 void *page_addr; 84 unsigned long bit_inpage; 85 }; 86 87 #define NR_ATOM_PER_PAGE 128 88 struct kwork_atom_page { 89 struct list_head list; 90 struct kwork_atom atoms[NR_ATOM_PER_PAGE]; 91 DECLARE_BITMAP(bitmap, NR_ATOM_PER_PAGE); 92 }; 93 94 struct kwork_class; 95 struct kwork_work { 96 /* 97 * class field 98 */ 99 struct rb_node node; 100 struct kwork_class *class; 101 102 /* 103 * work field 104 */ 105 u64 id; 106 int cpu; 107 char *name; 108 109 /* 110 * atom field 111 */ 112 u64 nr_atoms; 113 struct list_head atom_list[KWORK_TRACE_MAX]; 114 115 /* 116 * runtime report 117 */ 118 u64 max_runtime; 119 u64 max_runtime_start; 120 u64 max_runtime_end; 121 u64 total_runtime; 122 123 /* 124 * latency report 125 */ 126 u64 max_latency; 127 u64 max_latency_start; 128 u64 max_latency_end; 129 u64 total_latency; 130 }; 131 132 struct kwork_class { 133 struct list_head list; 134 const char *name; 135 enum kwork_class_type type; 136 137 unsigned int nr_tracepoints; 138 const struct evsel_str_handler *tp_handlers; 139 140 struct rb_root_cached work_root; 141 142 int (*class_init)(struct kwork_class *class, 143 struct perf_session *session); 144 145 void (*work_init)(struct kwork_class *class, 146 struct kwork_work *work, 147 struct evsel *evsel, 148 struct perf_sample *sample, 149 struct machine *machine); 150 151 void (*work_name)(struct kwork_work *work, 152 char *buf, int len); 153 }; 154 155 struct perf_kwork; 156 struct trace_kwork_handler { 157 int (*raise_event)(struct perf_kwork *kwork, 158 struct kwork_class *class, struct evsel *evsel, 159 struct perf_sample *sample, struct machine *machine); 160 161 int (*entry_event)(struct perf_kwork *kwork, 162 struct kwork_class *class, struct evsel *evsel, 163 struct perf_sample *sample, struct machine *machine); 164 165 int (*exit_event)(struct perf_kwork *kwork, 166 struct kwork_class *class, struct evsel *evsel, 167 struct perf_sample *sample, struct machine *machine); 168 }; 169 170 struct perf_kwork { 171 /* 172 * metadata 173 */ 174 struct perf_tool tool; 175 struct list_head class_list; 176 struct list_head atom_page_list; 177 struct list_head sort_list, cmp_id; 178 struct rb_root_cached sorted_work_root; 179 const struct trace_kwork_handler *tp_handler; 180 181 /* 182 * profile filters 183 */ 184 const char *profile_name; 185 186 const char *cpu_list; 187 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 188 189 const char *time_str; 190 struct perf_time_interval ptime; 191 192 /* 193 * options for command 194 */ 195 bool force; 196 const char *event_list_str; 197 enum kwork_report_type report; 198 199 /* 200 * options for subcommand 201 */ 202 bool summary; 203 const char *sort_order; 204 bool show_callchain; 205 unsigned int max_stack; 206 bool use_bpf; 207 208 /* 209 * statistics 210 */ 211 u64 timestart; 212 u64 timeend; 213 214 unsigned long nr_events; 215 unsigned long nr_lost_chunks; 216 unsigned long nr_lost_events; 217 218 u64 all_runtime; 219 u64 all_count; 220 u64 nr_skipped_events[KWORK_TRACE_MAX + 1]; 221 }; 222 223 struct kwork_work *perf_kwork_add_work(struct perf_kwork *kwork, 224 struct kwork_class *class, 225 struct kwork_work *key); 226 227 #ifdef HAVE_BPF_SKEL 228 229 int perf_kwork__trace_prepare_bpf(struct perf_kwork *kwork); 230 int perf_kwork__report_read_bpf(struct perf_kwork *kwork); 231 void perf_kwork__report_cleanup_bpf(void); 232 233 void perf_kwork__trace_start(void); 234 void perf_kwork__trace_finish(void); 235 236 #else /* !HAVE_BPF_SKEL */ 237 238 static inline int 239 perf_kwork__trace_prepare_bpf(struct perf_kwork *kwork __maybe_unused) 240 { 241 return -1; 242 } 243 244 static inline int 245 perf_kwork__report_read_bpf(struct perf_kwork *kwork __maybe_unused) 246 { 247 return -1; 248 } 249 250 static inline void perf_kwork__report_cleanup_bpf(void) {} 251 252 static inline void perf_kwork__trace_start(void) {} 253 static inline void perf_kwork__trace_finish(void) {} 254 255 #endif /* HAVE_BPF_SKEL */ 256 257 #endif /* PERF_UTIL_KWORK_H */ 258