From 6f27e449a9cbb96c4731207469aea7cbd8d0a5c4 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Mon, 11 Jul 2016 15:33:46 +0200 Subject: chrt: add fallback to be usable on kernels without sched_{get,set}attr We have fallback for compilation with/without proper glibc and kernel headers, but it's not enough, because people can switch between kernels with and without the syscalls. (For example RT kernels for RHEL/CentOS). Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1353340 Signed-off-by: Karel Zak --- schedutils/chrt.c | 51 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/schedutils/chrt.c b/schedutils/chrt.c index e934275d7..edae0d9f4 100644 --- a/schedutils/chrt.c +++ b/schedutils/chrt.c @@ -58,11 +58,19 @@ # define SCHED_FLAG_RESET_ON_FORK 0x01 #endif - #if defined (__linux__) && !defined(HAVE_SCHED_SETATTR) # include #endif +/* usable kernel-headers, but old glibc-headers */ +#if defined (__linux__) && !defined(SYS_sched_setattr) && defined(__NR_sched_setattr) +# define SYS_sched_setattr __NR_sched_setattr +#endif + +#if defined (__linux__) && !defined(SYS_sched_getattr) && defined(__NR_sched_getattr) +# define SYS_sched_getattr __NR_sched_getattr +#endif + #if defined (__linux__) && !defined(HAVE_SCHED_SETATTR) && defined(SYS_sched_setattr) # define HAVE_SCHED_SETATTR @@ -207,12 +215,20 @@ static void show_sched_pid_info(struct chrt_ctl *ctl, pid_t pid) if (!pid) pid = getpid(); + errno = 0; + + /* + * New way + */ #ifdef HAVE_SCHED_SETATTR { struct sched_attr sa; - if (sched_getattr(pid, &sa, sizeof(sa), 0) != 0) + if (sched_getattr(pid, &sa, sizeof(sa), 0) != 0) { + if (errno == ENOSYS) + goto fallback; err(EXIT_FAILURE, _("failed to get pid %d's policy"), pid); + } policy = sa.sched_policy; prio = sa.sched_priority; @@ -221,8 +237,13 @@ static void show_sched_pid_info(struct chrt_ctl *ctl, pid_t pid) runtime = sa.sched_runtime; period = sa.sched_period; } -#else /* !HAVE_SCHED_SETATTR */ - { +#endif + + /* + * Old way + */ +fallback: + if (errno == ENOSYS) { struct sched_param sp; policy = sched_getscheduler(pid); @@ -238,7 +259,6 @@ static void show_sched_pid_info(struct chrt_ctl *ctl, pid_t pid) reset_on_fork = 1; # endif } -#endif /* !HAVE_SCHED_SETATTR */ if (ctl->altered) printf(_("pid %d's new scheduling policy: %s"), pid, get_policy_name(policy)); @@ -315,8 +335,7 @@ static void show_min_max(void) } } -#ifndef HAVE_SCHED_SETATTR -static int set_sched_one(struct chrt_ctl *ctl, pid_t pid) +static int set_sched_one_by_setscheduler(struct chrt_ctl *ctl, pid_t pid) { struct sched_param sp = { .sched_priority = ctl->priority }; int policy = ctl->policy; @@ -328,6 +347,13 @@ static int set_sched_one(struct chrt_ctl *ctl, pid_t pid) return sched_setscheduler(pid, policy, &sp); } + +#ifndef HAVE_SCHED_SETATTR +static int set_sched_one(struct chrt_ctl *ctl, pid_t pid) +{ + return set_sched_one_by_setscheduler(ctl, pid); +} + #else /* !HAVE_SCHED_SETATTR */ static int set_sched_one(struct chrt_ctl *ctl, pid_t pid) { @@ -340,11 +366,20 @@ static int set_sched_one(struct chrt_ctl *ctl, pid_t pid) .sched_period = ctl->period, .sched_deadline = ctl->deadline }; + int rc; + # ifdef SCHED_RESET_ON_FORK if (ctl->reset_on_fork) sa.sched_flags |= SCHED_RESET_ON_FORK; # endif - return sched_setattr(pid, &sa, 0); + errno = 0; + rc = sched_setattr(pid, &sa, 0); + + if (rc != 0 && errno == ENOSYS && ctl->policy != SCHED_DEADLINE) + /* fallback -- build with new kernel/libc, but executed on old kernels */ + rc = set_sched_one_by_setscheduler(ctl, pid); + + return rc; } #endif /* HAVE_SCHED_SETATTR */ -- cgit v1.2.3-55-g7522