Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/sched_ext/scx_central.c
26282 views
1
/* SPDX-License-Identifier: GPL-2.0 */
2
/*
3
* Copyright (c) 2022 Meta Platforms, Inc. and affiliates.
4
* Copyright (c) 2022 Tejun Heo <[email protected]>
5
* Copyright (c) 2022 David Vernet <[email protected]>
6
*/
7
#define _GNU_SOURCE
8
#include <sched.h>
9
#include <stdio.h>
10
#include <unistd.h>
11
#include <inttypes.h>
12
#include <signal.h>
13
#include <assert.h>
14
#include <libgen.h>
15
#include <bpf/bpf.h>
16
#include <scx/common.h>
17
#include "scx_central.bpf.skel.h"
18
19
const char help_fmt[] =
20
"A central FIFO sched_ext scheduler.\n"
21
"\n"
22
"See the top-level comment in .bpf.c for more details.\n"
23
"\n"
24
"Usage: %s [-s SLICE_US] [-c CPU]\n"
25
"\n"
26
" -s SLICE_US Override slice duration\n"
27
" -c CPU Override the central CPU (default: 0)\n"
28
" -v Print libbpf debug messages\n"
29
" -h Display this help and exit\n";
30
31
static bool verbose;
32
static volatile int exit_req;
33
34
static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args)
35
{
36
if (level == LIBBPF_DEBUG && !verbose)
37
return 0;
38
return vfprintf(stderr, format, args);
39
}
40
41
static void sigint_handler(int dummy)
42
{
43
exit_req = 1;
44
}
45
46
int main(int argc, char **argv)
47
{
48
struct scx_central *skel;
49
struct bpf_link *link;
50
__u64 seq = 0, ecode;
51
__s32 opt;
52
cpu_set_t *cpuset;
53
54
libbpf_set_print(libbpf_print_fn);
55
signal(SIGINT, sigint_handler);
56
signal(SIGTERM, sigint_handler);
57
restart:
58
skel = SCX_OPS_OPEN(central_ops, scx_central);
59
60
skel->rodata->central_cpu = 0;
61
skel->rodata->nr_cpu_ids = libbpf_num_possible_cpus();
62
skel->rodata->slice_ns = __COMPAT_ENUM_OR_ZERO("scx_public_consts", "SCX_SLICE_DFL");
63
64
assert(skel->rodata->nr_cpu_ids <= INT32_MAX);
65
66
while ((opt = getopt(argc, argv, "s:c:pvh")) != -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
return -1;
76
}
77
skel->rodata->central_cpu = (s32)central_cpu;
78
break;
79
}
80
case 'v':
81
verbose = true;
82
break;
83
default:
84
fprintf(stderr, help_fmt, basename(argv[0]));
85
return opt != 'h';
86
}
87
}
88
89
/* Resize arrays so their element count is equal to cpu count. */
90
RESIZE_ARRAY(skel, data, cpu_gimme_task, skel->rodata->nr_cpu_ids);
91
RESIZE_ARRAY(skel, data, cpu_started_at, skel->rodata->nr_cpu_ids);
92
93
SCX_OPS_LOAD(skel, central_ops, scx_central, uei);
94
95
/*
96
* Affinitize the loading thread to the central CPU, as:
97
* - That's where the BPF timer is first invoked in the BPF program.
98
* - We probably don't want this user space component to take up a core
99
* from a task that would benefit from avoiding preemption on one of
100
* the tickless cores.
101
*
102
* Until BPF supports pinning the timer, it's not guaranteed that it
103
* will always be invoked on the central CPU. In practice, this
104
* suffices the majority of the time.
105
*/
106
cpuset = CPU_ALLOC(skel->rodata->nr_cpu_ids);
107
SCX_BUG_ON(!cpuset, "Failed to allocate cpuset");
108
CPU_ZERO_S(CPU_ALLOC_SIZE(skel->rodata->nr_cpu_ids), cpuset);
109
CPU_SET(skel->rodata->central_cpu, cpuset);
110
SCX_BUG_ON(sched_setaffinity(0, sizeof(*cpuset), cpuset),
111
"Failed to affinitize to central CPU %d (max %d)",
112
skel->rodata->central_cpu, skel->rodata->nr_cpu_ids - 1);
113
CPU_FREE(cpuset);
114
115
link = SCX_OPS_ATTACH(skel, central_ops, scx_central);
116
117
if (!skel->data->timer_pinned)
118
printf("WARNING : BPF_F_TIMER_CPU_PIN not available, timer not pinned to central\n");
119
120
while (!exit_req && !UEI_EXITED(skel, uei)) {
121
printf("[SEQ %llu]\n", seq++);
122
printf("total :%10" PRIu64 " local:%10" PRIu64 " queued:%10" PRIu64 " lost:%10" PRIu64 "\n",
123
skel->bss->nr_total,
124
skel->bss->nr_locals,
125
skel->bss->nr_queued,
126
skel->bss->nr_lost_pids);
127
printf("timer :%10" PRIu64 " dispatch:%10" PRIu64 " mismatch:%10" PRIu64 " retry:%10" PRIu64 "\n",
128
skel->bss->nr_timers,
129
skel->bss->nr_dispatches,
130
skel->bss->nr_mismatches,
131
skel->bss->nr_retries);
132
printf("overflow:%10" PRIu64 "\n",
133
skel->bss->nr_overflows);
134
fflush(stdout);
135
sleep(1);
136
}
137
138
bpf_link__destroy(link);
139
ecode = UEI_REPORT(skel, uei);
140
scx_central__destroy(skel);
141
142
if (UEI_ECODE_RESTART(ecode))
143
goto restart;
144
return 0;
145
}
146
147