summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/librthread/rthread.h3
-rw-r--r--lib/librthread/rthread_sig.c45
-rw-r--r--sys/kern/kern_sig.c53
-rw-r--r--sys/sys/proc.h3
4 files changed, 57 insertions, 47 deletions
diff --git a/lib/librthread/rthread.h b/lib/librthread/rthread.h
index 1281b0dcece..0d8dafd08cd 100644
--- a/lib/librthread/rthread.h
+++ b/lib/librthread/rthread.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rthread.h,v 1.18 2008/06/05 21:06:11 kurt Exp $ */
+/* $OpenBSD: rthread.h,v 1.19 2008/10/03 04:22:37 guenther Exp $ */
/*
* Copyright (c) 2004,2005 Ted Unangst <tedu@openbsd.org>
* All Rights Reserved.
@@ -119,7 +119,6 @@ struct pthread {
struct pthread_attr attr;
struct sched_param sched_param;
struct rthread_storage *local_storage;
- int sigpend;
struct rthread_cleanup_fn *cleanup_fns;
};
#define THREAD_DONE 0x001
diff --git a/lib/librthread/rthread_sig.c b/lib/librthread/rthread_sig.c
index 1591cd87ccf..83dc5eee2b7 100644
--- a/lib/librthread/rthread_sig.c
+++ b/lib/librthread/rthread_sig.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rthread_sig.c,v 1.5 2008/04/24 11:44:26 kurt Exp $ */
+/* $OpenBSD: rthread_sig.c,v 1.6 2008/10/03 04:22:37 guenther Exp $ */
/*
* Copyright (c) 2005 Ted Unangst <tedu@openbsd.org>
* All Rights Reserved.
@@ -42,45 +42,14 @@ pthread_sigmask(int how, const sigset_t *set, sigset_t *oset)
return (sigprocmask(how, set, oset) ? errno : 0);
}
-/*
- * implementation of sigwait:
- * 1. we install a handler for each masked signal.
- * 2. we inform the kernel we are interested in this signal set.
- * 3. sleep. the handler will wake us up.
- *
- * this is atomic because the kernel will only divert one signal
- * to a thread until it asks for more.
- */
-static void
-sigwait_handler(int sig)
-{
- pthread_t self = pthread_self();
- self->sigpend = sig;
- thrwakeup(&self->sigpend, 0);
-}
-
-typedef void (*sigfn)(int);
-
int
sigwait(const sigset_t *set, int *sig)
{
- int i;
- sigset_t mask = *set;
- pthread_t self = pthread_self();
- sigfn oldhandlers[NSIG];
-
- for (i = 0; i < NSIG; i++) {
- if (mask & (1 << i))
- oldhandlers[i] = signal(i, sigwait_handler);
- }
-
- thrsigdivert(set);
- thrsleep(&self->sigpend, 0, NULL);
+ int ret;
- for (i = 0; i < NSIG; i++) {
- if (mask & (1 << i))
- signal(i, oldhandlers[i]);
- }
- *sig = self->sigpend;
- return (0);
+ ret = thrsigdivert(set);
+ if (ret == -1)
+ return errno;
+ *sig = ret;
+ return 0;
}
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index 46c766447c8..7fe57337454 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_sig.c,v 1.99 2008/06/10 20:41:52 hshoexer Exp $ */
+/* $OpenBSD: kern_sig.c,v 1.100 2008/10/03 04:22:37 guenther Exp $ */
/* $NetBSD: kern_sig.c,v 1.54 1996/04/22 01:38:32 christos Exp $ */
/*
@@ -784,12 +784,13 @@ psignal(struct proc *p, int signum)
if (p->p_flag & P_WEXIT)
return;
+ mask = sigmask(signum);
+
#ifdef RTHREADS
TAILQ_FOREACH(q, &p->p_p->ps_threads, p_thr_link) {
if (q == p)
continue;
- if (q->p_sigdivert & (1 << signum)) {
- q->p_sigdivert = 0;
+ if (q->p_sigdivert & mask) {
psignal(q, signum);
return;
}
@@ -798,7 +799,6 @@ psignal(struct proc *p, int signum)
KNOTE(&p->p_klist, NOTE_SIGNAL | signum);
- mask = sigmask(signum);
prop = sigprop[signum];
/*
@@ -806,6 +806,14 @@ psignal(struct proc *p, int signum)
*/
if (p->p_flag & P_TRACED)
action = SIG_DFL;
+#ifdef RTHREADS
+ else if (p->p_sigdivert & mask) {
+ p->p_sigwait = signum;
+ atomic_clearbits_int(&p->p_sigdivert, ~0);
+ action = SIG_CATCH;
+ wakeup(&p->p_sigdivert);
+ }
+#endif
else {
/*
* If the signal is being ignored,
@@ -1459,10 +1467,43 @@ sys_nosys(struct proc *p, void *v, register_t *retval)
int
sys_thrsigdivert(struct proc *p, void *v, register_t *retval)
{
- struct sys_thrsigdivert_args *uap = v;
+ struct sys_thrsigdivert_args /* {
+ syscallarg(sigset_t) sigmask;
+ } */ *uap = v;
+ sigset_t mask;
+ sigset_t *m;
+ int error;
+
+ m = NULL;
+ mask = SCARG(uap, sigmask) &~ sigcantmask;
+
+ /* pending signal for this thread? */
+ if (p->p_siglist & mask)
+ m = &p->p_siglist;
+ else if (p->p_p->ps_mainproc->p_siglist & mask)
+ m = &p->p_p->ps_mainproc->p_siglist;
+ if (m != NULL) {
+ int sig = ffs((long)(*m & mask));
+ atomic_clearbits_int(m, sigmask(sig));
+ *retval = sig;
+ return (0);
+ }
- p->p_sigdivert = SCARG(uap, sigmask);
+ p->p_sigwait = 0;
+ atomic_setbits_int(&p->p_sigdivert, mask);
+ error = tsleep(&p->p_sigdivert, PPAUSE|PCATCH, "sigwait", 0);
+ if (p->p_sigdivert) {
+ /* interrupted */
+ KASSERT(error != 0);
+ atomic_clearbits_int(&p->p_sigdivert, ~0);
+ if (error == ERESTART)
+ error = EINTR;
+ return (error);
+ }
+ KASSERT(error == 0);
+ KASSERT(p->p_sigwait != 0);
+ *retval = p->p_sigwait;
return (0);
}
#endif
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index fe13e39a683..91b415b7ac6 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: proc.h,v 1.104 2008/09/19 12:24:55 art Exp $ */
+/* $OpenBSD: proc.h,v 1.105 2008/10/03 04:22:37 guenther Exp $ */
/* $NetBSD: proc.h,v 1.44 1996/04/22 01:23:21 christos Exp $ */
/*-
@@ -185,6 +185,7 @@ struct proc {
int p_dupfd; /* Sideways return value from filedescopen. XXX */
long p_thrslpid; /* for thrsleep syscall */
+ int p_sigwait; /* signal handled by sigwait() */
/* scheduling */