Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Copyright (c) 2022 Meta Platforms, Inc. and affiliates.
4 * Copyright (c) 2022 Tejun Heo <tj@kernel.org>
5 * Copyright (c) 2022 David Vernet <dvernet@meta.com>
6 */
7#define _GNU_SOURCE
8#include <stdio.h>
9#include <unistd.h>
10#include <inttypes.h>
11#include <signal.h>
12#include <assert.h>
13#include <libgen.h>
14#include <bpf/bpf.h>
15#include <scx/common.h>
16#include "scx_central.bpf.skel.h"
17
18const char help_fmt[] =
19"A central FIFO sched_ext scheduler.\n"
20"\n"
21"See the top-level comment in .bpf.c for more details.\n"
22"\n"
23"Usage: %s [-s SLICE_US] [-c CPU] [-v]\n"
24"\n"
25" -s SLICE_US Override slice duration\n"
26" -c CPU Override the central CPU (default: 0)\n"
27" -v Print libbpf debug messages\n"
28" -h Display this help and exit\n";
29
30static bool verbose;
31static volatile int exit_req;
32
33static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args)
34{
35 if (level == LIBBPF_DEBUG && !verbose)
36 return 0;
37 return vfprintf(stderr, format, args);
38}
39
40static void sigint_handler(int dummy)
41{
42 exit_req = 1;
43}
44
45int main(int argc, char **argv)
46{
47 struct scx_central *skel;
48 struct bpf_link *link;
49 __u64 seq = 0, ecode;
50 __s32 opt;
51
52 libbpf_set_print(libbpf_print_fn);
53 signal(SIGINT, sigint_handler);
54 signal(SIGTERM, sigint_handler);
55restart:
56 optind = 1;
57 skel = SCX_OPS_OPEN(central_ops, scx_central);
58
59 skel->rodata->central_cpu = 0;
60 skel->rodata->nr_cpu_ids = libbpf_num_possible_cpus();
61 skel->rodata->slice_ns = __COMPAT_ENUM_OR_ZERO("scx_public_consts", "SCX_SLICE_DFL");
62
63 assert(skel->rodata->nr_cpu_ids > 0);
64 assert(skel->rodata->nr_cpu_ids <= INT32_MAX);
65
66 while ((opt = getopt(argc, argv, "s:c:vh")) != -1) {
67 switch (opt) {
68 case 's':
69 skel->rodata->slice_ns = strtoull(optarg, NULL, 0) * 1000;
70 break;
71 case 'c': {
72 u32 central_cpu = strtoul(optarg, NULL, 0);
73 if (central_cpu >= skel->rodata->nr_cpu_ids) {
74 fprintf(stderr, "invalid central CPU id value, %u given (%u max)\n", central_cpu, skel->rodata->nr_cpu_ids);
75 scx_central__destroy(skel);
76 return -1;
77 }
78 skel->rodata->central_cpu = (s32)central_cpu;
79 break;
80 }
81 case 'v':
82 verbose = true;
83 break;
84 default:
85 fprintf(stderr, help_fmt, basename(argv[0]));
86 return opt != 'h';
87 }
88 }
89
90 /* Resize arrays so their element count is equal to cpu count. */
91 RESIZE_ARRAY(skel, data, cpu_gimme_task, skel->rodata->nr_cpu_ids);
92 RESIZE_ARRAY(skel, data, cpu_started_at, skel->rodata->nr_cpu_ids);
93
94 SCX_OPS_LOAD(skel, central_ops, scx_central, uei);
95
96 link = SCX_OPS_ATTACH(skel, central_ops, scx_central);
97
98 if (!skel->data->timer_pinned)
99 printf("WARNING : BPF_F_TIMER_CPU_PIN not available, timer not pinned to central\n");
100
101 while (!exit_req && !UEI_EXITED(skel, uei)) {
102 printf("[SEQ %llu]\n", seq++);
103 printf("total :%10" PRIu64 " local:%10" PRIu64 " queued:%10" PRIu64 " lost:%10" PRIu64 "\n",
104 skel->bss->nr_total,
105 skel->bss->nr_locals,
106 skel->bss->nr_queued,
107 skel->bss->nr_lost_pids);
108 printf("timer :%10" PRIu64 " dispatch:%10" PRIu64 " mismatch:%10" PRIu64 " retry:%10" PRIu64 "\n",
109 skel->bss->nr_timers,
110 skel->bss->nr_dispatches,
111 skel->bss->nr_mismatches,
112 skel->bss->nr_retries);
113 printf("overflow:%10" PRIu64 "\n",
114 skel->bss->nr_overflows);
115 fflush(stdout);
116 sleep(1);
117 }
118
119 bpf_link__destroy(link);
120 ecode = UEI_REPORT(skel, uei);
121 scx_central__destroy(skel);
122
123 if (UEI_ECODE_RESTART(ecode))
124 goto restart;
125 return 0;
126}