Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/sched_ext/include/scx/compat.h
26295 views
1
/* SPDX-License-Identifier: GPL-2.0 */
2
/*
3
* Copyright (c) 2024 Meta Platforms, Inc. and affiliates.
4
* Copyright (c) 2024 Tejun Heo <[email protected]>
5
* Copyright (c) 2024 David Vernet <[email protected]>
6
*/
7
#ifndef __SCX_COMPAT_H
8
#define __SCX_COMPAT_H
9
10
#include <bpf/btf.h>
11
#include <fcntl.h>
12
#include <stdlib.h>
13
#include <unistd.h>
14
15
struct btf *__COMPAT_vmlinux_btf __attribute__((weak));
16
17
static inline void __COMPAT_load_vmlinux_btf(void)
18
{
19
if (!__COMPAT_vmlinux_btf) {
20
__COMPAT_vmlinux_btf = btf__load_vmlinux_btf();
21
SCX_BUG_ON(!__COMPAT_vmlinux_btf, "btf__load_vmlinux_btf()");
22
}
23
}
24
25
static inline bool __COMPAT_read_enum(const char *type, const char *name, u64 *v)
26
{
27
const struct btf_type *t;
28
const char *n;
29
s32 tid;
30
int i;
31
32
__COMPAT_load_vmlinux_btf();
33
34
tid = btf__find_by_name(__COMPAT_vmlinux_btf, type);
35
if (tid < 0)
36
return false;
37
38
t = btf__type_by_id(__COMPAT_vmlinux_btf, tid);
39
SCX_BUG_ON(!t, "btf__type_by_id(%d)", tid);
40
41
if (btf_is_enum(t)) {
42
struct btf_enum *e = btf_enum(t);
43
44
for (i = 0; i < BTF_INFO_VLEN(t->info); i++) {
45
n = btf__name_by_offset(__COMPAT_vmlinux_btf, e[i].name_off);
46
SCX_BUG_ON(!n, "btf__name_by_offset()");
47
if (!strcmp(n, name)) {
48
*v = e[i].val;
49
return true;
50
}
51
}
52
} else if (btf_is_enum64(t)) {
53
struct btf_enum64 *e = btf_enum64(t);
54
55
for (i = 0; i < BTF_INFO_VLEN(t->info); i++) {
56
n = btf__name_by_offset(__COMPAT_vmlinux_btf, e[i].name_off);
57
SCX_BUG_ON(!n, "btf__name_by_offset()");
58
if (!strcmp(n, name)) {
59
*v = btf_enum64_value(&e[i]);
60
return true;
61
}
62
}
63
}
64
65
return false;
66
}
67
68
#define __COMPAT_ENUM_OR_ZERO(__type, __ent) \
69
({ \
70
u64 __val = 0; \
71
__COMPAT_read_enum(__type, __ent, &__val); \
72
__val; \
73
})
74
75
static inline bool __COMPAT_has_ksym(const char *ksym)
76
{
77
__COMPAT_load_vmlinux_btf();
78
return btf__find_by_name(__COMPAT_vmlinux_btf, ksym) >= 0;
79
}
80
81
static inline bool __COMPAT_struct_has_field(const char *type, const char *field)
82
{
83
const struct btf_type *t;
84
const struct btf_member *m;
85
const char *n;
86
s32 tid;
87
int i;
88
89
__COMPAT_load_vmlinux_btf();
90
tid = btf__find_by_name_kind(__COMPAT_vmlinux_btf, type, BTF_KIND_STRUCT);
91
if (tid < 0)
92
return false;
93
94
t = btf__type_by_id(__COMPAT_vmlinux_btf, tid);
95
SCX_BUG_ON(!t, "btf__type_by_id(%d)", tid);
96
97
m = btf_members(t);
98
99
for (i = 0; i < BTF_INFO_VLEN(t->info); i++) {
100
n = btf__name_by_offset(__COMPAT_vmlinux_btf, m[i].name_off);
101
SCX_BUG_ON(!n, "btf__name_by_offset()");
102
if (!strcmp(n, field))
103
return true;
104
}
105
106
return false;
107
}
108
109
#define SCX_OPS_FLAG(name) __COMPAT_ENUM_OR_ZERO("scx_ops_flags", #name)
110
111
#define SCX_OPS_KEEP_BUILTIN_IDLE SCX_OPS_FLAG(SCX_OPS_KEEP_BUILTIN_IDLE)
112
#define SCX_OPS_ENQ_LAST SCX_OPS_FLAG(SCX_OPS_ENQ_LAST)
113
#define SCX_OPS_ENQ_EXITING SCX_OPS_FLAG(SCX_OPS_ENQ_EXITING)
114
#define SCX_OPS_SWITCH_PARTIAL SCX_OPS_FLAG(SCX_OPS_SWITCH_PARTIAL)
115
#define SCX_OPS_ENQ_MIGRATION_DISABLED SCX_OPS_FLAG(SCX_OPS_ENQ_MIGRATION_DISABLED)
116
#define SCX_OPS_ALLOW_QUEUED_WAKEUP SCX_OPS_FLAG(SCX_OPS_ALLOW_QUEUED_WAKEUP)
117
#define SCX_OPS_BUILTIN_IDLE_PER_NODE SCX_OPS_FLAG(SCX_OPS_BUILTIN_IDLE_PER_NODE)
118
119
#define SCX_PICK_IDLE_FLAG(name) __COMPAT_ENUM_OR_ZERO("scx_pick_idle_cpu_flags", #name)
120
121
#define SCX_PICK_IDLE_CORE SCX_PICK_IDLE_FLAG(SCX_PICK_IDLE_CORE)
122
#define SCX_PICK_IDLE_IN_NODE SCX_PICK_IDLE_FLAG(SCX_PICK_IDLE_IN_NODE)
123
124
static inline long scx_hotplug_seq(void)
125
{
126
int fd;
127
char buf[32];
128
ssize_t len;
129
long val;
130
131
fd = open("/sys/kernel/sched_ext/hotplug_seq", O_RDONLY);
132
if (fd < 0)
133
return -ENOENT;
134
135
len = read(fd, buf, sizeof(buf) - 1);
136
SCX_BUG_ON(len <= 0, "read failed (%ld)", len);
137
buf[len] = 0;
138
close(fd);
139
140
val = strtoul(buf, NULL, 10);
141
SCX_BUG_ON(val < 0, "invalid num hotplug events: %lu", val);
142
143
return val;
144
}
145
146
/*
147
* struct sched_ext_ops can change over time. If compat.bpf.h::SCX_OPS_DEFINE()
148
* is used to define ops and compat.h::SCX_OPS_LOAD/ATTACH() are used to load
149
* and attach it, backward compatibility is automatically maintained where
150
* reasonable.
151
*
152
* ec7e3b0463e1 ("implement-ops") in https://github.com/sched-ext/sched_ext is
153
* the current minimum required kernel version.
154
*/
155
#define SCX_OPS_OPEN(__ops_name, __scx_name) ({ \
156
struct __scx_name *__skel; \
157
\
158
SCX_BUG_ON(!__COMPAT_struct_has_field("sched_ext_ops", "dump"), \
159
"sched_ext_ops.dump() missing, kernel too old?"); \
160
\
161
__skel = __scx_name##__open(); \
162
SCX_BUG_ON(!__skel, "Could not open " #__scx_name); \
163
__skel->struct_ops.__ops_name->hotplug_seq = scx_hotplug_seq(); \
164
SCX_ENUM_INIT(__skel); \
165
__skel; \
166
})
167
168
#define SCX_OPS_LOAD(__skel, __ops_name, __scx_name, __uei_name) ({ \
169
UEI_SET_SIZE(__skel, __ops_name, __uei_name); \
170
SCX_BUG_ON(__scx_name##__load((__skel)), "Failed to load skel"); \
171
})
172
173
/*
174
* New versions of bpftool now emit additional link placeholders for BPF maps,
175
* and set up BPF skeleton in such a way that libbpf will auto-attach BPF maps
176
* automatically, assumming libbpf is recent enough (v1.5+). Old libbpf will do
177
* nothing with those links and won't attempt to auto-attach maps.
178
*
179
* To maintain compatibility with older libbpf while avoiding trying to attach
180
* twice, disable the autoattach feature on newer libbpf.
181
*/
182
#if LIBBPF_MAJOR_VERSION > 1 || \
183
(LIBBPF_MAJOR_VERSION == 1 && LIBBPF_MINOR_VERSION >= 5)
184
#define __SCX_OPS_DISABLE_AUTOATTACH(__skel, __ops_name) \
185
bpf_map__set_autoattach((__skel)->maps.__ops_name, false)
186
#else
187
#define __SCX_OPS_DISABLE_AUTOATTACH(__skel, __ops_name) do {} while (0)
188
#endif
189
190
#define SCX_OPS_ATTACH(__skel, __ops_name, __scx_name) ({ \
191
struct bpf_link *__link; \
192
__SCX_OPS_DISABLE_AUTOATTACH(__skel, __ops_name); \
193
SCX_BUG_ON(__scx_name##__attach((__skel)), "Failed to attach skel"); \
194
__link = bpf_map__attach_struct_ops((__skel)->maps.__ops_name); \
195
SCX_BUG_ON(!__link, "Failed to attach struct_ops"); \
196
__link; \
197
})
198
199
#endif /* __SCX_COMPAT_H */
200
201