From 016e9d8d08ce66f5e81b42e0a0db398afc17336a Mon Sep 17 00:00:00 2001 From: Florian Schmaus Date: Wed, 26 Jun 2024 14:37:52 +0200 Subject: [PATCH] core/exec-invoke: use sched_setattr instead of sched_setscheduler The kernel's sched_setattr interface allows for more control over a processes scheduling attributes as the previously used sched_setscheduler interface. Using sched_setattr is also the prerequisite for support of utilization clamping (UCLAMP [1], see #26705) and allows to set sched_runtime. The latter, sched_runtime, will probably become a relevant scheduling parameter of the EEVDF scheduler [2, 3], and therefore will not only apply to processes scheduled via SCHED_DEADLINE, but also for processes scheduled via SCHED_OTHER/SCHED_BATCH (i.e., most processes). 1: https://docs.kernel.org/next/scheduler/sched-util-clamp.html 2: https://lwn.net/Articles/969062/ 3: https://lwn.net/ml/linux-kernel/20240405110010.934104715@infradead.org/ --- meson.build | 3 +++ src/basic/missing_sched.h | 18 ++++++++++++++++++ src/basic/missing_syscall.h | 17 +++++++++++++++++ src/core/exec-invoke.c | 13 +++++++------ 4 files changed, 45 insertions(+), 6 deletions(-) diff --git a/meson.build b/meson.build index aa36e72b02..ddad82ddc9 100644 --- a/meson.build +++ b/meson.build @@ -547,6 +547,7 @@ decl_headers = ''' #include #include #include +#include ''' foreach decl : ['char16_t', @@ -554,6 +555,7 @@ foreach decl : ['char16_t', 'struct mount_attr', 'struct statx', 'struct dirent64', + 'struct sched_attr', ] # We get -1 if the size cannot be determined @@ -601,6 +603,7 @@ foreach ident : [ #include '''], # no known header declares pivot_root ['ioprio_get', '''#include '''], # no known header declares ioprio_get ['ioprio_set', '''#include '''], # no known header declares ioprio_set + ['sched_setattr', '''#include '''], # no known header declares sched_setattr ['name_to_handle_at', '''#include #include #include '''], diff --git a/src/basic/missing_sched.h b/src/basic/missing_sched.h index b8109d30ac..bd83b41a71 100644 --- a/src/basic/missing_sched.h +++ b/src/basic/missing_sched.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once +#include #include #include "macro.h" @@ -35,3 +36,20 @@ assert_cc(PF_KTHREAD == 0x00200000); #else assert_cc(TASK_COMM_LEN == 16); #endif + +#if !HAVE_STRUCT_SCHED_ATTR +struct sched_attr { + __u32 size; /* Size of this structure */ + __u32 sched_policy; /* Policy (SCHED_*) */ + __u64 sched_flags; /* Flags */ + __s32 sched_nice; /* Nice value (SCHED_OTHER, + SCHED_BATCH) */ + __u32 sched_priority; /* Static priority (SCHED_FIFO, + SCHED_RR) */ + /* Remaining fields are for SCHED_DEADLINE + and potentially soon for SCHED_OTHER/SCHED_BATCH */ + __u64 sched_runtime; + __u64 sched_deadline; + __u64 sched_period; +}; +#endif diff --git a/src/basic/missing_syscall.h b/src/basic/missing_syscall.h index 86280771c4..e2cd8b4e35 100644 --- a/src/basic/missing_syscall.h +++ b/src/basic/missing_syscall.h @@ -22,6 +22,7 @@ #include "macro.h" #include "missing_keyctl.h" +#include "missing_sched.h" #include "missing_stat.h" #include "missing_syscall_def.h" @@ -667,6 +668,22 @@ static inline ssize_t missing_getdents64(int fd, void *buffer, size_t length) { /* ======================================================================= */ +#if !HAVE_SCHED_SETATTR + +static inline ssize_t missing_sched_setattr(pid_t pid, struct sched_attr *attr, unsigned int flags) { +# if defined __NR_sched_setattr + return syscall(__NR_sched_setattr, pid, attr, flags); +# else + errno = ENOSYS; + return -1; +# endif +} + +# define sched_setattr missing_sched_setattr +#endif + +/* ======================================================================= */ + /* glibc does not provide clone() on ia64, only clone2(). Not only that, but it also doesn't provide a * prototype, only the symbol in the shared library (it provides a prototype for clone(), but not the * symbol in the shared library). */ diff --git a/src/core/exec-invoke.c b/src/core/exec-invoke.c index 3f713e731f..94c908afd7 100644 --- a/src/core/exec-invoke.c +++ b/src/core/exec-invoke.c @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ +#include #include #include #include @@ -44,6 +45,7 @@ #include "journal-send.h" #include "missing_ioprio.h" #include "missing_prctl.h" +#include "missing_sched.h" #include "missing_securebits.h" #include "missing_syscall.h" #include "mkdir-label.h" @@ -4411,15 +4413,14 @@ int exec_invoke( } if (context->cpu_sched_set) { - struct sched_param param = { + struct sched_attr attr = { + .size = sizeof(attr), + .sched_policy = context->cpu_sched_policy, .sched_priority = context->cpu_sched_priority, + .sched_flags = context->cpu_sched_reset_on_fork ? SCHED_FLAG_RESET_ON_FORK : 0, }; - r = sched_setscheduler(0, - context->cpu_sched_policy | - (context->cpu_sched_reset_on_fork ? - SCHED_RESET_ON_FORK : 0), - ¶m); + r = sched_setattr(/* pid= */ 0, &attr, /* flags= */ 0); if (r < 0) { *exit_status = EXIT_SETSCHEDULER; return log_exec_error_errno(context, params, errno, "Failed to set up CPU scheduling: %m"); -- 2.25.1