Module: xenomai-2.5
Branch: master
Commit: 96f5fa21548e5dcf8136aa133824aadb1dea7b60
URL:    
http://git.xenomai.org/?p=xenomai-2.5.git;a=commit;h=96f5fa21548e5dcf8136aa133824aadb1dea7b60

Author: Gilles Chanteperdrix <gilles.chanteperd...@xenomai.org>
Date:   Fri Jan  8 01:51:33 2010 +0100

nucleus: Fix RPI issue.

Fix a deadlock which was occuring with short periods.

It was due to the fact that a Linux thread in the RPI queue, when suspended
whereas not current, could not be removed from the RPI queue because the
nucleus was not notified.

We fix the issue by removing such threads from the RPI queue when they head
the RPI queue.

Furthermore we suppress the removal of such threads which was occuring when
Linux was switching them out, to only remove them lazily when they head the
RPI queue.

---

 ksrc/nucleus/shadow.c |   71 +++++++++++++++++++++++++++----------------------
 1 files changed, 39 insertions(+), 32 deletions(-)

diff --git a/ksrc/nucleus/shadow.c b/ksrc/nucleus/shadow.c
index 22bac6f..8dcdb4a 100644
--- a/ksrc/nucleus/shadow.c
+++ b/ksrc/nucleus/shadow.c
@@ -174,6 +174,41 @@ static inline void set_switch_lock_owner(struct 
task_struct *p)
 
 #define rpi_p(t)       ((t)->rpi != NULL)
 
+static inline struct xnthread *rpi_next(struct xnsched *sched)
+{
+       struct xnthread *thread;
+       spl_t s;
+
+       thread = xnsched_peek_rpi(sched);
+       while (thread && 
+              xnthread_user_task(thread)->state != TASK_RUNNING &&
+              !xnthread_test_info(thread, XNATOMIC)) {
+               /*
+                * A blocked Linux task must be removed from the RPI
+                * list. Checking for XNATOMIC prevents from unlinking
+                * a thread which is currently in flight to the
+                * primary domain (see xnshadow_harden()); not doing
+                * so would open a tiny window for priority inversion.
+                *
+                * BIG FAT WARNING: Do not consider a blocked thread
+                * linked to another processor's RPI list for removal,
+                * since this may happen if such thread immediately
+                * resumes on the remote CPU.
+                */
+               xnsched_pop_rpi(thread);
+               thread->rpi = NULL;
+               xnlock_put_irqrestore(&sched->rpilock, s);
+               /* Do NOT nest the rpilock and nklock locks. */
+               xnlock_get_irqsave(&nklock, s);
+               xnsched_suspend_rpi(thread);
+               xnlock_put_irqrestore(&nklock, s);
+               xnlock_get_irqsave(&sched->rpilock, s);
+               thread = xnsched_peek_rpi(sched);
+       }
+
+       return thread;
+}
+
 static void rpi_push(struct xnsched *sched, struct xnthread *thread)
 {
        struct xnsched_class *sched_class;
@@ -236,7 +271,7 @@ static void rpi_pop(struct xnthread *thread)
                return;
        }
 
-       top = xnsched_peek_rpi(sched);
+       top = rpi_next(sched);
        if (likely(top == NULL)) {
                prio = XNSCHED_IDLE_PRIO;
                sched_class = &xnsched_class_idle;
@@ -310,7 +345,7 @@ static void rpi_clear_remote(struct xnthread *thread)
        xnsched_pop_rpi(thread);
        thread->rpi = NULL;
 
-       if (xnsched_peek_rpi(rpi) == NULL)
+       if (rpi_next(rpi) == NULL)
                rcpu = xnsched_cpu(rpi);
 
        xnlock_put_irqrestore(&rpi->rpilock, s);
@@ -374,40 +409,12 @@ static inline void rpi_switch(struct task_struct 
*next_task)
        oldprio = xnsched_root_priority(sched);
        oldclass = xnsched_root_class(sched);
 
-       if (prev &&
-           current->state != TASK_RUNNING &&
-           !xnthread_test_info(prev, XNATOMIC)) {
-               /*
-                * A blocked Linux task must be removed from the RPI
-                * list. Checking for XNATOMIC prevents from unlinking
-                * a thread which is currently in flight to the
-                * primary domain (see xnshadow_harden()); not doing
-                * so would open a tiny window for priority inversion.
-                *
-                * BIG FAT WARNING: Do not consider a blocked thread
-                * linked to another processor's RPI list for removal,
-                * since this may happen if such thread immediately
-                * resumes on the remote CPU.
-                */
-               xnlock_get_irqsave(&sched->rpilock, s);
-               if (prev->rpi == sched) {
-                       xnsched_pop_rpi(prev);
-                       prev->rpi = NULL;
-                       xnlock_put_irqrestore(&sched->rpilock, s);
-                       /* Do NOT nest the rpilock and nklock locks. */
-                       xnlock_get_irqsave(&nklock, s);
-                       xnsched_suspend_rpi(prev);
-                       xnlock_put_irqrestore(&nklock, s);
-               } else
-                       xnlock_put_irqrestore(&sched->rpilock, s);
-       }
-
        if (next == NULL ||
            next_task->policy != SCHED_FIFO ||
            xnthread_test_state(next, XNRPIOFF)) {
                xnlock_get_irqsave(&sched->rpilock, s);
 
-               top = xnsched_peek_rpi(sched);
+               top = rpi_next(sched);
                if (top) {
                        newprio = top->cprio;
                        newclass = top->sched_class;
@@ -495,7 +502,7 @@ void xnshadow_rpi_check(void)
        struct xnthread *top;
  
        xnlock_get(&sched->rpilock);
-       top = xnsched_peek_rpi(sched);
+       top = rpi_next(sched);
        xnlock_put(&sched->rpilock);
 
        if (top == NULL && xnsched_root_class(sched) != &xnsched_class_idle)


_______________________________________________
Xenomai-git mailing list
Xenomai-git@gna.org
https://mail.gna.org/listinfo/xenomai-git

Reply via email to