Module: xenomai-forge
Branch: next
Commit: 1860675ef35c5644eabaf2063fd15867c900924d
URL:    
http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=1860675ef35c5644eabaf2063fd15867c900924d

Author: Philippe Gerum <r...@xenomai.org>
Date:   Sun Jun  9 17:16:12 2013 +0200

cobalt/nucleus: introduce per-thread resource management handlers

Extend the operation handlers registered by personalities with
per-thread handlers to be invoked upon thread mapping, exit and
unmapping to/from the real-time system.

This mechanism is useful for managing per-thread resources allocated
by personalities in a more straightforward way than nucleus hooks,
which unfortunately don't know about the originating interfaces.

Handlers are called in sequence during any thread's lifetime, with the
following semantics:

- map_thread() is called when the shadow TCB is fully built for an
  emerging Xenomai thread, prior to enabling the I-pipe notification
  events.  The thread is guaranteed to match "current", unstarted yet,
  running in secondary mode. Interrupts are enabled, no lock is held.

- exit_thread() is invoked on behalf of the task exit handler. The
  thread is guaranteed to be current, running in secondary
  mode. Interrupts are enabled, no lock is held.

- unmap_thread() is invoked last, for performing the ultimate (fast)
  cleanup duties after a thread left the Xenomai system. This thread
  may be non-current (i.e. wiping out a dormant TCB), the current
  domain is unspecified. Interrupts are DISABLED, the nucleus lock is
  HELD.

---

 include/cobalt/nucleus/shadow.h |    8 ++++--
 kernel/cobalt/nucleus/pod.c     |    4 +++
 kernel/cobalt/nucleus/sched.c   |    5 ++++
 kernel/cobalt/nucleus/shadow.c  |   51 ++++++++++++++++++++++++++------------
 kernel/cobalt/rtdm/syscall.c    |    4 +-
 kernel/cobalt/syscall.c         |    4 +-
 6 files changed, 53 insertions(+), 23 deletions(-)

diff --git a/include/cobalt/nucleus/shadow.h b/include/cobalt/nucleus/shadow.h
index 3eba4c7..cafc0e6 100644
--- a/include/cobalt/nucleus/shadow.h
+++ b/include/cobalt/nucleus/shadow.h
@@ -25,7 +25,6 @@
 
 struct xnthread;
 struct xnthread_user_window;
-struct xnmutex;
 struct pt_regs;
 struct timespec;
 struct timeval;
@@ -40,8 +39,11 @@ struct xnpersonality {
        struct xnsyscall *syscalls;
        atomic_t refcnt;
        struct {
-               struct xnshadow_ppd *(*attach)(void);
-               void (*detach)(struct xnshadow_ppd *ppd);
+               struct xnshadow_ppd *(*attach_process)(void);
+               void (*detach_process)(struct xnshadow_ppd *ppd);
+               void (*map_thread)(struct xnthread *thread);
+               void (*exit_thread)(struct xnthread *thread);
+               void (*unmap_thread)(struct xnthread *thread);
        } ops;
        struct module *module;
 };
diff --git a/kernel/cobalt/nucleus/pod.c b/kernel/cobalt/nucleus/pod.c
index 3b99bd9..25cf5d2 100644
--- a/kernel/cobalt/nucleus/pod.c
+++ b/kernel/cobalt/nucleus/pod.c
@@ -812,6 +812,7 @@ static inline int moving_target(struct xnsched *sched, 
struct xnthread *thread)
 
 static void cleanup_thread(struct xnthread *thread) /* nklock held, irqs off */
 {
+       struct xnpersonality *personality = thread->personality;
        struct xnsched *sched = thread->sched;
 
        trace_mark(xn_nucleus, thread_cleanup, "thread %p thread_name %s",
@@ -846,6 +847,9 @@ static void cleanup_thread(struct xnthread *thread) /* 
nklock held, irqs off */
        __xnpod_giveup_fpu(sched, thread);
 
        if (!moving_target(sched, thread)) {
+               if (personality->ops.unmap_thread)
+                       personality->ops.unmap_thread(thread);
+
                xnpod_run_hooks(&nkpod->tdeleteq, thread, "DELETE");
 
                xnsched_forget(thread);
diff --git a/kernel/cobalt/nucleus/sched.c b/kernel/cobalt/nucleus/sched.c
index ae9e767..a45be88 100644
--- a/kernel/cobalt/nucleus/sched.c
+++ b/kernel/cobalt/nucleus/sched.c
@@ -246,6 +246,8 @@ struct xnthread *xnsched_pick_next(struct xnsched *sched)
 /* Must be called with nklock locked, interrupts off. */
 void xnsched_zombie_hooks(struct xnthread *thread)
 {
+       struct xnpersonality *personality = thread->personality;
+
        XENO_BUGON(NUCLEUS, thread->sched->zombie != NULL);
        thread->sched->zombie = thread;
 
@@ -253,6 +255,9 @@ void xnsched_zombie_hooks(struct xnthread *thread)
                   "thread_out %p thread_out_name %s",
                   thread, xnthread_name(thread));
 
+       if (personality->ops.unmap_thread)
+               personality->ops.unmap_thread(thread);
+
        xnpod_run_hooks(&nkpod->tdeleteq, thread, "DELETE");
 
        xnsched_forget(thread);
diff --git a/kernel/cobalt/nucleus/shadow.c b/kernel/cobalt/nucleus/shadow.c
index e19b1ff..dc0e66f 100644
--- a/kernel/cobalt/nucleus/shadow.c
+++ b/kernel/cobalt/nucleus/shadow.c
@@ -238,7 +238,7 @@ static void detach_ppd(struct xnshadow_ppd *ppd)
 
        muxid = xnshadow_ppd_muxid(ppd);
        personality = personalities[muxid];
-       personality->ops.detach(ppd);
+       personality->ops.detach_process(ppd);
        if (personality->module)
                module_put(personality->module);
 }
@@ -884,6 +884,16 @@ int xnshadow_map_user(struct xnthread *thread,
        xnthread_set_state(thread, XNMAPPED);
        xndebug_shadow_init(thread);
        xnarch_atomic_inc(&sys_ppd->refcnt);
+       /*
+        * ->map_thread() handler is invoked after the TCB is fully
+        * built, and when we know for sure that current will go
+        * through our task-exit handler, because it has a shadow
+        * extension and I-pipe notifications will soon be enabled for
+        * it.
+        */
+       if (personality->ops.map_thread)
+               personality->ops.map_thread(thread);
+
        ipipe_enable_notifier(current);
 
        attr.mode = 0;
@@ -1009,6 +1019,10 @@ int xnshadow_map_kernel(struct xnthread *thread, struct 
completion *done)
        init_threadinfo(thread);
        xnthread_set_state(thread, XNMAPPED);
        xndebug_shadow_init(thread);
+
+       if (personality->ops.map_thread)
+               personality->ops.map_thread(thread);
+
        ipipe_enable_notifier(p);
 
        /*
@@ -1340,7 +1354,7 @@ do_bind:
        if (sys_ppd)
                goto muxid_eventcb;
 
-       sys_ppd = personalities[user_muxid]->ops.attach();
+       sys_ppd = personalities[user_muxid]->ops.attach_process();
        if (IS_ERR(sys_ppd)) {
                ret = PTR_ERR(sys_ppd);
                goto fail;
@@ -1354,7 +1368,7 @@ do_bind:
        if (ppd_insert(sys_ppd) == -EBUSY) {
                /* In case of concurrent binding (which can not happen with
                   Xenomai libraries), detach right away the second ppd. */
-               personalities[user_muxid]->ops.detach(sys_ppd);
+               personalities[user_muxid]->ops.detach_process(sys_ppd);
                sys_ppd = NULL;
        }
 
@@ -1373,7 +1387,7 @@ muxid_eventcb:
        if (ppd)
                goto eventcb_done;
 
-       ppd = personality->ops.attach();
+       ppd = personality->ops.attach_process();
        if (IS_ERR(ppd)) {
                ret = PTR_ERR(ppd);
                goto fail_destroy_sys_ppd;
@@ -1391,7 +1405,7 @@ muxid_eventcb:
                 * with Xenomai libraries), detach right away the
                 * second ppd.
                 */
-               personality->ops.detach(ppd);
+               personality->ops.detach_process(ppd);
                ppd = NULL;
        }
 
@@ -1405,7 +1419,7 @@ eventcb_done:
                 */
                if (ppd) {
                        ppd_remove(ppd);
-                       personality->ops.detach(ppd);
+                       personality->ops.detach_process(ppd);
                }
 
                if (personality->module)
@@ -1416,7 +1430,7 @@ eventcb_done:
        fail_destroy_sys_ppd:
                if (sys_ppd) {
                        ppd_remove(sys_ppd);
-                       personalities[user_muxid]->ops.detach(sys_ppd);
+                       personalities[user_muxid]->ops.detach_process(sys_ppd);
                }
        fail:
                return ret;
@@ -1608,7 +1622,7 @@ out:
        return pathname;
 }
 
-static struct xnshadow_ppd *xnshadow_user_attach(void)
+static struct xnshadow_ppd *user_process_attach(void)
 {
        struct xnsys_ppd *p;
        char *exe_path;
@@ -1652,7 +1666,7 @@ static struct xnshadow_ppd *xnshadow_user_attach(void)
        return &p->ppd;
 }
 
-static void xnshadow_user_detach(struct xnshadow_ppd *ppd)
+static void user_process_detach(struct xnshadow_ppd *ppd)
 {
        struct xnsys_ppd *p;
 
@@ -1683,8 +1697,8 @@ static struct xnpersonality user_personality = {
        .nrcalls = ARRAY_SIZE(user_syscalls),
        .syscalls = user_syscalls,
        .ops = {
-               .attach = xnshadow_user_attach,
-               .detach = xnshadow_user_detach,
+               .attach_process = user_process_attach,
+               .detach_process = user_process_detach,
        },
 };
 
@@ -1709,9 +1723,9 @@ EXPORT_SYMBOL_GPL(xnshadow_send_sig);
  * @internal
  * @brief Register a new interface personality.
  *
- * - ops->attach() is called when a user-space process binds to the
- *   personality, on behalf of one of its threads. The attach()
- *   handler may return:
+ * - ops->attach_process() is called when a user-space process binds
+ *   to the personality, on behalf of one of its threads. The
+ *   attach_process() handler may return:
  *
  *   . a pointer to a xnshadow_ppd structure, representing the context
  *   of the calling process for this personality;
@@ -1725,7 +1739,7 @@ EXPORT_SYMBOL_GPL(xnshadow_send_sig);
  * - ops->detach() is called on behalf of an exiting user-space
  *   process which has previously attached to the personality. This
  *   handler is passed a pointer to the per-process data received
- *   earlier from the ops->attach() handler.
+ *   earlier from the ops->attach_process() handler.
  */
 int xnshadow_register_personality(struct xnpersonality *personality)
 {
@@ -2149,6 +2163,7 @@ int ipipe_syscall_hook(struct ipipe_domain *ipd, struct 
pt_regs *regs)
 
 static int handle_taskexit_event(struct task_struct *p) /* p == current */
 {
+       struct xnpersonality *personality;
        struct xnsys_ppd *sys_ppd;
        struct xnthread *thread;
        struct mm_struct *mm;
@@ -2169,6 +2184,10 @@ static int handle_taskexit_event(struct task_struct *p) 
/* p == current */
        if (xnthread_test_state(thread, XNDEBUG))
                unlock_timers();
 
+       personality = thread->personality;
+       if (personality->ops.exit_thread)
+               personality->ops.exit_thread(thread);
+
        /* __xnpod_cleanup_thread() -> hook -> xnshadow_unmap() */
        __xnpod_cleanup_thread(thread);
 
@@ -2181,7 +2200,7 @@ static int handle_taskexit_event(struct task_struct *p) 
/* p == current */
                        ppd_remove_mm(mm, detach_ppd);
        }
 
-       leave_personality(thread->personality);
+       leave_personality(personality);
        destroy_threadinfo();
 
        return EVENT_PROPAGATE;
diff --git a/kernel/cobalt/rtdm/syscall.c b/kernel/cobalt/rtdm/syscall.c
index f11e7e7..c4461fa 100644
--- a/kernel/cobalt/rtdm/syscall.c
+++ b/kernel/cobalt/rtdm/syscall.c
@@ -147,8 +147,8 @@ struct xnpersonality rtdm_personality = {
        .nrcalls = ARRAY_SIZE(rtdm_syscalls),
        .syscalls = rtdm_syscalls,
        .ops = {
-               .attach = rtdm_process_attach,
-               .detach = rtdm_process_detach,
+               .attach_process = rtdm_process_attach,
+               .detach_process = rtdm_process_detach,
        },
 };
 EXPORT_SYMBOL_GPL(rtdm_personality);
diff --git a/kernel/cobalt/syscall.c b/kernel/cobalt/syscall.c
index 447d1ca..c048b66 100644
--- a/kernel/cobalt/syscall.c
+++ b/kernel/cobalt/syscall.c
@@ -354,8 +354,8 @@ struct xnpersonality cobalt_personality = {
        .nrcalls = ARRAY_SIZE(cobalt_syscalls),
        .syscalls = cobalt_syscalls,
        .ops = {
-               .attach = cobalt_process_attach,
-               .detach = cobalt_process_detach,
+               .attach_process = cobalt_process_attach,
+               .detach_process = cobalt_process_detach,
        },
 };
 EXPORT_SYMBOL_GPL(cobalt_personality);


_______________________________________________
Xenomai-git mailing list
Xenomai-git@xenomai.org
http://www.xenomai.org/mailman/listinfo/xenomai-git

Reply via email to