summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Kacur <jkacur@redhat.com>2012-05-09 16:03:03 +0200
committerClark Williams <williams@redhat.com>2012-05-09 09:22:07 -0500
commit81c42e0162412cb990354d1ccb9d60d0dc10b79c (patch)
treef325e845a1da546184c744b5ccaf9b21438ae061
parent683a326a12e75c6d4afc8b61cfe0cec5c8cb965b (diff)
downloadrt-tests-81c42e0162412cb990354d1ccb9d60d0dc10b79c.tar.gz
rt-tests / cyclictest: Make cyclictest fail if it cannot run with requested priority.
Currently if a non-root user requests a priority higher than the soft limit in /etc/security/limits.conf the call to sched_setscheduler will silently fail and the user will be running with priority of 0. Cyclictest will not complain, and display the requested priority resulting in seemingly poor results. The following patch fixes this by doing two things. 1. If the requested priority is higher than the soft limit but lower than the hard limit, it will raise the soft limit to the requested priority. 2. If the requested priority is higher than the hard limit, it will fail with a warning. The patch should not affect privileged users. Reported-by: Nicholas Mc Guire <der.herr@hofr.at> Signed-off-by: John Kacur <jkacur@redhat.com> Signed-off-by: Clark Williams <williams@redhat.com>
-rw-r--r--src/cyclictest/cyclictest.c76
1 files changed, 75 insertions, 1 deletions
diff --git a/src/cyclictest/cyclictest.c b/src/cyclictest/cyclictest.c
index 880f42c..11b6cea 100644
--- a/src/cyclictest/cyclictest.c
+++ b/src/cyclictest/cyclictest.c
@@ -31,6 +31,7 @@
#include <sys/sysinfo.h>
#include <sys/types.h>
#include <sys/time.h>
+#include <sys/resource.h>
#include <sys/utsname.h>
#include <sys/mman.h>
#include "rt_numa.h"
@@ -589,6 +590,79 @@ parse_time_string(char *val)
}
/*
+ * Raise the soft priority limit up to prio, if that is less than or equal
+ * to the hard limit
+ * if a call fails, return the error
+ * if successful return 0
+ * if fails, return -1
+*/
+static int raise_soft_prio(int policy, const struct sched_param *param)
+{
+ int err;
+ int policy_max; /* max for scheduling policy such as SCHED_FIFO */
+ int soft_max;
+ int hard_max;
+ int prio;
+ struct rlimit rlim;
+
+ prio = param->sched_priority;
+
+ policy_max = sched_get_priority_max(policy);
+ if (policy_max == -1) {
+ err = errno;
+ err_msg("WARN: no such policy\n");
+ return err;
+ }
+
+ err = getrlimit(RLIMIT_RTPRIO, &rlim);
+ if (err) {
+ err = errno;
+ err_msg_n(err, "WARN: getrlimit failed\n");
+ return err;
+ }
+
+ soft_max = (rlim.rlim_cur == RLIM_INFINITY) ? policy_max : rlim.rlim_cur;
+ hard_max = (rlim.rlim_max == RLIM_INFINITY) ? policy_max : rlim.rlim_max;
+
+ if (prio > soft_max && prio <= hard_max) {
+ rlim.rlim_cur = prio;
+ err = setrlimit(RLIMIT_RTPRIO, &rlim);
+ if (err) {
+ err = errno;
+ err_msg_n(err, "WARN: setrlimit failed\n");
+ /* return err; */
+ }
+ } else {
+ err = -1;
+ }
+
+ return err;
+}
+
+/*
+ * Check the error status of sched_setscheduler
+ * If an error can be corrected by raising the soft limit priority to
+ * a priority less than or equal to the hard limit, then do so.
+ */
+static int setscheduler(pid_t pid, int policy, const struct sched_param *param)
+{
+ int err = 0;
+
+try_again:
+ err = sched_setscheduler(pid, policy, param);
+ if (err) {
+ err = errno;
+ if (err == EPERM) {
+ int err1;
+ err1 = raise_soft_prio(policy, param);
+ if (!err1) goto try_again;
+ }
+ }
+
+ return err;
+}
+
+/*
* timer thread
*
* Modes:
@@ -646,7 +720,7 @@ void *timerthread(void *param)
memset(&schedp, 0, sizeof(schedp));
schedp.sched_priority = par->prio;
- if (sched_setscheduler(0, par->policy, &schedp))
+ if (setscheduler(0, par->policy, &schedp))
fatal("timerthread%d: failed to set priority to %d\n", par->cpu, par->prio);
/* Get current time */