Module: xenomai-gch Branch: u_mode Commit: 1f14785539e6add86bc583804f0476c56d1ca7f3 URL: http://git.xenomai.org/?p=xenomai-gch.git;a=commit;h=1f14785539e6add86bc583804f0476c56d1ca7f3
Author: Gilles Chanteperdrix <gilles.chanteperd...@xenomai.org> Date: Thu Jun 23 22:57:59 2011 +0200 nucleus: add reference counter to sys_ppd This way, if the main thread is shadowed and the last event is its taskexit event, the ppd are destroyed at this point and not earlier. --- include/nucleus/sys_ppd.h | 1 + ksrc/nucleus/shadow.c | 53 ++++++++++++++++++++++++++++++++------------ 2 files changed, 39 insertions(+), 15 deletions(-) diff --git a/include/nucleus/sys_ppd.h b/include/nucleus/sys_ppd.h index 3ae8581..665e973 100644 --- a/include/nucleus/sys_ppd.h +++ b/include/nucleus/sys_ppd.h @@ -10,6 +10,7 @@ struct xnsys_ppd { #ifdef XNARCH_HAVE_MAYDAY unsigned long mayday_addr; #endif + xnarch_atomic_t refcnt; #define ppd2sys(addr) container_of(addr, struct xnsys_ppd, ppd) }; diff --git a/ksrc/nucleus/shadow.c b/ksrc/nucleus/shadow.c index dcda1e7..08ce462 100644 --- a/ksrc/nucleus/shadow.c +++ b/ksrc/nucleus/shadow.c @@ -673,6 +673,14 @@ static inline void ppd_remove_mm(struct mm_struct *mm, xnlock_put_irqrestore(&nklock, s); } +static void detach_ppd(xnshadow_ppd_t * ppd) +{ + unsigned muxid = xnshadow_ppd_muxid(ppd); + muxtable[muxid].props->eventcb(XNSHADOW_CLIENT_DETACH, ppd); + if (muxtable[muxid].props->module) + module_put(muxtable[muxid].props->module); +} + struct xnvdso *nkvdso; EXPORT_SYMBOL_GPL(nkvdso); @@ -1237,9 +1245,11 @@ int xnshadow_map(xnthread_t *thread, xncompletion_t __user *u_completion, { struct xnthread_start_attr attr; xnarch_cpumask_t affinity; + struct xnsys_ppd *sys_ppd; unsigned int muxid, magic; unsigned long *u_mode; xnheap_t *sem_heap; + spl_t s; int ret; if (!xnthread_test_state(thread, XNSHADOW)) @@ -1278,7 +1288,11 @@ int xnshadow_map(xnthread_t *thread, xncompletion_t __user *u_completion, } } - sem_heap = &xnsys_ppd_get(0)->sem_heap; + xnlock_get_irqsave(&nklock, s); + sys_ppd = xnsys_ppd_get(0); + xnlock_put_irqrestore(&nklock, s); + + sem_heap = &sys_ppd->sem_heap; u_mode = xnheap_alloc(sem_heap, sizeof(*u_mode)); if (!u_mode) return -ENOMEM; @@ -1317,6 +1331,7 @@ int xnshadow_map(xnthread_t *thread, xncompletion_t __user *u_completion, */ xnshadow_thrptd(current) = thread; xnshadow_mmptd(current) = current->mm; + xnarch_atomic_inc(&sys_ppd->refcnt); rthal_enable_notifier(current); @@ -1371,6 +1386,7 @@ EXPORT_SYMBOL_GPL(xnshadow_map); void xnshadow_unmap(xnthread_t *thread) { + struct xnsys_ppd *sys_ppd; struct task_struct *p; if (XENO_DEBUG(NUCLEUS) && @@ -1382,6 +1398,12 @@ void xnshadow_unmap(xnthread_t *thread) xnthread_clear_state(thread, XNMAPPED); rpi_pop(thread); + sys_ppd = xnsys_ppd_get(0); + xnheap_free(&sys_ppd->sem_heap, thread->u_mode); + thread->u_mode = NULL; + + xnarch_atomic_dec(&sys_ppd->refcnt); + trace_mark(xn_nucleus, shadow_unmap, "thread %p thread_name %s pid %d", thread, xnthread_name(thread), p ? p->pid : -1); @@ -1396,9 +1418,6 @@ void xnshadow_unmap(xnthread_t *thread) xnshadow_thrptd(p) = NULL; - xnheap_free(&xnsys_ppd_get(0)->sem_heap, thread->u_mode); - thread->u_mode = NULL; - schedule_linux_call(LO_UNMAP_REQ, p, xnthread_get_magic(thread)); } EXPORT_SYMBOL_GPL(xnshadow_unmap); @@ -2119,14 +2138,14 @@ static void *xnshadow_sys_event(int event, void *data) return ERR_PTR(err); } #endif /* XNARCH_HAVE_MAYDAY */ - + xnarch_atomic_set(&p->refcnt, 1); xnarch_atomic_inc(&muxtable[0].refcnt); return &p->ppd; case XNSHADOW_CLIENT_DETACH: + printk("sys detach !\n"); p = ppd2sys(data); xnheap_destroy_mapped(&p->sem_heap, post_ppd_release, NULL); - xnarch_atomic_dec(&muxtable[0].refcnt); return NULL; } @@ -2474,6 +2493,7 @@ RTHAL_DECLARE_EVENT(losyscall_event); static inline void do_taskexit_event(struct task_struct *p) { xnthread_t *thread = xnshadow_thread(p); /* p == current */ + struct xnsys_ppd *sys_ppd; unsigned magic; spl_t s; @@ -2494,9 +2514,13 @@ static inline void do_taskexit_event(struct task_struct *p) /* xnpod_delete_thread() -> hook -> xnshadow_unmap(). */ 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)) + ppd_remove_mm(xnshadow_mm(p), &detach_ppd); + xnshadow_dereference_skin(magic); trace_mark(xn_nucleus, shadow_exit, "thread %p thread_name %s", thread, xnthread_name(thread)); @@ -2731,24 +2755,23 @@ static inline void do_setsched_event(struct task_struct *p, int priority) RTHAL_DECLARE_SETSCHED_EVENT(setsched_event); -static void detach_ppd(xnshadow_ppd_t * ppd) -{ - unsigned muxid = xnshadow_ppd_muxid(ppd); - muxtable[muxid].props->eventcb(XNSHADOW_CLIENT_DETACH, ppd); - if (muxtable[muxid].props->module) - module_put(muxtable[muxid].props->module); -} - static inline void do_cleanup_event(struct mm_struct *mm) { struct task_struct *p = current; + struct xnsys_ppd *sys_ppd; struct mm_struct *old; old = xnshadow_mm(p); xnshadow_mmptd(p) = mm; - ppd_remove_mm(mm, &detach_ppd); + sys_ppd = xnsys_ppd_get(0); + if (sys_ppd == &__xnsys_global_ppd) + goto done; + + if (xnarch_atomic_dec_and_test(&sys_ppd->refcnt)) + ppd_remove_mm(mm, &detach_ppd); + done: xnshadow_mmptd(p) = old; } _______________________________________________ Xenomai-git mailing list Xenomai-git@gna.org https://mail.gna.org/listinfo/xenomai-git