summaryrefslogtreecommitdiffstats
path: root/schedutils
diff options
context:
space:
mode:
authorKarel Zak2016-07-11 15:33:46 +0200
committerKarel Zak2016-07-11 15:33:46 +0200
commit6f27e449a9cbb96c4731207469aea7cbd8d0a5c4 (patch)
tree9c1d04f330d72e43bafb9192f90485e1491d49f7 /schedutils
parenttests: mark chrt as TS_KNOWN_FAIL (diff)
downloadkernel-qcow2-util-linux-6f27e449a9cbb96c4731207469aea7cbd8d0a5c4.tar.gz
kernel-qcow2-util-linux-6f27e449a9cbb96c4731207469aea7cbd8d0a5c4.tar.xz
kernel-qcow2-util-linux-6f27e449a9cbb96c4731207469aea7cbd8d0a5c4.zip
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 <kzak@redhat.com>
Diffstat (limited to 'schedutils')
-rw-r--r--schedutils/chrt.c51
1 files 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 <sys/syscall.h>
#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 */