Module: xenomai-head Branch: master Commit: 86abf6b12baa26679dc01c3713167970190eb7bf URL: http://git.xenomai.org/?p=xenomai-head.git;a=commit;h=86abf6b12baa26679dc01c3713167970190eb7bf
Author: Philippe Gerum <r...@xenomai.org> Date: Mon Oct 18 17:30:29 2010 +0200 posix: introduce SIGSUSP/SIGRESM for pthread_kill() In order to support the red core layer, we need a way to suspend/resume a thread synchronously, using the low-level nucleus services. To this end, this patch introduces two pseudo-signals, namely SIGSUSP and SIGRESM, to respectively call xnpod_suspend_thread() or xnpod_resume_thread() for the target thread. CAVEAT: those are pseudo-signals above SIGRTMAX, so they can't be blocked, or queued, or even set in a sigset. They are just meant for internal usage. They are semantically very different from POSIX's SIGSTOP/SIGCONT, since: - they are thread-specific - they are guaranteed to perform the action synchronously, i.e. the target thread shall be suspended or resumed before the call returns. If SIGSUSP is sent to the current thread, pthread_kill() only returns after SIGRESM is received conversely, sent from another thread. --- include/posix/signal.h | 13 +++++++++++++ ksrc/skins/posix/signal.c | 21 +++++++++++++++++++++ ksrc/skins/posix/syscall.c | 22 ++++++++++++++++++++-- 3 files changed, 54 insertions(+), 2 deletions(-) diff --git a/include/posix/signal.h b/include/posix/signal.h index 50f6c60..78a6b93 100644 --- a/include/posix/signal.h +++ b/include/posix/signal.h @@ -114,4 +114,17 @@ int pthread_sigqueue_np (struct pse51_thread *thread, int sig, union sigval valu #endif /* !(__KERNEL__ || __XENO_SIM__) */ +/* + * Those are pseudo-signals only available with pthread_kill() to + * suspend/resume threads synchronously via the low-level nucleus + * interface. Can't block them, queue them, or even set them in a + * sigset. Those are nasty, strictly anti-POSIX things; we do provide + * them nevertheless only because we are mean people doing harmful + * code for no valid reason. Can't go against your nature, right? + * Nah... (this said, don't blame us for POSIX, we are not _that_ + * mean). + */ +#define SIGSUSP (SIGRTMAX + 1) +#define SIGRESM (SIGRTMAX + 2) + #endif /* _XENO_POSIX_SIGNAL_H */ diff --git a/ksrc/skins/posix/signal.c b/ksrc/skins/posix/signal.c index 94bc3e4..4ab27d6 100644 --- a/ksrc/skins/posix/signal.c +++ b/ksrc/skins/posix/signal.c @@ -529,6 +529,27 @@ int pthread_kill(pthread_t thread, int sig) pse51_siginfo_t *si = NULL; spl_t s; + /* + * Undocumented pseudo-signals to suspend and resume threads + * via the low-level nucleus services. Process them early, + * before anyone can notice... + */ + if (sig == SIGSUSP) { + /* + * The self-suspension case for shadows was handled at + * call site: we must be in primary mode already. + */ + xnpod_suspend_thread(&thread->threadbase, XNSUSP, + XN_INFINITE, XN_RELATIVE, NULL); + if (&thread->threadbase == xnpod_current_thread() && + xnthread_test_info(&thread->threadbase, XNBREAK)) + return -EINTR; + return 0; + } else if (sig == SIGRESM) { + xnpod_resume_thread(&thread->threadbase, XNSUSP); + return 0; + } + if ((unsigned)sig > SIGRTMAX) return EINVAL; diff --git a/ksrc/skins/posix/syscall.c b/ksrc/skins/posix/syscall.c index 25831ab..be5bbb0 100644 --- a/ksrc/skins/posix/syscall.c +++ b/ksrc/skins/posix/syscall.c @@ -441,7 +441,8 @@ static int __pthread_set_name_np(struct pt_regs *regs) static int __pthread_kill(struct pt_regs *regs) { struct pse51_hkey hkey; - pthread_t k_tid; + pthread_t k_tid, curr; + int sig, ret; hkey.u_tid = __xn_reg_arg1(regs); hkey.mm = current->mm; @@ -449,8 +450,25 @@ static int __pthread_kill(struct pt_regs *regs) if (!k_tid) return -ESRCH; + /* + * We have to take care of self-suspension, when the + * underlying shadow thread is currently relaxed. In that + * case, we must switch back to primary before issuing the + * suspend call to the nucleus in pthread_kill(). Marking the + * __pthread_kill syscall as __xn_exec_primary would be + * overkill, since no other signal would require this, so we + * handle that case locally here. + */ + sig = __xn_reg_arg2(regs); + if (sig == SIGSUSP && xnpod_current_p(&k_tid->threadbase)) { + if (!xnpod_shadow_p()) { + ret = xnshadow_harden(); + if (ret) + return ret; + } + } - return -pthread_kill(k_tid, __xn_reg_arg2(regs)); + return -pthread_kill(k_tid, sig); } static int __sem_init(struct pt_regs *regs) _______________________________________________ Xenomai-git mailing list Xenomai-git@gna.org https://mail.gna.org/listinfo/xenomai-git