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

Author: Jan Kiszka <[email protected]>
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 <[email protected]>

---

 include/nucleus/thread.h |    2 ++
 ksrc/nucleus/shadow.c    |   23 +++++++++++++++++++++++
 2 files changed, 25 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 eea9151..235209d 100644
--- a/ksrc/nucleus/shadow.c
+++ b/ksrc/nucleus/shadow.c
@@ -986,6 +986,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);
 
@@ -1014,6 +1015,8 @@ redo:
        /* "current" is now running into the Xenomai domain. */
        sched = xnsched_finish_unlocked_switch(thread->sched);
 
+       thread->gksched = NULL;
+
        xnsched_finalize_zombie(sched);
 
 #ifdef CONFIG_XENO_HW_FPU
@@ -1307,6 +1310,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);
 
@@ -2488,6 +2493,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;
 
@@ -2502,6 +2508,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;
@@ -2509,7 +2530,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
[email protected]
https://mail.gna.org/listinfo/xenomai-git

Reply via email to