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

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    |   22 ++++++++++++++++++++++
 2 files changed, 24 insertions(+), 0 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..4b57032 100644
--- a/ksrc/nucleus/shadow.c
+++ b/ksrc/nucleus/shadow.c
@@ -999,6 +999,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 +1040,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 +1336,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 +2518,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 +2533,21 @@ 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);
+               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 +2555,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