summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Kacur <jkacur@redhat.com>2012-05-09 13:57:02 +0200
committerJohn Kacur <jkacur@redhat.com>2012-05-09 15:56:42 +0200
commit2a59ef6a3942e4def523d569c8132604478c064e (patch)
tree69b5e047828fbc17e0a256710dc23e5ab70ff836
parent9816d8e1aa798f225a8df2eb59f06e64e6a069ff (diff)
downloadrt-tests-0.83-devel.tar.gz
rt-tests / cyclictest: Make cyclictest fail if it cannot run with requested priority.rt-tests-0.83-devel
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>
-rw-r--r--src/cyclictest/cyclictest.c80
1 files changed, 79 insertions, 1 deletions
diff --git a/src/cyclictest/cyclictest.c b/src/cyclictest/cyclictest.c
index e8649c7..c44df6a 100644
--- a/src/cyclictest/cyclictest.c
+++ b/src/cyclictest/cyclictest.c
@@ -12,6 +12,7 @@
#include <stdio.h>
#include <stdlib.h>
+
#include <stdint.h>
#include <stdarg.h>
#include <unistd.h>
@@ -31,6 +32,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"
@@ -586,6 +588,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:
@@ -599,6 +674,7 @@ parse_time_string(char *val)
*/
void *timerthread(void *param)
{
+ int err;
struct thread_param *par = param;
struct sched_param schedp;
struct sigevent sigev;
@@ -643,7 +719,9 @@ void *timerthread(void *param)
memset(&schedp, 0, sizeof(schedp));
schedp.sched_priority = par->prio;
- sched_setscheduler(0, par->policy, &schedp);
+ err = setscheduler(0, par->policy, &schedp);
+ if (err)
+ fatal("Couldn't raise priority to %d\n", schedp.sched_priority);
/* Get current time */
clock_gettime(par->clock, &now);