Module: xenomai-rpm Branch: for-upstream Commit: ac5c739dabcb14334c2e390a9e3064f11f97283c URL: http://git.xenomai.org/?p=xenomai-rpm.git;a=commit;h=ac5c739dabcb14334c2e390a9e3064f11f97283c
Author: Philippe Gerum <r...@xenomai.org> Date: Sat May 1 18:22:40 2010 +0200 nucleus/shadow: revert commit 96f5fa2 This patch reverts 96f5fa2, which did fix a real bug, but the wrong way. It broke basic assumptions in RPI management wrt SMP, introducing races in rpi_clear_remote() and xnshadow_rpi_check() at least, regarding the update of the RPI backlink (i.e. thread->rpi). Those assumptions are as follows: - RPI queues are per-CPU, and threads may enter/leave them only from the CPU they belong to, with one exception: rpi_clear_remote(). - threads may enter/leave RPI queues when they are in a state mutually exclusive to running rpi_clear_remote(). --- ksrc/nucleus/shadow.c | 70 ++++++++++++++++++++++-------------------------- 1 files changed, 32 insertions(+), 38 deletions(-) diff --git a/ksrc/nucleus/shadow.c b/ksrc/nucleus/shadow.c index 872c37f..873a9bc 100644 --- a/ksrc/nucleus/shadow.c +++ b/ksrc/nucleus/shadow.c @@ -170,40 +170,6 @@ static inline void set_switch_lock_owner(struct task_struct *p) #define rpi_p(t) ((t)->rpi != NULL) -static struct xnthread *rpi_next(struct xnsched *sched, spl_t s) -{ - struct xnthread *thread; - - 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; @@ -266,7 +232,7 @@ static void rpi_pop(struct xnthread *thread) return; } - top = rpi_next(sched, s); + top = xnsched_peek_rpi(sched); if (likely(top == NULL)) { prio = XNSCHED_IDLE_PRIO; sched_class = &xnsched_class_idle; @@ -340,7 +306,7 @@ static void rpi_clear_remote(struct xnthread *thread) xnsched_pop_rpi(thread); thread->rpi = NULL; - if (rpi_next(rpi, s) == NULL) + if (xnsched_peek_rpi(rpi) == NULL) rcpu = xnsched_cpu(rpi); xnlock_put_irqrestore(&rpi->rpilock, s); @@ -404,12 +370,40 @@ 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 = rpi_next(sched, s); + top = xnsched_peek_rpi(sched); if (top) { newprio = top->cprio; newclass = top->sched_class; @@ -498,7 +492,7 @@ void xnshadow_rpi_check(void) spl_t s; xnlock_get_irqsave(&sched->rpilock, s); - top = rpi_next(sched, s); + top = xnsched_peek_rpi(sched); xnlock_put_irqrestore(&sched->rpilock, s); 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