aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sched.c
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2010-01-20 18:00:32 -0500
committerThomas Gleixner <tglx@linutronix.de>2010-02-21 14:20:12 -0500
commit28bbb2398ebbeac1d4c1fd109938441842c8f89e (patch)
tree7defe590648e75bb7b42db63a1eee0a0eb9870ce /kernel/sched.c
parentbabe95bad86cba3843cb53d1cee8ac39c491a64a (diff)
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>
Diffstat (limited to 'kernel/sched.c')
-rw-r--r--kernel/sched.c20
1 files changed, 19 insertions, 1 deletions
diff --git a/kernel/sched.c b/kernel/sched.c
index 1803667dbb6e..32d7eb474fa7 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -6714,7 +6714,25 @@ recheck:
6714 if (running) 6714 if (running)
6715 p->sched_class->set_curr_task(rq); 6715 p->sched_class->set_curr_task(rq);
6716 if (on_rq) { 6716 if (on_rq) {
6717 activate_task(rq, p, 0, false); 6717 /*
6718 * Workaround to make prio ceiling work as expected:
6719 *
6720 * Queue task to head when task is running and task is
6721 * lowering its priority. This works around the non-
6722 * availability of a sched_setprio syscall which was
6723 * tinkered into the posix spec to make prio ceiling
6724 * work correctly.
6725 *
6726 * This workaround violates the posix scheduling
6727 * semantics of tail queueing in the case that the
6728 * priority was changed by anything else than
6729 * sched_setprio, but there is no other breakage
6730 * lurking than some specification fetishists going
6731 * berserk on me.
6732 *
6733 * Fixing this in mainline needs more thoughts.
6734 */
6735 activate_task(rq, p, 0, running && oldprio < p->prio);
6718 6736
6719 check_class_changed(rq, p, prev_class, oldprio, running); 6737 check_class_changed(rq, p, prev_class, oldprio, running);
6720 } 6738 }