summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2010-01-21 00:00:32 +0100
committerThomas Gleixner <tglx@linutronix.de>2010-01-21 00:32:01 +0100
commit1679c2af7997aae234ebbeb8726800c45777bef3 (patch)
treea15b910a5bc4abe7a633a386d50e2eac6293db33
parent1f10ed61d75f849395fffcb46251510bd287d91d (diff)
downloadlwn-1679c2af7997aae234ebbeb8726800c45777bef3.tar.gz
lwn-1679c2af7997aae234ebbeb8726800c45777bef3.zip
sched: Hack to make prio ceiling posix compliant
POSIX scheduling semantics for SCHED_FIFO require that a thread whose priority is changed via pthread_setschedprio() is enqueued to the head of the new priority list when the thread is running and the new priority is lower than the old priority. This is required to implement user space driven priority ceiling. The sys_sched_setscheduler() and sys_sched_setparam() semantics are POSIX compliant as they move the thread to the tail of the priority list. The lack of the sys_sched_setprio syscall and the resulting usage of sys_sched_setscheduler() resp. sys_sched_setparam() results in the following non POSIX compliant scenario: Task A and B are runnable and in the same priority list X task A runs and boosts itself for priority ceiling to prio Y task A unboost itself to its original priority X -> task A gets dequeued from priority list Y -> task A gets enqueued at the tail of priority list X task B runs Work around that to make prio ceiling work as expected: Queue task to head when task is running and task is lowering its priority. This works around the non-availability of a sched_setprio syscall which was tinkered into the posix spec to make prio ceiling work correctly. This workaround violates the posix scheduling semantics of tail queueing in the case that the priority was changed by anything else than sched_setprio, but there is no other breakage lurking than some specification fetishists going berserk on me. Fixing this in mainline needs more thoughts. Reported-by: Mathias Weber <mathias.weber.mw1@roche.com> Reported-by: Carsten Emde <cbe@osadl.org> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--kernel/sched.c20
1 files changed, 19 insertions, 1 deletions
diff --git a/kernel/sched.c b/kernel/sched.c
index 1ca987256375..590b9bb06540 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -6653,7 +6653,25 @@ recheck:
if (running)
p->sched_class->set_curr_task(rq);
if (on_rq) {
- activate_task(rq, p, 0, false);
+ /*
+ * Workaround to make prio ceiling work as expected:
+ *
+ * Queue task to head when task is running and task is
+ * lowering its priority. This works around the non-
+ * availability of a sched_setprio syscall which was
+ * tinkered into the posix spec to make prio ceiling
+ * work correctly.
+ *
+ * This workaround violates the posix scheduling
+ * semantics of tail queueing in the case that the
+ * priority was changed by anything else than
+ * sched_setprio, but there is no other breakage
+ * lurking than some specification fetishists going
+ * berserk on me.
+ *
+ * Fixing this in mainline needs more thoughts.
+ */
+ activate_task(rq, p, 0, running && oldprio < p->prio);
check_class_changed(rq, p, prev_class, oldprio, running);
}