Module: xenomai-rpm Branch: for-upstream Commit: d3242401b8e1cf2c28822f801b681194243b4394 URL: http://git.xenomai.org/?p=xenomai-rpm.git;a=commit;h=d3242401b8e1cf2c28822f801b681194243b4394
Author: Philippe Gerum <r...@xenomai.org> Date: Sat May 1 18:10:50 2010 +0200 nucleus/shadow: fix RPI race in xnshadow_relax() introduced by 695f3d0 This patch fixes a race in the RPI management code which may cause the root thread to remain priority-boosted indefinitely. The related bug was introduced in the 2.5 timeframe by commit 695f3d0 (aka killer optimization). The faulty code fragment from xnshadow_relax(), is this one: rpi_push(thread->sched, thread); splhigh(s); schedule_linux_call(LO_WAKEUP_REQ, current, 0); The sequence of events leading to the bug is as follows: - a Xenomai thread running in primary mode enters xnshadow_relax(), to move to the Linux domain; because this thread runs under the control of the Xenomai scheduler at this point, it is blocked linux-wise (TASK_INTERRUPTIBLE). - a real-time timer tick preempts the thread and switches it out, right after it linked itself to the local RPI queue calling rpi_push(), but before it had a chance to send an asynchronous wake up request for itself to the linux kernel (i.e. schedule_linux_call(LO_WAKEUP_REQ...). As a consequence of this, a blocked shadow linux-wise was introduced into the RPI queue, with no later opportunity to leave it, indefinitely preventing the root thread to be demoted to its regular idle priority. That bug is easily reproduced by running the latency test concurrently to the mutex-torture-native test. The fix consists of making the two operations described above, belong to a single atomic sequence, by proper interrupt masking. --- ksrc/nucleus/shadow.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/ksrc/nucleus/shadow.c b/ksrc/nucleus/shadow.c index 873a9bc..1a32527 100644 --- a/ksrc/nucleus/shadow.c +++ b/ksrc/nucleus/shadow.c @@ -1148,8 +1148,8 @@ void xnshadow_relax(int notify, int reason) trace_mark(xn_nucleus, shadow_gorelax, "thread %p thread_name %s", thread, xnthread_name(thread)); - rpi_push(thread->sched, thread); splhigh(s); + rpi_push(thread->sched, thread); schedule_linux_call(LO_WAKEUP_REQ, current, 0); clear_task_nowakeup(current); xnpod_suspend_thread(thread, XNRELAX, XN_INFINITE, XN_RELATIVE, NULL); _______________________________________________ Xenomai-git mailing list Xenomai-git@gna.org https://mail.gna.org/listinfo/xenomai-git