// SPDX-License-Identifier: GPL-2.0 /* scx_perfprobe userspace - prints one line per second with every * CPU's rq->scx.cpuperf_target. */ #include #include #include #include #include #include #include "scx_perfprobe.bpf.skel.h" #define K2_MAX_CPUS 128 static volatile int exit_req; static void sig_handler(int sig) { exit_req = 1; } int main(int argc, char **argv) { struct scx_perfprobe *skel; struct bpf_link *link; long online = sysconf(_SC_NPROCESSORS_ONLN); unsigned long sec = 0; signal(SIGINT, sig_handler); signal(SIGTERM, sig_handler); skel = scx_perfprobe__open(); if (!skel) { fprintf(stderr, "perfprobe: open failed\n"); return 1; } if (scx_perfprobe__load(skel)) { fprintf(stderr, "perfprobe: load failed\n"); return 1; } link = bpf_program__attach(skel->progs.k2_sample_tick); if (libbpf_get_error(link)) { fprintf(stderr, "perfprobe: attach failed\n"); return 1; } while (!exit_req) { char line[1024]; int n = 0, cpu; n += snprintf(line + n, sizeof(line) - n, "[T+%lus]", ++sec); for (cpu = 0; cpu < online && cpu < K2_MAX_CPUS; cpu++) { u64 v = 0; u32 key = cpu; bpf_map_lookup_elem(bpf_map__fd(skel->maps.targets), &key, &v); u64 tk = 0; bpf_map_lookup_elem(bpf_map__fd(skel->maps.tickcnt), &key, &tk); n += snprintf(line + n, sizeof(line) - n, " c%d=%llu/t%llu", cpu, (unsigned long long)v, (unsigned long long)tk); } printf("%s\n", line); fflush(stdout); sleep(1); } bpf_link__destroy(link); scx_perfprobe__destroy(skel); return 0; }