Module: xenomai-head
Branch: master
Commit: b40b368a8e82fca055ce828d29aecc13561e913c
URL:    
http://git.xenomai.org/?p=xenomai-head.git;a=commit;h=b40b368a8e82fca055ce828d29aecc13561e913c

Author: Gilles Chanteperdrix <gilles.chanteperd...@xenomai.org>
Date:   Tue Nov 24 00:41:06 2009 +0100

nucleus: implement kernel-space per-thread per-skin signals handling.

---

 include/nucleus/shadow.h     |    6 ++
 include/nucleus/thread.h     |    7 +++
 ksrc/nucleus/pod.c           |    5 +-
 ksrc/nucleus/shadow.c        |  119 +++++++++++++++++++++++++++++++++++++++--
 ksrc/nucleus/thread.c        |    4 ++
 ksrc/skins/native/syscall.c  |    1 +
 ksrc/skins/posix/syscall.c   |    1 +
 ksrc/skins/psos+/syscall.c   |    1 +
 ksrc/skins/rtai/syscall.c    |    1 +
 ksrc/skins/rtdm/syscall.c    |    1 +
 ksrc/skins/uitron/syscall.c  |    1 +
 ksrc/skins/vrtx/syscall.c    |    1 +
 ksrc/skins/vxworks/syscall.c |    1 +
 13 files changed, 141 insertions(+), 8 deletions(-)

diff --git a/include/nucleus/shadow.h b/include/nucleus/shadow.h
index 236896f..0742044 100644
--- a/include/nucleus/shadow.h
+++ b/include/nucleus/shadow.h
@@ -41,12 +41,14 @@ struct pt_regs;
 struct timespec;
 struct timeval;
 struct xntbase;
+union xnsiginfo;
 
 struct xnskin_props {
        const char *name;
        unsigned magic;
        int nrcalls;
        void *(*eventcb)(int, void *);
+       int (*sig_unqueue)(struct xnthread *thread, union xnsiginfo __user *si);
        xnsysent_t *systab;
        struct xntbase **timebasep;
        struct module *module;
@@ -103,6 +105,10 @@ void xnshadow_rpi_check(void);
 
 extern struct xnskin_slot muxtable[];
 
+int xnshadow_mark_sig(struct xnthread *thread, unsigned muxid);
+
+void xnshadow_clear_sig(struct xnthread *thread, unsigned muxid);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/nucleus/thread.h b/include/nucleus/thread.h
index 1124eb4..31c33d6 100644
--- a/include/nucleus/thread.h
+++ b/include/nucleus/thread.h
@@ -326,6 +326,8 @@ typedef struct xnthread {
 
 #ifdef CONFIG_XENO_OPT_PERVASIVE
        unsigned long __user *u_mode;   /* Thread mode variable in userland. */
+
+       unsigned u_sigpending;          /* One bit per skin */
 #endif /* CONFIG_XENO_OPT_PERVASIVE */
 
     XNARCH_DECL_DISPLAY_CONTEXT();
@@ -385,6 +387,11 @@ typedef struct xnhook {
 #define xnthread_affine_p(thread, cpu)     xnarch_cpu_isset(cpu, 
(thread)->affinity)
 #define xnthread_get_exectime(thread)      
xnstat_exectime_get_total(&(thread)->stat.account)
 #define xnthread_get_lastswitch(thread)    
xnstat_exectime_get_last_switch((thread)->sched)
+#ifdef CONFIG_XENO_OPT_PERVASIVE
+#define xnthread_sigpending(thread) ((thread)->u_sigpending)
+#define xnthread_set_sigpending(thread, pending) \
+       ((thread)->u_sigpending = (pending))
+#endif /* CONFIG_XENO_OPT_PERVASIVE */
 
 /* Class-level operations for threads. */
 static inline int xnthread_get_denormalized_prio(struct xnthread *t, int 
coreprio)
diff --git a/ksrc/nucleus/pod.c b/ksrc/nucleus/pod.c
index 5690e95..4144ccd 100644
--- a/ksrc/nucleus/pod.c
+++ b/ksrc/nucleus/pod.c
@@ -1409,8 +1409,9 @@ void xnpod_suspend_thread(xnthread_t *thread, xnflags_t 
mask,
                 * context, to collect and act upon the pending Linux
                 * signal.
                 */
-               if ((mask & XNRELAX) == 0 &&
-                   xnthread_test_info(thread, XNKICKED)) {
+               if ((mask & XNRELAX) == 0 
+                   && (xnthread_sigpending(thread) 
+                       || xnthread_test_info(thread, XNKICKED))) {
                        xnthread_clear_info(thread, XNRMID | XNTIMEO);
                        xnthread_set_info(thread, XNBREAK);
                        goto unlock_and_exit;
diff --git a/ksrc/nucleus/shadow.c b/ksrc/nucleus/shadow.c
index 23afea6..0c94a60 100644
--- a/ksrc/nucleus/shadow.c
+++ b/ksrc/nucleus/shadow.c
@@ -652,6 +652,89 @@ static inline void ppd_remove_mm(struct mm_struct *mm,
        xnlock_put_irqrestore(&nklock, s);
 }
 
+/** 
+ * Mark the per-thread per-skin signal condition for the skin whose
+ * muxid is @a muxid.
+ * 
+ * @param thread the target thread;
+ * @param muxid the muxid of the skin for which the signal is marked
+ * pending.
+ * 
+ * @return whether rescheduling is needed.
+ */
+int xnshadow_mark_sig(xnthread_t *thread, unsigned muxid)
+{
+       int need_resched = 0;
+
+       if (xnthread_test_state(thread, XNMAPPED)) {
+               spl_t s;
+
+               xnlock_get_irqsave(&nklock, s);
+               thread->u_sigpending |= (1 << muxid);
+               need_resched = xnpod_unblock_thread(thread);
+               xnlock_put_irqrestore(&nklock, s);
+       }
+
+       return need_resched;
+}
+EXPORT_SYMBOL_GPL(xnshadow_mark_sig);
+
+/** 
+ * Clear the per-thrad per-skin signal condition.
+ * 
+ * Called with nklock locked irqs off.
+ *
+ * @param thread the target thrad
+ * @param muxid 
+ */
+void xnshadow_clear_sig(xnthread_t *thread, unsigned muxid)
+{
+       thread->u_sigpending &= ~(1 << muxid);
+}
+EXPORT_SYMBOL_GPL(xnshadow_clear_sig);
+
+static inline void handle_rt_signals(xnthread_t *thread,
+                                    struct pt_regs *regs,
+                                    int sysflags)
+{
+       int (*sig_unqueue)(xnthread_t *thread, union xnsiginfo __user *si);
+       struct xnsig __user *u_sigs;
+       const unsigned max_sigs = ARRAY_SIZE(u_sigs->pending);
+       unsigned muxid, i, pending;
+       int rc, res;
+
+       u_sigs = (struct xnsig __user *) __xn_reg_sigp(regs);
+       res = -ERESTART;
+       i = 0;
+
+       pending = xnthread_sigpending(thread);
+       do {
+               muxid = ffnz(pending);
+               sig_unqueue = muxtable[muxid].props->sig_unqueue;
+
+               do {
+                       __xn_put_user(muxid, &u_sigs->pending[i].muxid);
+                       rc = sig_unqueue(thread, &u_sigs->pending[i].si);
+                       if (res == -ERESTART)
+                               res = rc;
+                       ++i;
+                       pending = xnthread_sigpending(thread);
+               } while ((pending & (1 << muxid)) && i < max_sigs);
+
+       } while (pending && i < max_sigs);
+       __xn_put_user(i, &u_sigs->nsigs);
+       __xn_put_user(pending != 0, &u_sigs->remaining);
+
+/* In the case when we are going to handle linux signals, do not let
+   the kernel handle the syscall restart to give a chance to the
+   xenomai handlers to be executed. */
+       if (__xn_interrupted_p(regs) 
+           || __xn_reg_rval(regs) == -ERESTARTSYS
+           || __xn_reg_rval(regs) == -ERESTARTNOHAND)
+               __xn_error_return(regs, ((sysflags & __xn_exec_norestart)
+                                        ? -EINTR : res));
+}
+
 static inline void request_syscall_restart(xnthread_t *thread,
                                           struct pt_regs *regs,
                                           int sysflags)
@@ -1296,6 +1379,8 @@ void xnshadow_unmap(xnthread_t *thread)
        p = xnthread_archtcb(thread)->user_task;
 
        xnthread_clear_state(thread, XNMAPPED);
+       xnthread_set_sigpending(thread, 0); /* thread->sipending must be 0 for
+                                    non mapped threads. */
        rpi_pop(thread);
 
        trace_mark(xn_nucleus, shadow_unmap,
@@ -1859,6 +1944,11 @@ static int xnshadow_sys_current_info(struct pt_regs 
*regs)
        return __xn_safe_copy_to_user(us_info, &info, sizeof(*us_info));
 }
 
+static int xnshadow_sys_get_next_sigs(struct pt_regs *regs)
+{
+       return -EINTR;
+}
+
 static xnsysent_t __systab[] = {
        [__xn_sys_migrate] = {&xnshadow_sys_migrate, __xn_exec_current},
        [__xn_sys_arch] = {&xnshadow_sys_arch, __xn_exec_any},
@@ -1871,6 +1961,8 @@ static xnsysent_t __systab[] = {
        [__xn_sys_current] = {&xnshadow_sys_current, __xn_exec_any},
        [__xn_sys_current_info] =
                {&xnshadow_sys_current_info, __xn_exec_shadow},
+       [__xn_sys_get_next_sigs] = 
+               {&xnshadow_sys_get_next_sigs, __xn_exec_conforming},
 };
 
 static void post_ppd_release(struct xnheap *h)
@@ -1918,6 +2010,7 @@ static struct xnskin_props __props = {
        .nrcalls = sizeof(__systab) / sizeof(__systab[0]),
        .systab = __systab,
        .eventcb = xnshadow_sys_event,
+       .sig_unqueue = NULL,
        .timebasep = NULL,
        .module = NULL
 };
@@ -1939,7 +2032,7 @@ EXPORT_SYMBOL_GPL(xnshadow_send_sig);
 static inline int do_hisyscall_event(unsigned event, unsigned domid, void 
*data)
 {
        struct pt_regs *regs = (struct pt_regs *)data;
-       int muxid, muxop, switched, err;
+       int muxid, muxop, switched, err, sigs;
        struct task_struct *p;
        xnthread_t *thread;
        u_long sysflags;
@@ -2057,9 +2150,16 @@ static inline int do_hisyscall_event(unsigned event, 
unsigned domid, void *data)
 
        __xn_status_return(regs, err);
 
-       if (xnpod_shadow_p() && signal_pending(p))
+       sigs = 0;
+       if (xnpod_shadow_p() && signal_pending(p)) {
+               sigs = 1;
                request_syscall_restart(thread, regs, sysflags);
-       else if ((sysflags & __xn_exec_switchback) != 0 && switched)
+       }
+       if (thread && xnthread_sigpending(thread)) {
+               sigs = 1;
+               handle_rt_signals(thread, regs, sysflags);
+       }
+       if (!sigs && (sysflags & __xn_exec_switchback) != 0 && switched)
                xnshadow_harden();      /* -EPERM will be trapped later if 
needed. */
 
       ret_handled:
@@ -2137,9 +2237,9 @@ RTHAL_DECLARE_EVENT(hisyscall_event);
 
 static inline int do_losyscall_event(unsigned event, unsigned domid, void 
*data)
 {
+       int muxid, muxop, sysflags, switched, err, sigs;
        struct pt_regs *regs = (struct pt_regs *)data;
        xnthread_t *thread = xnshadow_thread(current);
-       int muxid, muxop, sysflags, switched, err;
 
        if (__xn_reg_mux_p(regs))
                goto xenomai_syscall;
@@ -2208,9 +2308,16 @@ static inline int do_losyscall_event(unsigned event, 
unsigned domid, void *data)
 
        __xn_status_return(regs, err);
 
-       if (xnpod_active_p() && xnpod_shadow_p() && signal_pending(current))
+       sigs = 0;
+       if (xnpod_active_p() && xnpod_shadow_p() && signal_pending(current)) {
+               sigs = 1;
                request_syscall_restart(xnshadow_thread(current), regs, 
sysflags);
-       else if ((sysflags & __xn_exec_switchback) != 0 && switched)
+       }
+       if (thread && xnthread_sigpending(thread)) {
+               sigs = 1;
+               handle_rt_signals(thread, regs, sysflags);
+       }
+       if (!sigs && (sysflags & __xn_exec_switchback) != 0 && switched)
                xnshadow_relax(0);
 
       ret_handled:
diff --git a/ksrc/nucleus/thread.c b/ksrc/nucleus/thread.c
index 8e55fca..77fa442 100644
--- a/ksrc/nucleus/thread.c
+++ b/ksrc/nucleus/thread.c
@@ -145,6 +145,10 @@ int xnthread_init(struct xnthread *thread,
 #endif /* CONFIG_XENO_OPT_SELECT */
        initpq(&thread->claimq);
 
+#ifdef CONFIG_XENO_OPT_PERVASIVE
+       xnthread_set_sigpending(thread, 0);
+#endif /* CONFIG_XENO_OPT_PERVASIVE */
+
        thread->sched = sched;
        thread->init_class = sched_class;
        thread->base_class = NULL; /* xnsched_set_policy() will set it. */
diff --git a/ksrc/skins/native/syscall.c b/ksrc/skins/native/syscall.c
index cb9f075..88dc233 100644
--- a/ksrc/skins/native/syscall.c
+++ b/ksrc/skins/native/syscall.c
@@ -4111,6 +4111,7 @@ static struct xnskin_props __props = {
        .nrcalls = sizeof(__systab) / sizeof(__systab[0]),
        .systab = __systab,
        .eventcb = &__shadow_eventcb,
+       .sig_unqueue = NULL,
        .timebasep = &__native_tbase,
        .module = THIS_MODULE
 };
diff --git a/ksrc/skins/posix/syscall.c b/ksrc/skins/posix/syscall.c
index 8c18e37..c08db8b 100644
--- a/ksrc/skins/posix/syscall.c
+++ b/ksrc/skins/posix/syscall.c
@@ -2919,6 +2919,7 @@ static struct xnskin_props __props = {
        .nrcalls = sizeof(__systab) / sizeof(__systab[0]),
        .systab = __systab,
        .eventcb = &pse51_eventcb,
+       .sig_unqueue = NULL,
        .timebasep = &pse51_tbase,
        .module = THIS_MODULE
 };
diff --git a/ksrc/skins/psos+/syscall.c b/ksrc/skins/psos+/syscall.c
index 6a37ecf..a05d231 100644
--- a/ksrc/skins/psos+/syscall.c
+++ b/ksrc/skins/psos+/syscall.c
@@ -1432,6 +1432,7 @@ static struct xnskin_props __props = {
        .nrcalls = sizeof(__systab) / sizeof(__systab[0]),
        .systab = __systab,
        .eventcb = &psos_shadow_eventcb,
+       .sig_unqueue = NULL,
        .timebasep = &psos_tbase,
        .module = THIS_MODULE
 };
diff --git a/ksrc/skins/rtai/syscall.c b/ksrc/skins/rtai/syscall.c
index 2c1583d..634a177 100644
--- a/ksrc/skins/rtai/syscall.c
+++ b/ksrc/skins/rtai/syscall.c
@@ -152,6 +152,7 @@ static struct xnskin_props __props = {
        .nrcalls = sizeof(__systab) / sizeof(__systab[0]),
        .systab = __systab,
        .eventcb = NULL,
+       .sig_unqueue = NULL,
        .timebasep = &rtai_tbase,
        .module = THIS_MODULE
 };
diff --git a/ksrc/skins/rtdm/syscall.c b/ksrc/skins/rtdm/syscall.c
index 388187a..80785ab 100644
--- a/ksrc/skins/rtdm/syscall.c
+++ b/ksrc/skins/rtdm/syscall.c
@@ -170,6 +170,7 @@ static struct xnskin_props __props = {
        .nrcalls = sizeof(__systab) / sizeof(__systab[0]),
        .systab = __systab,
        .eventcb = &rtdm_skin_callback,
+       .sig_unqueue = NULL,
        .timebasep = NULL,
        .module = THIS_MODULE
 };
diff --git a/ksrc/skins/uitron/syscall.c b/ksrc/skins/uitron/syscall.c
index 4442bee..87117d5 100644
--- a/ksrc/skins/uitron/syscall.c
+++ b/ksrc/skins/uitron/syscall.c
@@ -815,6 +815,7 @@ static struct xnskin_props __props = {
        .nrcalls = sizeof(__systab) / sizeof(__systab[0]),
        .systab = __systab,
        .eventcb = &ui_shadow_eventcb,
+       .sig_unqueue = NULL,
        .timebasep = &ui_tbase,
        .module = THIS_MODULE
 };
diff --git a/ksrc/skins/vrtx/syscall.c b/ksrc/skins/vrtx/syscall.c
index 5933d39..87849a7 100644
--- a/ksrc/skins/vrtx/syscall.c
+++ b/ksrc/skins/vrtx/syscall.c
@@ -1310,6 +1310,7 @@ static struct xnskin_props __props = {
        .nrcalls = sizeof(__systab) / sizeof(__systab[0]),
        .systab = __systab,
        .eventcb = NULL,
+       .sig_unqueue = NULL,
        .timebasep = &vrtx_tbase,
        .module = THIS_MODULE
 };
diff --git a/ksrc/skins/vxworks/syscall.c b/ksrc/skins/vxworks/syscall.c
index c5b85fc..eb3661f 100644
--- a/ksrc/skins/vxworks/syscall.c
+++ b/ksrc/skins/vxworks/syscall.c
@@ -1264,6 +1264,7 @@ static struct xnskin_props __props = {
        .nrcalls = sizeof(__systab) / sizeof(__systab[0]),
        .systab = __systab,
        .eventcb = __wind_shadow_eventcb,
+       .sig_unqueue = NULL,
        .timebasep = &wind_tbase,
        .module = THIS_MODULE
 };


_______________________________________________
Xenomai-git mailing list
Xenomai-git@gna.org
https://mail.gna.org/listinfo/xenomai-git

Reply via email to