1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3 * Copyright (c) 2025 Meta Platforms, Inc. and affiliates.
4 * Copyright (c) 2025 Tejun Heo <tj@kernel.org>
5 */
6 #include <stdio.h>
7 #include <unistd.h>
8 #include <signal.h>
9 #include <assert.h>
10 #include <libgen.h>
11 #include <bpf/bpf.h>
12 #include <scx/common.h>
13 #include "scx_cpu0.bpf.skel.h"
14
15 const char help_fmt[] =
16 "A cpu0 sched_ext scheduler.\n"
17 "\n"
18 "See the top-level comment in .bpf.c for more details.\n"
19 "\n"
20 "Usage: %s [-v]\n"
21 "\n"
22 " -v Print libbpf debug messages\n"
23 " -h Display this help and exit\n";
24
25 static bool verbose;
26 static volatile int exit_req;
27
libbpf_print_fn(enum libbpf_print_level level,const char * format,va_list args)28 static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args)
29 {
30 if (level == LIBBPF_DEBUG && !verbose)
31 return 0;
32 return vfprintf(stderr, format, args);
33 }
34
sigint_handler(int sig)35 static void sigint_handler(int sig)
36 {
37 exit_req = 1;
38 }
39
read_stats(struct scx_cpu0 * skel,__u64 * stats)40 static void read_stats(struct scx_cpu0 *skel, __u64 *stats)
41 {
42 int nr_cpus = libbpf_num_possible_cpus();
43 assert(nr_cpus > 0);
44 __u64 cnts[2][nr_cpus];
45 __u32 idx;
46
47 memset(stats, 0, sizeof(stats[0]) * 2);
48
49 for (idx = 0; idx < 2; idx++) {
50 int ret, cpu;
51
52 ret = bpf_map_lookup_elem(bpf_map__fd(skel->maps.stats),
53 &idx, cnts[idx]);
54 if (ret < 0)
55 continue;
56 for (cpu = 0; cpu < nr_cpus; cpu++)
57 stats[idx] += cnts[idx][cpu];
58 }
59 }
60
main(int argc,char ** argv)61 int main(int argc, char **argv)
62 {
63 struct scx_cpu0 *skel;
64 struct bpf_link *link;
65 __u32 opt;
66 __u64 ecode;
67
68 libbpf_set_print(libbpf_print_fn);
69 signal(SIGINT, sigint_handler);
70 signal(SIGTERM, sigint_handler);
71 restart:
72 optind = 1;
73 skel = SCX_OPS_OPEN(cpu0_ops, scx_cpu0);
74
75 skel->rodata->nr_cpus = libbpf_num_possible_cpus();
76
77 while ((opt = getopt(argc, argv, "vh")) != -1) {
78 switch (opt) {
79 case 'v':
80 verbose = true;
81 break;
82 default:
83 fprintf(stderr, help_fmt, basename(argv[0]));
84 return opt != 'h';
85 }
86 }
87
88 SCX_OPS_LOAD(skel, cpu0_ops, scx_cpu0, uei);
89 link = SCX_OPS_ATTACH(skel, cpu0_ops, scx_cpu0);
90
91 while (!exit_req && !UEI_EXITED(skel, uei)) {
92 __u64 stats[2];
93
94 read_stats(skel, stats);
95 printf("local=%llu cpu0=%llu\n", stats[0], stats[1]);
96 fflush(stdout);
97 sleep(1);
98 }
99
100 bpf_link__destroy(link);
101 ecode = UEI_REPORT(skel, uei);
102 scx_cpu0__destroy(skel);
103
104 if (UEI_ECODE_RESTART(ecode))
105 goto restart;
106 return 0;
107 }
108