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