Module: xenomai-jki
Branch: for-upstream
Commit: 8c2cdb6e586d69eaf06c176645c7665d8b79bb4c
URL:    
http://git.xenomai.org/?p=xenomai-jki.git;a=commit;h=8c2cdb6e586d69eaf06c176645c7665d8b79bb4c

Author: Jan Kiszka <jan.kis...@siemens.com>
Date:   Fri Jul  8 18:19:09 2011 +0200

nucleus: Fix race between gatekeeper and task signal wakeup

As we cannot synchronize with Linux try_to_wake_up directly while it
checks if a hijacked task may be woken up, take nklock while setting
TASK_ATOMICSWITCH and check for pending signals beforehand. This also
removes any valid reason to return from schedule in xnshadow_harden
without being migrated.

Signed-off-by: Jan Kiszka <jan.kis...@siemens.com>

---

 ksrc/nucleus/shadow.c |   45 +++++++++++++++++++++++++++------------------
 1 files changed, 27 insertions(+), 18 deletions(-)

diff --git a/ksrc/nucleus/shadow.c b/ksrc/nucleus/shadow.c
index 235209d..1030817 100644
--- a/ksrc/nucleus/shadow.c
+++ b/ksrc/nucleus/shadow.c
@@ -941,6 +941,7 @@ int xnshadow_harden(void)
        struct xnthread *thread;
        struct xnsched *sched;
        int cpu;
+       spl_t s;
 
 redo:
        thread = xnshadow_thread(this_task);
@@ -950,8 +951,8 @@ redo:
        cpu = task_cpu(this_task);
        sched = xnpod_sched_slot(cpu);
 
-       if (signal_pending(this_task) || down_interruptible(&sched->gksync))
-               /* Grab the request token. */
+       /* Grab the request token. */
+       if (down_interruptible(&sched->gksync))
                return -ERESTARTSYS;
 
        if (thread->u_mode)
@@ -985,32 +986,40 @@ redo:
                   "thread %p thread_name %s comm %s",
                   thread, xnthread_name(thread), this_task->comm);
 
+       xnlock_get_irqsave(&nklock, s);
+
+       /*
+        * Recheck if there are no signals pending. We must not start the
+        * migration as in that case both Linux and the gatekeeper may resume
+        * the same task.
+        *
+        * TASK_ATOMICSWITCH is tested by try_to_wake_up under rq lock, but
+        * that is not available to us. Holding nklock synchronizes us with
+        * do_sigwake_event to ensure the ATOMICSWITCH will be visible for
+        * try_to_wake_up when we proceed.
+        */
+       if (signal_pending(this_task)) {
+               xnlock_put_irqrestore(&nklock, s);
+
+               preempt_enable();
+               up(&sched->gksync);
+
+               return -ERESTARTSYS;
+       }
+
        sched->gktarget = thread;
        thread->gksched = sched;
        xnthread_set_info(thread, XNATOMIC);
        set_current_state(TASK_INTERRUPTIBLE | TASK_ATOMICSWITCH);
 
+       xnlock_put_irqrestore(&nklock, s);
+
        wake_up_process(sched->gatekeeper);
 
        schedule();
        xnthread_clear_info(thread, XNATOMIC);
 
-       /*
-        * Rare case: we might have been awaken by a signal before the
-        * gatekeeper sent us to primary mode. Since
-        * TASK_UNINTERRUPTIBLE is unavailable to us without wrecking
-        * the runqueue's count of uniniterruptible tasks, we just
-        * notice the issue and gracefully fail; the caller will have
-        * to process this signal anyway.
-        */
-       if (rthal_current_domain == rthal_root_domain) {
-               if (XENO_DEBUG(NUCLEUS) && (!signal_pending(this_task)
-                   || this_task->state != TASK_RUNNING))
-                       xnpod_fatal
-                           ("xnshadow_harden() failed for thread %s[%d]",
-                            thread->name, xnthread_user_pid(thread));
-               return -ERESTARTSYS;
-       }
+       XENO_BUGON(NUCLEUS, rthal_current_domain == rthal_root_domain);
 
        /* "current" is now running into the Xenomai domain. */
        sched = xnsched_finish_unlocked_switch(thread->sched);


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

Reply via email to