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

Reply via email to