On 10.02.2015 16:35, Martin Kletzander wrote:
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 <mkletzan(a)redhat.com>
---
configure.ac | 4 +-
src/libvirt_private.syms | 1 +
src/util/virprocess.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++-
src/util/virprocess.h | 20 ++++++++-
4 files changed, 124 insertions(+), 5 deletions(-)
diff --git a/configure.ac b/configure.ac
index 99a2283..b3e99e7 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 376c69b..79fc14f 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1915,6 +1915,7 @@ virProcessSetMaxFiles;
virProcessSetMaxMemLock;
virProcessSetMaxProcesses;
virProcessSetNamespaces;
+virProcessSetScheduler;
virProcessTranslateStatus;
virProcessWait;
diff --git a/src/util/virprocess.c b/src/util/virprocess.c
index d0a1500..c030d74 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 <sys/time.h>
# include <sys/resource.h>
#endif
-#include <sched.h>
+#if HAVE_SCHED_SETSCHEDULER
+# include <sched.h>
+#endif
#if defined(__FreeBSD__) || HAVE_BSD_CPU_AFFINITY
# include <sys/param.h>
@@ -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,94 @@ 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;
In order to do this, you have to make sure enum has a zero value
element. I think compilers don't guarantee enum values <-> integer
mapping unless told so.
+
+ 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);
CONFIG? I'd say ARGUMENT, but we have the mess in error codes anyway and
this doesn't make situation any worse :)
+ 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, int policy, int priority)
ATTRIBUTE_UNUSED for arguments ^^. Although, would it be worth to copy
the check I've pointed out in here too? That is, even if
sched_setscheduler() is not available, and virProcessSetScheduler(pid,
0, prio); is called, return success instead of error (of course return
error for any other policy than VIR_PROC_POLICY_NONE).
+{
+ 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 bcaede5..8b95560 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,
+ 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);
This ^^ introduces virProcessSchedPolicyType{From,To}String(). However,
I don't see the symbols exported.
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__ */
ACK with all of that fixed.
Michal