Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tools/sched_ext: Receive updates from SCX repo

Receive tools/sched_ext updates form https://github.com/sched-ext/scx to
sync userspace bits:

- scx_bpf_dump_header() added which can be used to print out basic scheduler
info on dump.

- BPF possible/online CPU iterators added.

- CO-RE enums added. The enums are autogenerated from vmlinux.h. Include the
generated artifacts in tools/sched_ext to keep the Makefile simpler.

- Other misc changes.

Signed-off-by: Tejun Heo <tj@kernel.org>

+286 -8
+81 -2
tools/sched_ext/include/scx/common.bpf.h
··· 9 9 10 10 #ifdef LSP 11 11 #define __bpf__ 12 - #include "../vmlinux/vmlinux.h" 12 + #include "../vmlinux.h" 13 13 #else 14 14 #include "vmlinux.h" 15 15 #endif ··· 23 23 #define PF_KTHREAD 0x00200000 /* I am a kernel thread */ 24 24 #define PF_EXITING 0x00000004 25 25 #define CLOCK_MONOTONIC 1 26 + 27 + extern int LINUX_KERNEL_VERSION __kconfig; 28 + extern const char CONFIG_CC_VERSION_TEXT[64] __kconfig __weak; 29 + extern const char CONFIG_LOCALVERSION[64] __kconfig __weak; 26 30 27 31 /* 28 32 * Earlier versions of clang/pahole lost upper 32bits in 64bit enums which can ··· 102 98 _Pragma("GCC diagnostic push") \ 103 99 _Pragma("GCC diagnostic ignored \"-Wint-conversion\"") \ 104 100 ___bpf_fill(___param, args); \ 105 - _Pragma("GCC diagnostic pop") \ 101 + _Pragma("GCC diagnostic pop") 106 102 107 103 /* 108 104 * scx_bpf_exit() wraps the scx_bpf_exit_bstr() kfunc with variadic arguments ··· 138 134 scx_bpf_bstr_preamble(fmt, args) \ 139 135 scx_bpf_dump_bstr(___fmt, ___param, sizeof(___param)); \ 140 136 ___scx_bpf_bstr_format_checker(fmt, ##args); \ 137 + }) 138 + 139 + /* 140 + * scx_bpf_dump_header() is a wrapper around scx_bpf_dump that adds a header 141 + * of system information for debugging. 142 + */ 143 + #define scx_bpf_dump_header() \ 144 + ({ \ 145 + scx_bpf_dump("kernel: %d.%d.%d %s\ncc: %s\n", \ 146 + LINUX_KERNEL_VERSION >> 16, \ 147 + LINUX_KERNEL_VERSION >> 8 & 0xFF, \ 148 + LINUX_KERNEL_VERSION & 0xFF, \ 149 + CONFIG_LOCALVERSION, \ 150 + CONFIG_CC_VERSION_TEXT); \ 141 151 }) 142 152 143 153 #define BPF_STRUCT_OPS(name, args...) \ ··· 335 317 const struct cpumask *src2) __ksym; 336 318 u32 bpf_cpumask_weight(const struct cpumask *cpumask) __ksym; 337 319 320 + int bpf_iter_bits_new(struct bpf_iter_bits *it, const u64 *unsafe_ptr__ign, u32 nr_words) __ksym; 321 + int *bpf_iter_bits_next(struct bpf_iter_bits *it) __ksym; 322 + void bpf_iter_bits_destroy(struct bpf_iter_bits *it) __ksym; 323 + 324 + #define def_iter_struct(name) \ 325 + struct bpf_iter_##name { \ 326 + struct bpf_iter_bits it; \ 327 + const struct cpumask *bitmap; \ 328 + }; 329 + 330 + #define def_iter_new(name) \ 331 + static inline int bpf_iter_##name##_new( \ 332 + struct bpf_iter_##name *it, const u64 *unsafe_ptr__ign, u32 nr_words) \ 333 + { \ 334 + it->bitmap = scx_bpf_get_##name##_cpumask(); \ 335 + return bpf_iter_bits_new(&it->it, (const u64 *)it->bitmap, \ 336 + sizeof(struct cpumask) / 8); \ 337 + } 338 + 339 + #define def_iter_next(name) \ 340 + static inline int *bpf_iter_##name##_next(struct bpf_iter_##name *it) { \ 341 + return bpf_iter_bits_next(&it->it); \ 342 + } 343 + 344 + #define def_iter_destroy(name) \ 345 + static inline void bpf_iter_##name##_destroy(struct bpf_iter_##name *it) { \ 346 + scx_bpf_put_cpumask(it->bitmap); \ 347 + bpf_iter_bits_destroy(&it->it); \ 348 + } 349 + #define def_for_each_cpu(cpu, name) for_each_##name##_cpu(cpu) 350 + 351 + /// Provides iterator for possible and online cpus. 352 + /// 353 + /// # Example 354 + /// 355 + /// ``` 356 + /// static inline void example_use() { 357 + /// int *cpu; 358 + /// 359 + /// for_each_possible_cpu(cpu){ 360 + /// bpf_printk("CPU %d is possible", *cpu); 361 + /// } 362 + /// 363 + /// for_each_online_cpu(cpu){ 364 + /// bpf_printk("CPU %d is online", *cpu); 365 + /// } 366 + /// } 367 + /// ``` 368 + def_iter_struct(possible); 369 + def_iter_new(possible); 370 + def_iter_next(possible); 371 + def_iter_destroy(possible); 372 + #define for_each_possible_cpu(cpu) bpf_for_each(possible, cpu, NULL, 0) 373 + 374 + def_iter_struct(online); 375 + def_iter_new(online); 376 + def_iter_next(online); 377 + def_iter_destroy(online); 378 + #define for_each_online_cpu(cpu) bpf_for_each(online, cpu, NULL, 0) 379 + 338 380 /* 339 381 * Access a cpumask in read-only mode (typically to check bits). 340 382 */ ··· 501 423 } 502 424 503 425 #include "compat.bpf.h" 426 + #include "enums.bpf.h" 504 427 505 428 #endif /* __SCX_COMMON_BPF_H */
+6
tools/sched_ext/include/scx/common.h
··· 71 71 72 72 #include "user_exit_info.h" 73 73 #include "compat.h" 74 + #include "enums.h" 75 + 76 + /* not available when building kernel tools/sched_ext */ 77 + #if __has_include(<lib/sdt_task.h>) 78 + #include <lib/sdt_task.h> 79 + #endif 74 80 75 81 #endif /* __SCHED_EXT_COMMON_H */
+1
tools/sched_ext/include/scx/compat.h
··· 149 149 __skel = __scx_name##__open(); \ 150 150 SCX_BUG_ON(!__skel, "Could not open " #__scx_name); \ 151 151 __skel->struct_ops.__ops_name->hotplug_seq = scx_hotplug_seq(); \ 152 + SCX_ENUM_INIT(__skel); \ 152 153 __skel; \ 153 154 }) 154 155
+105
tools/sched_ext/include/scx/enums.autogen.bpf.h
··· 1 + /* 2 + * WARNING: This file is autogenerated from scripts/gen_enums.py. If you would 3 + * like to access an enum that is currently missing, add it to the script 4 + * and run it from the root directory to update this file. 5 + */ 6 + 7 + const volatile u64 __SCX_OPS_NAME_LEN __weak; 8 + #define SCX_OPS_NAME_LEN __SCX_OPS_NAME_LEN 9 + 10 + const volatile u64 __SCX_SLICE_DFL __weak; 11 + #define SCX_SLICE_DFL __SCX_SLICE_DFL 12 + 13 + const volatile u64 __SCX_SLICE_INF __weak; 14 + #define SCX_SLICE_INF __SCX_SLICE_INF 15 + 16 + const volatile u64 __SCX_DSQ_FLAG_BUILTIN __weak; 17 + #define SCX_DSQ_FLAG_BUILTIN __SCX_DSQ_FLAG_BUILTIN 18 + 19 + const volatile u64 __SCX_DSQ_FLAG_LOCAL_ON __weak; 20 + #define SCX_DSQ_FLAG_LOCAL_ON __SCX_DSQ_FLAG_LOCAL_ON 21 + 22 + const volatile u64 __SCX_DSQ_INVALID __weak; 23 + #define SCX_DSQ_INVALID __SCX_DSQ_INVALID 24 + 25 + const volatile u64 __SCX_DSQ_GLOBAL __weak; 26 + #define SCX_DSQ_GLOBAL __SCX_DSQ_GLOBAL 27 + 28 + const volatile u64 __SCX_DSQ_LOCAL __weak; 29 + #define SCX_DSQ_LOCAL __SCX_DSQ_LOCAL 30 + 31 + const volatile u64 __SCX_DSQ_LOCAL_ON __weak; 32 + #define SCX_DSQ_LOCAL_ON __SCX_DSQ_LOCAL_ON 33 + 34 + const volatile u64 __SCX_DSQ_LOCAL_CPU_MASK __weak; 35 + #define SCX_DSQ_LOCAL_CPU_MASK __SCX_DSQ_LOCAL_CPU_MASK 36 + 37 + const volatile u64 __SCX_TASK_QUEUED __weak; 38 + #define SCX_TASK_QUEUED __SCX_TASK_QUEUED 39 + 40 + const volatile u64 __SCX_TASK_RESET_RUNNABLE_AT __weak; 41 + #define SCX_TASK_RESET_RUNNABLE_AT __SCX_TASK_RESET_RUNNABLE_AT 42 + 43 + const volatile u64 __SCX_TASK_DEQD_FOR_SLEEP __weak; 44 + #define SCX_TASK_DEQD_FOR_SLEEP __SCX_TASK_DEQD_FOR_SLEEP 45 + 46 + const volatile u64 __SCX_TASK_STATE_SHIFT __weak; 47 + #define SCX_TASK_STATE_SHIFT __SCX_TASK_STATE_SHIFT 48 + 49 + const volatile u64 __SCX_TASK_STATE_BITS __weak; 50 + #define SCX_TASK_STATE_BITS __SCX_TASK_STATE_BITS 51 + 52 + const volatile u64 __SCX_TASK_STATE_MASK __weak; 53 + #define SCX_TASK_STATE_MASK __SCX_TASK_STATE_MASK 54 + 55 + const volatile u64 __SCX_TASK_CURSOR __weak; 56 + #define SCX_TASK_CURSOR __SCX_TASK_CURSOR 57 + 58 + const volatile u64 __SCX_TASK_NONE __weak; 59 + #define SCX_TASK_NONE __SCX_TASK_NONE 60 + 61 + const volatile u64 __SCX_TASK_INIT __weak; 62 + #define SCX_TASK_INIT __SCX_TASK_INIT 63 + 64 + const volatile u64 __SCX_TASK_READY __weak; 65 + #define SCX_TASK_READY __SCX_TASK_READY 66 + 67 + const volatile u64 __SCX_TASK_ENABLED __weak; 68 + #define SCX_TASK_ENABLED __SCX_TASK_ENABLED 69 + 70 + const volatile u64 __SCX_TASK_NR_STATES __weak; 71 + #define SCX_TASK_NR_STATES __SCX_TASK_NR_STATES 72 + 73 + const volatile u64 __SCX_TASK_DSQ_ON_PRIQ __weak; 74 + #define SCX_TASK_DSQ_ON_PRIQ __SCX_TASK_DSQ_ON_PRIQ 75 + 76 + const volatile u64 __SCX_KICK_IDLE __weak; 77 + #define SCX_KICK_IDLE __SCX_KICK_IDLE 78 + 79 + const volatile u64 __SCX_KICK_PREEMPT __weak; 80 + #define SCX_KICK_PREEMPT __SCX_KICK_PREEMPT 81 + 82 + const volatile u64 __SCX_KICK_WAIT __weak; 83 + #define SCX_KICK_WAIT __SCX_KICK_WAIT 84 + 85 + const volatile u64 __SCX_ENQ_WAKEUP __weak; 86 + #define SCX_ENQ_WAKEUP __SCX_ENQ_WAKEUP 87 + 88 + const volatile u64 __SCX_ENQ_HEAD __weak; 89 + #define SCX_ENQ_HEAD __SCX_ENQ_HEAD 90 + 91 + const volatile u64 __SCX_ENQ_PREEMPT __weak; 92 + #define SCX_ENQ_PREEMPT __SCX_ENQ_PREEMPT 93 + 94 + const volatile u64 __SCX_ENQ_REENQ __weak; 95 + #define SCX_ENQ_REENQ __SCX_ENQ_REENQ 96 + 97 + const volatile u64 __SCX_ENQ_LAST __weak; 98 + #define SCX_ENQ_LAST __SCX_ENQ_LAST 99 + 100 + const volatile u64 __SCX_ENQ_CLEAR_OPSS __weak; 101 + #define SCX_ENQ_CLEAR_OPSS __SCX_ENQ_CLEAR_OPSS 102 + 103 + const volatile u64 __SCX_ENQ_DSQ_PRIQ __weak; 104 + #define SCX_ENQ_DSQ_PRIQ __SCX_ENQ_DSQ_PRIQ 105 +
+41
tools/sched_ext/include/scx/enums.autogen.h
··· 1 + /* 2 + * WARNING: This file is autogenerated from scripts/gen_enums.py. If you would 3 + * like to access an enum that is currently missing, add it to the script 4 + * and run it from the root directory to update this file. 5 + */ 6 + 7 + #define SCX_ENUM_INIT(skel) do { \ 8 + SCX_ENUM_SET(skel, scx_public_consts, SCX_OPS_NAME_LEN); \ 9 + SCX_ENUM_SET(skel, scx_public_consts, SCX_SLICE_DFL); \ 10 + SCX_ENUM_SET(skel, scx_public_consts, SCX_SLICE_INF); \ 11 + SCX_ENUM_SET(skel, scx_dsq_id_flags, SCX_DSQ_FLAG_BUILTIN); \ 12 + SCX_ENUM_SET(skel, scx_dsq_id_flags, SCX_DSQ_FLAG_LOCAL_ON); \ 13 + SCX_ENUM_SET(skel, scx_dsq_id_flags, SCX_DSQ_INVALID); \ 14 + SCX_ENUM_SET(skel, scx_dsq_id_flags, SCX_DSQ_GLOBAL); \ 15 + SCX_ENUM_SET(skel, scx_dsq_id_flags, SCX_DSQ_LOCAL); \ 16 + SCX_ENUM_SET(skel, scx_dsq_id_flags, SCX_DSQ_LOCAL_ON); \ 17 + SCX_ENUM_SET(skel, scx_dsq_id_flags, SCX_DSQ_LOCAL_CPU_MASK); \ 18 + SCX_ENUM_SET(skel, scx_ent_flags, SCX_TASK_QUEUED); \ 19 + SCX_ENUM_SET(skel, scx_ent_flags, SCX_TASK_RESET_RUNNABLE_AT); \ 20 + SCX_ENUM_SET(skel, scx_ent_flags, SCX_TASK_DEQD_FOR_SLEEP); \ 21 + SCX_ENUM_SET(skel, scx_ent_flags, SCX_TASK_STATE_SHIFT); \ 22 + SCX_ENUM_SET(skel, scx_ent_flags, SCX_TASK_STATE_BITS); \ 23 + SCX_ENUM_SET(skel, scx_ent_flags, SCX_TASK_STATE_MASK); \ 24 + SCX_ENUM_SET(skel, scx_ent_flags, SCX_TASK_CURSOR); \ 25 + SCX_ENUM_SET(skel, scx_task_state, SCX_TASK_NONE); \ 26 + SCX_ENUM_SET(skel, scx_task_state, SCX_TASK_INIT); \ 27 + SCX_ENUM_SET(skel, scx_task_state, SCX_TASK_READY); \ 28 + SCX_ENUM_SET(skel, scx_task_state, SCX_TASK_ENABLED); \ 29 + SCX_ENUM_SET(skel, scx_task_state, SCX_TASK_NR_STATES); \ 30 + SCX_ENUM_SET(skel, scx_ent_dsq_flags, SCX_TASK_DSQ_ON_PRIQ); \ 31 + SCX_ENUM_SET(skel, scx_kick_flags, SCX_KICK_IDLE); \ 32 + SCX_ENUM_SET(skel, scx_kick_flags, SCX_KICK_PREEMPT); \ 33 + SCX_ENUM_SET(skel, scx_kick_flags, SCX_KICK_WAIT); \ 34 + SCX_ENUM_SET(skel, scx_enq_flags, SCX_ENQ_WAKEUP); \ 35 + SCX_ENUM_SET(skel, scx_enq_flags, SCX_ENQ_HEAD); \ 36 + SCX_ENUM_SET(skel, scx_enq_flags, SCX_ENQ_PREEMPT); \ 37 + SCX_ENUM_SET(skel, scx_enq_flags, SCX_ENQ_REENQ); \ 38 + SCX_ENUM_SET(skel, scx_enq_flags, SCX_ENQ_LAST); \ 39 + SCX_ENUM_SET(skel, scx_enq_flags, SCX_ENQ_CLEAR_OPSS); \ 40 + SCX_ENUM_SET(skel, scx_enq_flags, SCX_ENQ_DSQ_PRIQ); \ 41 + } while (0)
+12
tools/sched_ext/include/scx/enums.bpf.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Convenience macros for getting/setting struct scx_enums instances. 4 + * 5 + * Copyright (c) 2024 Meta Platforms, Inc. and affiliates. 6 + */ 7 + #ifndef __SCX_ENUMS_BPF_H 8 + #define __SCX_ENUMS_BPF_H 9 + 10 + #include "enums.autogen.bpf.h" 11 + 12 + #endif /* __SCX_ENUMS_BPF_H */
+27
tools/sched_ext/include/scx/enums.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Define struct scx_enums that stores the load-time values of enums 4 + * used by the BPF program. 5 + * 6 + * Copyright (c) 2024 Meta Platforms, Inc. and affiliates. 7 + */ 8 + 9 + #ifndef __SCX_ENUMS_H 10 + #define __SCX_ENUMS_H 11 + 12 + static inline void __ENUM_set(u64 *val, char *type, char *name) 13 + { 14 + bool res; 15 + 16 + res = __COMPAT_read_enum(type, name, val); 17 + SCX_BUG_ON(!res, "enum not found(%s)", name); 18 + } 19 + 20 + #define SCX_ENUM_SET(skel, type, name) do { \ 21 + __ENUM_set(&skel->rodata->__##name, #type, #name); \ 22 + } while (0) 23 + 24 + 25 + #include "enums.autogen.h" 26 + 27 + #endif /* __SCX_ENUMS_H */
+6 -3
tools/sched_ext/include/scx/user_exit_info.h
··· 10 10 #ifndef __USER_EXIT_INFO_H 11 11 #define __USER_EXIT_INFO_H 12 12 13 + #ifdef LSP 14 + #define __bpf__ 15 + #include "../vmlinux.h" 16 + #endif 17 + 13 18 enum uei_sizes { 14 19 UEI_REASON_LEN = 128, 15 20 UEI_MSG_LEN = 1024, ··· 30 25 31 26 #ifdef __bpf__ 32 27 33 - #ifdef LSP 34 - #include "../vmlinux/vmlinux.h" 35 - #else 28 + #ifndef LSP 36 29 #include "vmlinux.h" 37 30 #endif 38 31 #include <bpf/bpf_core_read.h>
+1 -1
tools/sched_ext/scx_central.bpf.c
··· 57 57 58 58 const volatile s32 central_cpu; 59 59 const volatile u32 nr_cpu_ids = 1; /* !0 for veristat, set during init */ 60 - const volatile u64 slice_ns = SCX_SLICE_DFL; 60 + const volatile u64 slice_ns; 61 61 62 62 bool timer_pinned = true; 63 63 u64 nr_total, nr_locals, nr_queued, nr_lost_pids;
+1
tools/sched_ext/scx_central.c
··· 58 58 59 59 skel->rodata->central_cpu = 0; 60 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"); 61 62 62 63 while ((opt = getopt(argc, argv, "s:c:pvh")) != -1) { 63 64 switch (opt) {
+1 -1
tools/sched_ext/scx_flatcg.bpf.c
··· 57 57 char _license[] SEC("license") = "GPL"; 58 58 59 59 const volatile u32 nr_cpus = 32; /* !0 for veristat, set during init */ 60 - const volatile u64 cgrp_slice_ns = SCX_SLICE_DFL; 60 + const volatile u64 cgrp_slice_ns; 61 61 const volatile bool fifo_sched; 62 62 63 63 u64 cvtime_now;
+1
tools/sched_ext/scx_flatcg.c
··· 137 137 skel = SCX_OPS_OPEN(flatcg_ops, scx_flatcg); 138 138 139 139 skel->rodata->nr_cpus = libbpf_num_possible_cpus(); 140 + skel->rodata->cgrp_slice_ns = __COMPAT_ENUM_OR_ZERO("scx_public_consts", "SCX_SLICE_DFL"); 140 141 141 142 while ((opt = getopt(argc, argv, "s:i:dfvh")) != -1) { 142 143 double v;
+1 -1
tools/sched_ext/scx_qmap.bpf.c
··· 33 33 34 34 char _license[] SEC("license") = "GPL"; 35 35 36 - const volatile u64 slice_ns = SCX_SLICE_DFL; 36 + const volatile u64 slice_ns; 37 37 const volatile u32 stall_user_nth; 38 38 const volatile u32 stall_kernel_nth; 39 39 const volatile u32 dsp_inf_loop_after;
+2
tools/sched_ext/scx_qmap.c
··· 64 64 65 65 skel = SCX_OPS_OPEN(qmap_ops, scx_qmap); 66 66 67 + skel->rodata->slice_ns = __COMPAT_ENUM_OR_ZERO("scx_public_consts", "SCX_SLICE_DFL"); 68 + 67 69 while ((opt = getopt(argc, argv, "s:e:t:T:l:b:PHd:D:Spvh")) != -1) { 68 70 switch (opt) { 69 71 case 's':