326 lines · 8.8 KB · C
RawDownload
#ifndef PERF_UTIL_KWORK_H#define PERF_UTIL_KWORK_H #include "perf.h"#include "util/tool.h"#include "util/time-utils.h" #include <stdlib.h>#include <linux/bitmap.h>#include <linux/list.h>#include <linux/rbtree.h>#include <linux/types.h> struct perf_sample;struct perf_session; enum kwork_class_type {	KWORK_CLASS_IRQ,	KWORK_CLASS_SOFTIRQ,	KWORK_CLASS_WORKQUEUE,	KWORK_CLASS_SCHED,	KWORK_CLASS_MAX,}; enum kwork_report_type {	KWORK_REPORT_RUNTIME,	KWORK_REPORT_LATENCY,	KWORK_REPORT_TIMEHIST,	KWORK_REPORT_TOP,}; enum kwork_trace_type {	KWORK_TRACE_RAISE,	KWORK_TRACE_ENTRY,	KWORK_TRACE_EXIT,	KWORK_TRACE_MAX,}; /* * data structure: * *                 +==================+ +============+ +======================+ *                 |      class       | |    work    | |         atom         | *                 +==================+ +============+ +======================+ * +------------+  |  +-----+         | |  +------+  | |  +-------+   +-----+ | * | perf_kwork | +-> | irq | --------|+-> | eth0 | --+-> | raise | - | ... | --+   +-----------+ * +-----+------+ ||  +-----+         |||  +------+  |||  +-------+   +-----+ | |   |           | *       |        ||                  |||            |||                      | +-> | atom_page | *       |        ||                  |||            |||  +-------+   +-----+ |     |           | *       |  class_list                |||            |+-> | entry | - | ... | ----> |           | *       |        ||                  |||            |||  +-------+   +-----+ |     |           | *       |        ||                  |||            |||                      | +-> |           | *       |        ||                  |||            |||  +-------+   +-----+ | |   |           | *       |        ||                  |||            |+-> | exit  | - | ... | --+   +-----+-----+ *       |        ||                  |||            | |  +-------+   +-----+ |           | *       |        ||                  |||            | |                      |           | *       |        ||                  |||  +-----+   | |                      |           | *       |        ||                  |+-> | ... |   | |                      |           | *       |        ||                  | |  +-----+   | |                      |           | *       |        ||                  | |            | |                      |           | *       |        ||  +---------+     | |  +-----+   | |  +-------+   +-----+ |           | *       |        +-> | softirq | -------> | RCU | ---+-> | raise | - | ... | --+   +-----+-----+ *       |        ||  +---------+     | |  +-----+   |||  +-------+   +-----+ | |   |           | *       |        ||                  | |            |||                      | +-> | atom_page | *       |        ||                  | |            |||  +-------+   +-----+ |     |           | *       |        ||                  | |            |+-> | entry | - | ... | ----> |           | *       |        ||                  | |            |||  +-------+   +-----+ |     |           | *       |        ||                  | |            |||                      | +-> |           | *       |        ||                  | |            |||  +-------+   +-----+ | |   |           | *       |        ||                  | |            |+-> | exit  | - | ... | --+   +-----+-----+ *       |        ||                  | |            | |  +-------+   +-----+ |           | *       |        ||                  | |            | |                      |           | *       |        ||  +-----------+   | |  +-----+   | |                      |           | *       |        +-> | workqueue | -----> | ... |   | |                      |           | *       |         |  +-----------+   | |  +-----+   | |                      |           | *       |         +==================+ +============+ +======================+           | *       |                                                                                | *       +---->  atom_page_list  ---------------------------------------------------------+ * */ struct kwork_atom {	struct list_head list;	u64 time;	struct kwork_atom *prev; 	void *page_addr;	unsigned long bit_inpage;}; #define NR_ATOM_PER_PAGE 128struct kwork_atom_page {	struct list_head list;	struct kwork_atom atoms[NR_ATOM_PER_PAGE];	DECLARE_BITMAP(bitmap, NR_ATOM_PER_PAGE);}; struct perf_kwork;struct kwork_class;struct kwork_work {	/*	 * class field	 */	struct rb_node node;	struct kwork_class *class; 	/*	 * work field	 */	u64 id;	int cpu;	char *name; 	/*	 * atom field	 */	u64 nr_atoms;	struct list_head atom_list[KWORK_TRACE_MAX]; 	/*	 * runtime report	 */	u64 max_runtime;	u64 max_runtime_start;	u64 max_runtime_end;	u64 total_runtime; 	/*	 * latency report	 */	u64 max_latency;	u64 max_latency_start;	u64 max_latency_end;	u64 total_latency; 	/*	 * top report	 */	u32 cpu_usage;	u32 tgid;	bool is_kthread;}; struct kwork_class {	struct list_head list;	const char *name;	enum kwork_class_type type; 	unsigned int nr_tracepoints;	const struct evsel_str_handler *tp_handlers; 	struct rb_root_cached work_root; 	int (*class_init)(struct kwork_class *class,			  struct perf_session *session); 	void (*work_init)(struct perf_kwork *kwork,			  struct kwork_class *class,			  struct kwork_work *work,			  enum kwork_trace_type src_type,			  struct perf_sample *sample,			  struct machine *machine); 	void (*work_name)(struct kwork_work *work,			  char *buf, int len);}; static inline void work_exit(struct kwork_work *work){	if (work) {		free(work->name);		work->name = NULL;	}} struct trace_kwork_handler {	int (*raise_event)(struct perf_kwork *kwork,			   struct kwork_class *class,			   struct perf_sample *sample, struct machine *machine); 	int (*entry_event)(struct perf_kwork *kwork,			   struct kwork_class *class,			   struct perf_sample *sample, struct machine *machine); 	int (*exit_event)(struct perf_kwork *kwork,			  struct kwork_class *class,			  struct perf_sample *sample, struct machine *machine); 	int (*sched_switch_event)(struct perf_kwork *kwork,				  struct kwork_class *class,				  struct perf_sample *sample, struct machine *machine);}; struct __top_cpus_runtime {	u64 load;	u64 idle;	u64 irq;	u64 softirq;	u64 total;}; struct kwork_top_stat {	DECLARE_BITMAP(all_cpus_bitmap, MAX_NR_CPUS);	struct __top_cpus_runtime *cpus_runtime;	unsigned int nr_skipped_cpu;}; struct perf_kwork {	/*	 * metadata	 */	struct perf_tool tool;	struct list_head class_list;	struct list_head atom_page_list;	struct list_head sort_list, cmp_id;	struct rb_root_cached sorted_work_root;	const struct trace_kwork_handler *tp_handler; 	/*	 * profile filters	 */	const char *profile_name; 	const char *cpu_list;	DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 	const char *time_str;	struct perf_time_interval ptime; 	/*	 * options for command	 */	bool force;	const char *event_list_str;	enum kwork_report_type report; 	/*	 * options for subcommand	 */	bool summary;	const char *sort_order;	bool show_callchain;	unsigned int max_stack;	bool use_bpf; 	/*	 * statistics	 */	u64 timestart;	u64 timeend; 	unsigned long nr_events;	unsigned long nr_lost_chunks;	unsigned long nr_lost_events; 	u64 all_runtime;	u64 all_count;	u64 nr_skipped_events[KWORK_TRACE_MAX + 1]; 	/*	 * perf kwork top data	 */	struct kwork_top_stat top_stat; 	/* Add work callback. */	struct kwork_work *(*add_work)(struct perf_kwork *kwork,				       struct kwork_class *class,				       struct kwork_work *key); }; #ifdef HAVE_BPF_SKEL int perf_kwork__trace_prepare_bpf(struct perf_kwork *kwork);int perf_kwork__report_read_bpf(struct perf_kwork *kwork);void perf_kwork__report_cleanup_bpf(void); void perf_kwork__trace_start(void);void perf_kwork__trace_finish(void); int perf_kwork__top_prepare_bpf(struct perf_kwork *kwork);int perf_kwork__top_read_bpf(struct perf_kwork *kwork);void perf_kwork__top_cleanup_bpf(void); void perf_kwork__top_start(void);void perf_kwork__top_finish(void); #else  /* !HAVE_BPF_SKEL */ static inline intperf_kwork__trace_prepare_bpf(struct perf_kwork *kwork __maybe_unused){	return -1;} static inline intperf_kwork__report_read_bpf(struct perf_kwork *kwork __maybe_unused){	return -1;} static inline void perf_kwork__report_cleanup_bpf(void) {} static inline void perf_kwork__trace_start(void) {}static inline void perf_kwork__trace_finish(void) {} static inline intperf_kwork__top_prepare_bpf(struct perf_kwork *kwork __maybe_unused){	return -1;} static inline intperf_kwork__top_read_bpf(struct perf_kwork *kwork __maybe_unused){	return -1;} static inline void perf_kwork__top_cleanup_bpf(void) {} static inline void perf_kwork__top_start(void) {}static inline void perf_kwork__top_finish(void) {} #endif  /* HAVE_BPF_SKEL */ #endif  /* PERF_UTIL_KWORK_H */