Module: xenomai-3
Branch: master
Commit: e6feac3f6f26ee00a3985158eedcb53e3b8a82b1

Author: Philippe Gerum <>
Date:   Fri Jun 26 15:34:58 2015 +0200

cobalt/thread: fix missed rescheduling in SMP

During parallel multi-core operations involving two threads, the
following scenario may happen:

CPU0: thread A
      xnthread_suspend() on self
        => XNSCHED raised via xnsched_set_resched(), local scheduler (no IPI)
        => suspend eventually denied (bad timeout, lock break...)
           => no rescheduling

CPU1: thread B
      xnthread_resume() on A
        => XNSCHED seen pending by xnsched_set_resched(), no resched IPI marked
           => __xnsched_run() does not send a resched IPI to CPU0

The outcome is that CPU1 won't send any resched IPI to CPU0 although
it should have done so, which practically delays wakeup of thread A
until some operation on CPU0 eventually causes a local rescheduling.

The bottom line is that any code raising XNSCHED __must__ trigger the
rescheduling procedure.


 kernel/cobalt/thread.c |    4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/kernel/cobalt/thread.c b/kernel/cobalt/thread.c
index 5adf44f..e683d47 100644
--- a/kernel/cobalt/thread.c
+++ b/kernel/cobalt/thread.c
@@ -851,9 +851,6 @@ void xnthread_suspend(struct xnthread *thread, int mask,
        sched = thread->sched;
        oldstate = thread->state;
-       if (thread == sched->curr)
-               xnsched_set_resched(sched);
         * If attempting to suspend a runnable thread which is pending
         * a forced switch to secondary mode (XNKICKED), just raise
@@ -924,6 +921,7 @@ void xnthread_suspend(struct xnthread *thread, int mask,
         * defeat the purpose of xnarch_escalate().
        if (likely(thread == sched->curr)) {
+               xnsched_set_resched(sched);
                sched->lflags &= ~XNINLOCK;
                if (unlikely(mask & XNRELAX)) {

Xenomai-git mailing list

Reply via email to