From b6a2828e53717efdb41beb6a39b8e3a0166b9ef0 Mon Sep 17 00:00:00 2001 From: Martin Kletzander Date: Thu, 8 Jan 2015 15:36:54 +0100 Subject: [PATCH] util: Add virProcessSetScheduler() function for scheduler settings This function uses sched_setscheduler() function so it works with processes and threads as well (even threads not created by us, which is what we'll need in the future). Signed-off-by: Martin Kletzander --- configure.ac | 4 +- src/libvirt_private.syms | 3 ++ src/util/virprocess.c | 109 ++++++++++++++++++++++++++++++++++++++- src/util/virprocess.h | 20 ++++++- 4 files changed, 131 insertions(+), 5 deletions(-) diff --git a/configure.ac b/configure.ac index 99a2283434..b3e99e780c 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ dnl Process this file with autoconf to produce a configure script. -dnl Copyright (C) 2005-2014 Red Hat, Inc. +dnl Copyright (C) 2005-2015 Red Hat, Inc. dnl dnl This library is free software; you can redistribute it and/or dnl modify it under the terms of the GNU Lesser General Public @@ -275,7 +275,7 @@ dnl and various less common threadsafe functions AC_CHECK_FUNCS_ONCE([cfmakeraw fallocate geteuid getgid getgrnam_r \ getmntent_r getpwuid_r getuid kill mmap newlocale posix_fallocate \ posix_memalign prlimit regexec sched_getaffinity setgroups setns \ - setrlimit symlink sysctlbyname getifaddrs]) + setrlimit symlink sysctlbyname getifaddrs sched_setscheduler]) dnl Availability of pthread functions. Because of $LIB_PTHREAD, we dnl cannot use AC_CHECK_FUNCS_ONCE. LIB_PTHREAD and LIBMULTITHREAD diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 3b4ff41ed8..bff9a0bf38 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1916,11 +1916,14 @@ virProcessGetStartTime; virProcessKill; virProcessKillPainfully; virProcessRunInMountNamespace; +virProcessSchedPolicyTypeFromString; +virProcessSchedPolicyTypeToString; virProcessSetAffinity; virProcessSetMaxFiles; virProcessSetMaxMemLock; virProcessSetMaxProcesses; virProcessSetNamespaces; +virProcessSetScheduler; virProcessTranslateStatus; virProcessWait; diff --git a/src/util/virprocess.c b/src/util/virprocess.c index d0a1500cf2..b3e5435c0e 100644 --- a/src/util/virprocess.c +++ b/src/util/virprocess.c @@ -1,7 +1,7 @@ /* * virprocess.c: interaction with processes * - * Copyright (C) 2010-2014 Red Hat, Inc. + * Copyright (C) 2010-2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -32,7 +32,9 @@ # include # include #endif -#include +#if HAVE_SCHED_SETSCHEDULER +# include +#endif #if defined(__FreeBSD__) || HAVE_BSD_CPU_AFFINITY # include @@ -104,6 +106,13 @@ static inline int setns(int fd ATTRIBUTE_UNUSED, int nstype ATTRIBUTE_UNUSED) } #endif +VIR_ENUM_IMPL(virProcessSchedPolicy, VIR_PROC_POLICY_LAST, + "none", + "batch", + "idle", + "fifo", + "rr"); + /** * virProcessTranslateStatus: * @status: child exit status to translate @@ -1052,3 +1061,99 @@ virProcessExitWithStatus(int status) } exit(value); } + +#if HAVE_SCHED_SETSCHEDULER + +static int +virProcessSchedTranslatePolicy(virProcessSchedPolicy policy) +{ + switch (policy) { + case VIR_PROC_POLICY_NONE: + return SCHED_OTHER; + + case VIR_PROC_POLICY_BATCH: + return SCHED_BATCH; + + case VIR_PROC_POLICY_IDLE: + return SCHED_IDLE; + + case VIR_PROC_POLICY_FIFO: + return SCHED_FIFO; + + case VIR_PROC_POLICY_RR: + return SCHED_RR; + + case VIR_PROC_POLICY_LAST: + /* nada */ + break; + } + + return -1; +} + +int +virProcessSetScheduler(pid_t pid, virProcessSchedPolicy policy, int priority) +{ + struct sched_param param = {0}; + int pol = virProcessSchedTranslatePolicy(policy); + + VIR_DEBUG("pid=%d, policy=%d, priority=%u", pid, policy, priority); + + if (!policy) + return 0; + + if (pol == SCHED_FIFO || pol == SCHED_RR) { + int min = 0; + int max = 0; + + if ((min = sched_get_priority_min(pol)) < 0) { + virReportSystemError(errno, "%s", + _("Cannot get minimum scheduler " + "priority value")); + return -1; + } + + if ((max = sched_get_priority_max(pol)) < 0) { + virReportSystemError(errno, "%s", + _("Cannot get maximum scheduler " + "priority value")); + return -1; + } + + if (priority < min || priority > max) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Scheduler priority %d out of range [%d, %d]"), + priority, min, max); + return -1; + } + + param.sched_priority = priority; + } + + if (sched_setscheduler(pid, pol, ¶m) < 0) { + virReportSystemError(errno, + _("Cannot set scheduler parameters for pid %d"), + pid); + return -1; + } + + return 0; +} + +#else /* ! HAVE_SCHED_SETSCHEDULER */ + +int +virProcessSetScheduler(pid_t pid ATTRIBUTE_UNUSED, + int policy, + int priority ATTRIBUTE_UNUSED) +{ + if (!policy) + return 0; + + virReportSystemError(ENOSYS, "%s", + _("Process CPU scheduling is not supported " + "on this platform")); + return -1; +} + +#endif /* !HAVE_SCHED_SETSCHEDULER */ diff --git a/src/util/virprocess.h b/src/util/virprocess.h index bcaede58a9..c812882980 100644 --- a/src/util/virprocess.h +++ b/src/util/virprocess.h @@ -1,7 +1,7 @@ /* * virprocess.h: interaction with processes * - * Copyright (C) 2010-2014 Red Hat, Inc. + * Copyright (C) 2010-2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -26,6 +26,19 @@ # include "internal.h" # include "virbitmap.h" +# include "virutil.h" + +typedef enum { + VIR_PROC_POLICY_NONE = 0, + VIR_PROC_POLICY_BATCH, + VIR_PROC_POLICY_IDLE, + VIR_PROC_POLICY_FIFO, + VIR_PROC_POLICY_RR, + + VIR_PROC_POLICY_LAST +} virProcessSchedPolicy; + +VIR_ENUM_DECL(virProcessSchedPolicy); char * virProcessTranslateStatus(int status); @@ -73,4 +86,9 @@ typedef int (*virProcessNamespaceCallback)(pid_t pid, void *opaque); int virProcessRunInMountNamespace(pid_t pid, virProcessNamespaceCallback cb, void *opaque); + +int virProcessSetScheduler(pid_t pid, + virProcessSchedPolicy policy, + int priority); + #endif /* __VIR_PROCESS_H__ */ -- GitLab