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

Author: Philippe Gerum <r...@xenomai.org>
Date:   Mon Jun 10 17:38:39 2013 +0200

nucleus: allow personalities to stack

---

 include/cobalt/nucleus/shadow.h |   13 +++++--
 include/cobalt/nucleus/thread.h |   21 +++++------
 kernel/cobalt/nucleus/shadow.c  |   70 ++++++++++++++++++++++++++++++---------
 kernel/cobalt/thread.c          |   16 +++++----
 kernel/cobalt/thread.h          |    2 +-
 5 files changed, 84 insertions(+), 38 deletions(-)

diff --git a/include/cobalt/nucleus/shadow.h b/include/cobalt/nucleus/shadow.h
index cafc0e6..1f3e193 100644
--- a/include/cobalt/nucleus/shadow.h
+++ b/include/cobalt/nucleus/shadow.h
@@ -41,9 +41,9 @@ struct xnpersonality {
        struct {
                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);
+               struct xnpersonality *(*map_thread)(struct xnthread *thread);
+               struct xnpersonality *(*exit_thread)(struct xnthread *thread);
+               struct xnpersonality *(*unmap_thread)(struct xnthread *thread);
        } ops;
        struct module *module;
 };
@@ -116,4 +116,11 @@ void __xnshadow_demote(struct xnthread *thread);
 
 void xnshadow_demote(struct xnthread *thread);
 
+struct xnpersonality *
+xnshadow_push_personality(struct xnthread *thread,
+                         struct xnpersonality *next);
+
+void xnshadow_pop_personality(struct xnthread *thread,
+                             struct xnpersonality *prev);
+
 #endif /* !_XENO_NUCLEUS_SHADOW_H */
diff --git a/include/cobalt/nucleus/thread.h b/include/cobalt/nucleus/thread.h
index c7365fc..b27f893 100644
--- a/include/cobalt/nucleus/thread.h
+++ b/include/cobalt/nucleus/thread.h
@@ -334,6 +334,16 @@ typedef struct xnthread {
 #define xnthread_private(thread)           ((thread)->privdata)
 #define xnthread_personality(thread)       ((thread)->personality)
 
+#define xnthread_run_handler(__t, __h)                                 \
+       do {                                                            \
+               struct xnpersonality *__p__ = (__t)->personality;       \
+               do {                                                    \
+                       if ((__p__)->ops.__h == NULL)                   \
+                               break;                                  \
+                       __p__ = (__p__)->ops.__h(__t);                  \
+               } while (__p__);                                        \
+       } while (0)
+       
 static inline
 struct xnthread_wait_context *xnthread_get_wait_context(struct xnthread 
*thread)
 {
@@ -353,17 +363,6 @@ struct xnthread *xnthread_lookup(xnhandle_t threadh)
        return (thread && xnthread_handle(thread) == threadh) ? thread : NULL;
 }
 
-static inline struct xnpersonality *
-xnthread_set_personality(struct xnthread *thread,
-                        struct xnpersonality *personality)
-{
-       struct xnpersonality *prev = thread->personality;
-
-       thread->personality = personality;
-
-       return prev;
-}
-
 static inline void xnthread_sync_window(struct xnthread *thread)
 {
        if (thread->u_window)
diff --git a/kernel/cobalt/nucleus/shadow.c b/kernel/cobalt/nucleus/shadow.c
index 0ce58b1..303bd6c 100644
--- a/kernel/cobalt/nucleus/shadow.c
+++ b/kernel/cobalt/nucleus/shadow.c
@@ -891,9 +891,7 @@ int xnshadow_map_user(struct xnthread *thread,
         * extension and I-pipe notifications will soon be enabled for
         * it.
         */
-       if (personality->ops.map_thread)
-               personality->ops.map_thread(thread);
-
+       xnthread_run_handler(thread, map_thread);
        ipipe_enable_notifier(current);
 
        attr.mode = 0;
@@ -1019,10 +1017,7 @@ 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);
-
+       xnthread_run_handler(thread, map_thread);
        ipipe_enable_notifier(p);
 
        /*
@@ -1062,16 +1057,13 @@ EXPORT_SYMBOL_GPL(xnshadow_map_kernel);
 
 void xnshadow_unmap(struct xnthread *thread)
 {
-       struct xnpersonality *personality;
        struct xnsys_ppd *sys_ppd;
 
        trace_mark(xn_nucleus, shadow_unmap,
                   "thread %p thread_name %s pid %d",
                   thread, xnthread_name(thread), xnthread_host_pid(thread));
 
-       personality = thread->personality;
-       if (personality->ops.unmap_thread)
-               personality->ops.unmap_thread(thread);
+       xnthread_run_handler(thread, unmap_thread);
 
        xnthread_clear_state(thread, XNMAPPED);
 
@@ -1821,6 +1813,55 @@ struct xnshadow_ppd *xnshadow_ppd_get(unsigned int muxid)
 }
 EXPORT_SYMBOL_GPL(xnshadow_ppd_get);
 
+/**
+ * Stack a new personality over an existing thread.
+ *
+ * This service registers @a thread as a member of the additional
+ * personality @a next.
+ *
+ * @param thread the affected thread.
+ *
+ * @param next the additional personality to declare for @a thread.
+ *
+ * @return A pointer to the previous personality. The caller should
+ * save this pointer for unstacking @a next when applicable via a call
+ * to xnshadow_pop_personality().
+ */
+struct xnpersonality *
+xnshadow_push_personality(struct xnthread *thread,
+                         struct xnpersonality *next)
+{
+       struct xnpersonality *prev = thread->personality;
+
+       thread->personality = next;
+       enter_personality(next);
+
+       return prev;
+}
+EXPORT_SYMBOL_GPL(xnshadow_push_personality);
+
+/**
+ * Pop the topmost personality from a thread.
+ *
+ * This service unregisters @a thread from the topmost personality it
+ * is a member of.
+ *
+ * @param thread the affected thread.
+ *
+ * @param prev the previous personality in effect for @a thread prior
+ * to pushing the topmost one, as returned by the latest call to
+ * xnshadow_push_personality().
+ */
+void xnshadow_pop_personality(struct xnthread *thread,
+                             struct xnpersonality *prev)
+{
+       struct xnpersonality *old = thread->personality;
+
+       thread->personality = prev;
+       leave_personality(old);
+}
+EXPORT_SYMBOL_GPL(xnshadow_pop_personality);
+
 static int handle_head_syscall(struct ipipe_domain *ipd, struct pt_regs *regs)
 {
        int muxid, muxop, switched, ret, sigs;
@@ -2156,7 +2197,6 @@ 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;
@@ -2177,9 +2217,7 @@ 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);
+       xnthread_run_handler(thread, exit_thread);
 
        /* __xnpod_cleanup_thread() -> ... -> xnshadow_unmap() */
        __xnpod_cleanup_thread(thread);
@@ -2195,7 +2233,7 @@ static int handle_taskexit_event(struct task_struct *p) 
/* p == current */
                        ppd_remove_mm(mm, detach_ppd);
        }
 
-       leave_personality(personality);
+       leave_personality(thread->personality);
        destroy_threadinfo();
 
        return EVENT_PROPAGATE;
diff --git a/kernel/cobalt/thread.c b/kernel/cobalt/thread.c
index 5b42dc1..6f202e9 100644
--- a/kernel/cobalt/thread.c
+++ b/kernel/cobalt/thread.c
@@ -181,17 +181,19 @@ static void thread_destroy(pthread_t thread)
        xnheap_schedule_free(&kheap, thread, &thread->link);
 }
 
-void cobalt_thread_unmap(struct xnthread *thread)
+struct xnpersonality *cobalt_thread_unmap(struct xnthread *thread)
 {
        pthread_t tid = thread2pthread(thread);
 
-       if (tid == NULL)
-               return;
+       if (tid) {
+               cobalt_mark_deleted(tid);
+               cobalt_timer_cleanup_thread(tid);
+               thread_destroy(tid);
+               cobalt_thread_unhash(&tid->hkey);
+       }
 
-       cobalt_mark_deleted(tid);
-       cobalt_timer_cleanup_thread(tid);
-       thread_destroy(tid);
-       cobalt_thread_unhash(&tid->hkey);
+       /* We don't stack over any personality, no chaining. */
+       return NULL;
 }
 
 /**
diff --git a/kernel/cobalt/thread.h b/kernel/cobalt/thread.h
index 295dc5f..16d640b 100644
--- a/kernel/cobalt/thread.h
+++ b/kernel/cobalt/thread.h
@@ -122,7 +122,7 @@ int cobalt_sched_setconfig_np(int cpu,
                              union sched_config __user *u_config,
                              size_t len);
 
-void cobalt_thread_unmap(struct xnthread *thread);
+struct xnpersonality *cobalt_thread_unmap(struct xnthread *thread);
 
 void cobalt_thread_pkg_init(u_long rrperiod);
 


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

Reply via email to