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

Reply via email to