Module: xenomai-rpm
Branch: for-upstream
Commit: 62bd1efa35795ac05f8ef467b7ff7d04a0660954
URL:    
http://git.xenomai.org/?p=xenomai-rpm.git;a=commit;h=62bd1efa35795ac05f8ef467b7ff7d04a0660954

Author: Philippe Gerum <r...@xenomai.org>
Date:   Tue Feb  1 15:09:17 2011 +0100

nucleus/shadow: plug race while mapping a shadow

We should not allow linux interrupts to preempt xnshadow_map() while
the emerging shadow bears the XNMAPPED flag but not XNRELAX. Such race
may cause the debug code in do_schedule_event() to trigger over
preemptible kernels, since a primary mode Xenomai thread might be seen
as resuming on the linux side.

A typical backtrace of such issue is as follows (this one was caught
on x86_64):

Call Trace:
 [<ffffffff81515204>] preempt_schedule_irq+0x64/0xb0
 [<ffffffff81080341>] __ipipe_preempt_schedule_irq+0x51/0x150
 [<ffffffff81518635>] retint_kernel+0x35/0x40
 [<ffffffff8109ff54>] ? xnpod_suspend_thread+0x4/0x940
 [<ffffffff810dd413>] xnshadow_map+0x283/0x370

The fix simply gathers the code marking the emerging shadow as mapped
AND relaxed in the same IRQ free section (linux-wise).

---

 ksrc/nucleus/shadow.c |    8 +++++---
 1 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/ksrc/nucleus/shadow.c b/ksrc/nucleus/shadow.c
index 717a8a0..201becc 100644
--- a/ksrc/nucleus/shadow.c
+++ b/ksrc/nucleus/shadow.c
@@ -1306,7 +1306,8 @@ int xnshadow_map(xnthread_t *thread, xncompletion_t 
__user *u_completion,
 {
        struct xnthread_start_attr attr;
        xnarch_cpumask_t affinity;
-       unsigned muxid, magic;
+       unsigned int muxid, magic;
+       unsigned long flags;
        int ret;
 
        if (!xnthread_test_state(thread, XNSHADOW))
@@ -1368,10 +1369,11 @@ int xnshadow_map(xnthread_t *thread, xncompletion_t 
__user *u_completion,
        xnarch_init_shadow_tcb(xnthread_archtcb(thread), thread,
                               xnthread_name(thread));
        xnshadow_thrptd(current) = thread;
+       thread->u_mode = u_mode;
+       local_irq_save(flags);
        xnthread_set_state(thread, XNMAPPED);
        xnpod_suspend_thread(thread, XNRELAX, XN_INFINITE, XN_RELATIVE, NULL);
-
-       thread->u_mode = u_mode;
+       local_irq_restore(flags);
 
        if (u_completion) {
                /*


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

Reply via email to