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

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

nucleus: Fix race between gatekeeper and thread deletion

A task whose shadow is queued in some gatekeeper's gktarget may
terminate. In that case, we zapped the thread structure and left the
gatekeeper with an invalid reference behind.

Fix it by keeping a reference to the associated sched of the busy
gatekeeper in the thread structure and synchronize with that helper if
the tasks is supposed to terminate.

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

---

 include/nucleus/thread.h |    2 ++
 ksrc/nucleus/shadow.c    |   34 +++++++++++++++++++++++++++++-----
 2 files changed, 31 insertions(+), 5 deletions(-)

diff --git a/include/nucleus/thread.h b/include/nucleus/thread.h
index d5dc531..cfd2ea0 100644
--- a/include/nucleus/thread.h
+++ b/include/nucleus/thread.h
@@ -330,6 +330,8 @@ typedef struct xnthread {
 
 #ifdef CONFIG_XENO_OPT_PERVASIVE
        unsigned long *u_mode;  /* Thread mode variable shared with userland. */
+
+       struct xnsched *gksched;        /* Gatekeeper processing the thread. */
 #endif /* CONFIG_XENO_OPT_PERVASIVE */
 
     XNARCH_DECL_DISPLAY_CONTEXT();
diff --git a/ksrc/nucleus/shadow.c b/ksrc/nucleus/shadow.c
index e357351..85fcc16 100644
--- a/ksrc/nucleus/shadow.c
+++ b/ksrc/nucleus/shadow.c
@@ -898,12 +898,13 @@ static int gatekeeper_thread(void *data)
                target = sched->gktarget;
 
                /*
-                * In the very rare case where the requestor has been
-                * awaken by a signal before we have been able to
-                * process the pending request, just ignore the
-                * latter.
+                * In the very rare case where the requester has been
+                * awaken by a signal or has been deleted before we have
+                * been able to process the pending request, just ignore
+                * the latter.
                 */
-               if ((xnthread_user_task(target)->state & ~TASK_ATOMICSWITCH) == 
TASK_INTERRUPTIBLE) {
+               if (target && (xnthread_user_task(target)->state &
+                              ~TASK_ATOMICSWITCH) == TASK_INTERRUPTIBLE) {
                        rpi_pop(target);
                        xnlock_get_irqsave(&nklock, s);
 #ifdef CONFIG_SMP
@@ -999,6 +1000,7 @@ redo:
                   thread, xnthread_name(thread), this_task->comm);
 
        sched->gktarget = thread;
+       thread->gksched = sched;
        xnthread_set_info(thread, XNATOMIC);
        set_current_state(TASK_INTERRUPTIBLE | TASK_ATOMICSWITCH);
 #ifndef CONFIG_PREEMPT_RT
@@ -1039,6 +1041,7 @@ redo:
        }
 
        /* "current" is now running into the Xenomai domain. */
+       thread->gksched = NULL;
        sched = xnsched_finish_unlocked_switch(thread->sched);
 
        xnsched_finalize_zombie(sched);
@@ -1334,6 +1337,8 @@ int xnshadow_map(xnthread_t *thread, xncompletion_t 
__user *u_completion,
        thread->u_mode = u_mode;
        __xn_put_user(xnheap_mapped_offset(sem_heap, u_mode), u_mode_offset);
 
+       thread->gksched = NULL;
+
        xnthread_set_state(thread, XNMAPPED);
        xnpod_suspend_thread(thread, XNRELAX, XN_INFINITE, XN_RELATIVE, NULL);
 
@@ -2514,6 +2519,7 @@ static inline void do_taskexit_event(struct task_struct 
*p)
 {
        xnthread_t *thread = xnshadow_thread(p); /* p == current */
        struct xnsys_ppd *sys_ppd;
+       struct xnsched *gksched;
        unsigned magic;
        spl_t s;
 
@@ -2528,6 +2534,22 @@ static inline void do_taskexit_event(struct task_struct 
*p)
        magic = xnthread_get_magic(thread);
 
        xnlock_get_irqsave(&nklock, s);
+
+       gksched = thread->gksched;
+       if (gksched) {
+               xnlock_put_irqrestore(&nklock, s);
+
+               /*
+                * Synchronize with gatekeeper so that it no longer holds any
+                * reference to this thread.
+                */
+               down(&gksched->gksync);
+               gksched->gktarget = NULL;
+               up(&gksched->gksync);
+
+               xnlock_get_irqsave(&nklock, s);
+       }
+
        /* Prevent wakeup call from xnshadow_unmap(). */
        xnshadow_thrptd(p) = NULL;
        xnthread_archtcb(thread)->user_task = NULL;
@@ -2535,7 +2557,9 @@ static inline void do_taskexit_event(struct task_struct 
*p)
        xnsched_set_resched(thread->sched);
        xnpod_delete_thread(thread);
        sys_ppd = xnsys_ppd_get(0);
+
        xnlock_put_irqrestore(&nklock, s);
+
        xnpod_schedule();
 
        if (!xnarch_atomic_get(&sys_ppd->refcnt))


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

Reply via email to