Module: xenomai-gch Branch: for-head Commit: 98086b244feb46044f23d9b201dbc22931a16c7b URL: http://git.xenomai.org/?p=xenomai-gch.git;a=commit;h=98086b244feb46044f23d9b201dbc22931a16c7b
Author: Gilles Chanteperdrix <gilles.chanteperd...@xenomai.org> Date: Tue Nov 24 00:41:06 2009 +0100 nucleus: implement per-thread per-skin signals handling. --- include/nucleus/shadow.h | 6 ++ include/nucleus/thread.h | 5 ++ 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, 139 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..b588bbf 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,9 @@ 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) +#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..d1b2a38 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(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(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_arg6(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); + thread->u_sigpending = 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..92ea21a 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 + thread->u_sigpending = 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