Something went wrong. Try again.
(I'm so sorry!) Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327#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 */