From 51dc1020b7dff86dca9cf4b2cd74f2c88ac75131 Mon Sep 17 00:00:00 2001 From: Dantezy Date: Sat, 14 Sep 2024 16:30:19 +0800 Subject: [PATCH] libbpf-tools/hardirqs: add `--cpu/-s` for hardirqs Signed-off-by: Dantezy --- libbpf-tools/hardirqs.bpf.c | 17 +++++++++-- libbpf-tools/hardirqs.c | 59 +++++++++++++++++++++++-------------- 2 files changed, 52 insertions(+), 24 deletions(-) diff --git a/libbpf-tools/hardirqs.bpf.c b/libbpf-tools/hardirqs.bpf.c index cbcbd5c05158..898fefa17164 100644 --- a/libbpf-tools/hardirqs.bpf.c +++ b/libbpf-tools/hardirqs.bpf.c @@ -14,6 +14,7 @@ const volatile bool filter_cg = false; const volatile bool targ_dist = false; const volatile bool targ_ns = false; const volatile bool do_count = false; +const volatile bool targ_cpu = -1; struct { __uint(type, BPF_MAP_TYPE_CGROUP_ARRAY); @@ -38,12 +39,21 @@ struct { static struct info zero; +static __always_inline bool is_target_cpu() { + if (targ_cpu < 0) + return true; + + return (u32)targ_cpu == bpf_get_smp_processor_id(); +} + static int handle_entry(int irq, struct irqaction *action) { if (filter_cg && !bpf_current_task_under_cgroup(&cgroup_map, 0)) return 0; + if (!is_target_cpu()) + return 0; - if (do_count) { + if (do_count) { struct irq_key key = {}; struct info *info; @@ -76,7 +86,10 @@ static int handle_exit(int irq, struct irqaction *action) if (filter_cg && !bpf_current_task_under_cgroup(&cgroup_map, 0)) return 0; - tsp = bpf_map_lookup_elem(&start, &key); + if (!is_target_cpu()) + return 0; + + tsp = bpf_map_lookup_elem(&start, &key); if (!tsp) return 0; diff --git a/libbpf-tools/hardirqs.c b/libbpf-tools/hardirqs.c index b5257d95089a..a5e4c212c6c3 100644 --- a/libbpf-tools/hardirqs.c +++ b/libbpf-tools/hardirqs.c @@ -27,9 +27,11 @@ struct env { bool verbose; char *cgroupspath; bool cg; + int targ_cpu; } env = { - .interval = 99999999, - .times = 99999999, + .interval = 99999999, + .times = 99999999, + .targ_cpu = -1, }; static volatile bool exiting; @@ -38,26 +40,29 @@ const char *argp_program_version = "hardirqs 0.1"; const char *argp_program_bug_address = "https://github.com/iovisor/bcc/tree/master/libbpf-tools"; const char argp_program_doc[] = -"Summarize hard irq event time as histograms.\n" -"\n" -"USAGE: hardirqs [--help] [-T] [-N] [-d] [interval] [count] [-c CG]\n" -"\n" -"EXAMPLES:\n" -" hardirqs # sum hard irq event time\n" -" hardirqs -d # show hard irq event time as histograms\n" -" hardirqs 1 10 # print 1 second summaries, 10 times\n" -" hardirqs -c CG # Trace process under cgroupsPath CG\n" -" hardirqs -NT 1 # 1s summaries, nanoseconds, and timestamps\n"; + "Summarize hard irq event time as histograms.\n" + "\n" + "USAGE: hardirqs [--help] [-T] [-N] [-d] [interval] [count] [-c CG]\n" + "\n" + "EXAMPLES:\n" + " hardirqs # sum hard irq event time\n" + " hardirqs -d # show hard irq event time as histograms\n" + " hardirqs 1 10 # print 1 second summaries, 10 times\n" + " hardirqs -c CG # Trace process under cgroupsPath CG\n" + " hardirqs --cpu 1 # only stat irq on cpu 1\n" + " hardirqs -NT 1 # 1s summaries, nanoseconds, and timestamps\n"; static const struct argp_option opts[] = { - { "count", 'C', NULL, 0, "Show event counts instead of timing", 0 }, - { "distributed", 'd', NULL, 0, "Show distributions as histograms", 0 }, - { "cgroup", 'c', "/sys/fs/cgroup/unified", 0, "Trace process in cgroup path", 0 }, - { "timestamp", 'T', NULL, 0, "Include timestamp on output", 0 }, - { "nanoseconds", 'N', NULL, 0, "Output in nanoseconds", 0 }, - { "verbose", 'v', NULL, 0, "Verbose debug output", 0 }, - { NULL, 'h', NULL, OPTION_HIDDEN, "Show the full help", 0 }, - {}, + {"count", 'C', NULL, 0, "Show event counts instead of timing", 0}, + {"distributed", 'd', NULL, 0, "Show distributions as histograms", 0}, + {"cgroup", 'c', "/sys/fs/cgroup/unified", 0, "Trace process in cgroup path", + 0}, + {"cpu", 's', "CPU", 0, "Only stat irq on selected cpu", 0}, + {"timestamp", 'T', NULL, 0, "Include timestamp on output", 0}, + {"nanoseconds", 'N', NULL, 0, "Output in nanoseconds", 0}, + {"verbose", 'v', NULL, 0, "Verbose debug output", 0}, + {NULL, 'h', NULL, OPTION_HIDDEN, "Show the full help", 0}, + {}, }; static error_t parse_arg(int key, char *arg, struct argp_state *state) @@ -77,7 +82,16 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state) case 'C': env.count = true; break; - case 'c': + case 's': + errno = 0; + long c = strtol(arg, NULL, 10); + if (errno || c < 0) { + fprintf(stderr, "invalid cpu: %s\n", arg); + argp_usage(state); + } + env.targ_cpu = (int)c; + break; + case 'c': env.cgroupspath = arg; env.cg = true; break; @@ -218,8 +232,9 @@ int main(int argc, char **argv) obj->rodata->filter_cg = env.cg; obj->rodata->do_count = env.count; + obj->rodata->targ_cpu = env.targ_cpu; - /* initialize global data (filtering options) */ + /* initialize global data (filtering options) */ if (!env.count) { obj->rodata->targ_dist = env.distributed; obj->rodata->targ_ns = env.nanoseconds;