Module: xenomai-head Branch: master Commit: 9f1f45aecdbb4123f893dcfd3ae5c37e5a9e560a URL: http://git.xenomai.org/?p=xenomai-head.git;a=commit;h=9f1f45aecdbb4123f893dcfd3ae5c37e5a9e560a
Author: Philippe Gerum <[email protected]> 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 cleared). 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, xnthread_base_priority(thread)); + 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 [email protected] https://mail.gna.org/listinfo/xenomai-git
