Module: xenomai-rpm
Branch: for-upstream
Commit: 9f1f45aecdbb4123f893dcfd3ae5c37e5a9e560a

Author: Philippe Gerum <>
Date:   Tue Feb  1 15:09:17 2011 +0100

nucleus/shadow: plug race while mapping a shadow

We should prevent an emerging shadow thread from entering any
Xenomai-installed event notification callback until its TCB is fully
built and consistent. Failing to do so 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 for instance (i.e. non-NULL xnshadow_thread() with XNRELAX

Typical backtraces of such issue are as follows (these were caught on
x86_64, running switchtest + all "torture" tests + pingpong hog
application in parallel, SMP+PREEMPT enabled):

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

or another one may be:

Call Trace:
 [<ffffffff81457f0e>] ? common_interrupt+0xe/0x2c
 [<ffffffff81454d0c>] preempt_schedule_irq+0x5c/0xb0
 [<ffffffff8107d908>] __ipipe_preempt_schedule_irq+0x58/0x140
 [<ffffffff81458075>] retint_kernel+0x35/0x40
 [<ffffffff8107b8cf>] ? ipipe_check_context+0x7f/0x1d0
 [<ffffffff81453fca>] ? wait_for_common+0x14a/0x190
 [<ffffffff810a6417>] xnshadow_map+0x227/0x3a0

The fix simply postpones the enabling of task-related notifications
for the emerging shadow thread until its TCB is fully built. For good
measure, the Xenomai backlink in the task_struct PTD is not set until
that point either, so the emerging thread will be ignored in any case
by the callback code.


 ksrc/nucleus/shadow.c |   22 +++++++++++++---------
 1 files changed, 13 insertions(+), 9 deletions(-)

diff --git a/ksrc/nucleus/shadow.c b/ksrc/nucleus/shadow.c
index 717a8a0..33110f4 100644
--- a/ksrc/nucleus/shadow.c
+++ b/ksrc/nucleus/shadow.c
@@ -1306,7 +1306,7 @@ 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;
        int ret;
        if (!xnthread_test_state(thread, XNSHADOW))
@@ -1355,6 +1355,12 @@ int xnshadow_map(xnthread_t *thread, xncompletion_t 
__user *u_completion,
                   thread, xnthread_name(thread), current->pid,
+       xnarch_init_shadow_tcb(xnthread_archtcb(thread), thread,
+                              xnthread_name(thread));
+       thread->u_mode = u_mode;
+       xnthread_set_state(thread, XNMAPPED);
+       xnpod_suspend_thread(thread, XNRELAX, XN_INFINITE, XN_RELATIVE, NULL);
         * Switch on propagation of normal kernel events for the bound
         * task. This is basically a per-task event filter which
@@ -1362,16 +1368,14 @@ int xnshadow_map(xnthread_t *thread, xncompletion_t 
__user *u_completion,
         * tasks bearing a specific flag, so that we don't uselessly
         * intercept those events when they happen to be caused by
         * plain (i.e. non-Xenomai) Linux tasks.
+        *
+        * CAUTION: we arm the notification callback only when the
+        * shadow TCB is consistent, so that we won't trigger false
+        * positive in debug code from do_schedule_event() and
+        * friends.
-       rthal_enable_notifier(current);
-       xnarch_init_shadow_tcb(xnthread_archtcb(thread), thread,
-                              xnthread_name(thread));
        xnshadow_thrptd(current) = thread;
-       xnthread_set_state(thread, XNMAPPED);
-       xnpod_suspend_thread(thread, XNRELAX, XN_INFINITE, XN_RELATIVE, NULL);
-       thread->u_mode = u_mode;
+       rthal_enable_notifier(current);
        if (u_completion) {

Xenomai-git mailing list

Reply via email to