diff options
author | 2013-10-08 03:50:06 +0000 | |
---|---|---|
committer | 2013-10-08 03:50:06 +0000 | |
commit | a554f8d9c26f17ff529f06b95d7012ef0acf0fc6 (patch) | |
tree | bef7ec274b156d91bea80729c0556b6621f8cfd1 /sys/kern | |
parent | If a thread sends a signal to its own process, then have that thread (diff) | |
download | wireguard-openbsd-a554f8d9c26f17ff529f06b95d7012ef0acf0fc6.tar.xz wireguard-openbsd-a554f8d9c26f17ff529f06b95d7012ef0acf0fc6.zip |
Fix delivery of SIGPROF and SIGVTALRM to threaded processes by having
hardclock() set a flag on the running thread and force AST processing,
and then have the thread signal itself from userret().
idea and flag names from FreeBSD
ok jsing@
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/kern_clock.c | 49 | ||||
-rw-r--r-- | sys/kern/kern_exit.c | 4 | ||||
-rw-r--r-- | sys/kern/kern_fork.c | 4 | ||||
-rw-r--r-- | sys/kern/kern_sig.c | 16 | ||||
-rw-r--r-- | sys/kern/kern_time.c | 6 |
5 files changed, 30 insertions, 49 deletions
diff --git a/sys/kern/kern_clock.c b/sys/kern/kern_clock.c index 3d517b0c11b..3f1cdef2e6e 100644 --- a/sys/kern/kern_clock.c +++ b/sys/kern/kern_clock.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_clock.c,v 1.82 2013/08/13 05:52:23 guenther Exp $ */ +/* $OpenBSD: kern_clock.c,v 1.83 2013/10/08 03:50:07 guenther Exp $ */ /* $NetBSD: kern_clock.c,v 1.34 1996/06/09 04:51:03 briggs Exp $ */ /*- @@ -144,40 +144,11 @@ initclocks(void) /* * hardclock does the accounting needed for ITIMER_PROF and ITIMER_VIRTUAL. * We don't want to send signals with psignal from hardclock because it makes - * MULTIPROCESSOR locking very complicated. Instead we use a small trick - * to send the signals safely and without blocking too many interrupts - * while doing that (signal handling can be heavy). - * - * hardclock detects that the itimer has expired, and schedules a timeout - * to deliver the signal. This works because of the following reasons: - * - The timeout can be scheduled with a 1 tick time because we're - * doing it before the timeout processing in hardclock. So it will - * be scheduled to run as soon as possible. - * - The timeout will be run in softclock which will run before we - * return to userland and process pending signals. - * - If the system is so busy that several VIRTUAL/PROF ticks are - * sent before softclock processing, we'll send only one signal. - * But if we'd send the signal from hardclock only one signal would - * be delivered to the user process. So userland will only see one - * signal anyway. + * MULTIPROCESSOR locking very complicated. Instead, to use an idea from + * FreeBSD, we set a flag on the thread and when it goes to return to + * userspace it signals itself. */ -void -virttimer_trampoline(void *v) -{ - struct process *pr = v; - - psignal(pr->ps_mainproc, SIGVTALRM); -} - -void -proftimer_trampoline(void *v) -{ - struct process *pr = v; - - psignal(pr->ps_mainproc, SIGPROF); -} - /* * The real-time timer, interrupting hz times per second. */ @@ -196,11 +167,15 @@ hardclock(struct clockframe *frame) */ if (CLKF_USERMODE(frame) && timerisset(&pr->ps_timer[ITIMER_VIRTUAL].it_value) && - itimerdecr(&pr->ps_timer[ITIMER_VIRTUAL], tick) == 0) - timeout_add(&pr->ps_virt_to, 1); + itimerdecr(&pr->ps_timer[ITIMER_VIRTUAL], tick) == 0) { + atomic_setbits_int(&p->p_flag, P_ALRMPEND); + need_proftick(p); + } if (timerisset(&pr->ps_timer[ITIMER_PROF].it_value) && - itimerdecr(&pr->ps_timer[ITIMER_PROF], tick) == 0) - timeout_add(&pr->ps_prof_to, 1); + itimerdecr(&pr->ps_timer[ITIMER_PROF], tick) == 0) { + atomic_setbits_int(&p->p_flag, P_PROFPEND); + need_proftick(p); + } } /* diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index 2468406d67b..9d246c999f9 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_exit.c,v 1.127 2013/09/14 01:35:00 guenther Exp $ */ +/* $OpenBSD: kern_exit.c,v 1.128 2013/10/08 03:50:07 guenther Exp $ */ /* $NetBSD: kern_exit.c,v 1.39 1996/04/22 01:38:25 christos Exp $ */ /* @@ -185,8 +185,6 @@ exit1(struct proc *p, int rv, int flags) if ((p->p_flag & P_THREAD) == 0) { timeout_del(&pr->ps_realit_to); - timeout_del(&pr->ps_virt_to); - timeout_del(&pr->ps_prof_to); #ifdef SYSVSEM semexit(pr); #endif diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index fb04e7befc0..1255aae6d8f 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_fork.c,v 1.153 2013/08/14 05:26:14 guenther Exp $ */ +/* $OpenBSD: kern_fork.c,v 1.154 2013/10/08 03:50:07 guenther Exp $ */ /* $NetBSD: kern_fork.c,v 1.29 1996/02/09 18:59:34 christos Exp $ */ /* @@ -183,8 +183,6 @@ process_new(struct proc *p, struct process *parent) pr->ps_limit->p_refcnt++; timeout_set(&pr->ps_realit_to, realitexpire, pr); - timeout_set(&pr->ps_virt_to, virttimer_trampoline, pr); - timeout_set(&pr->ps_prof_to, proftimer_trampoline, pr); pr->ps_flags = parent->ps_flags & (PS_SUGID | PS_SUGIDEXEC); if (parent->ps_session->s_ttyvp != NULL && diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 43bd990da95..dd8fbfcc83e 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_sig.c,v 1.154 2013/10/08 03:36:48 guenther Exp $ */ +/* $OpenBSD: kern_sig.c,v 1.155 2013/10/08 03:50:07 guenther Exp $ */ /* $NetBSD: kern_sig.c,v 1.54 1996/04/22 01:38:32 christos Exp $ */ /* @@ -1748,6 +1748,20 @@ userret(struct proc *p) { int sig; + /* send SIGPROF or SIGVTALRM if their timers interrupted this thread */ + if (p->p_flag & P_PROFPEND) { + atomic_clearbits_int(&p->p_flag, P_PROFPEND); + KERNEL_LOCK(); + psignal(p, SIGPROF); + KERNEL_UNLOCK(); + } + if (p->p_flag & P_ALRMPEND) { + atomic_clearbits_int(&p->p_flag, P_ALRMPEND); + KERNEL_LOCK(); + psignal(p, SIGVTALRM); + KERNEL_UNLOCK(); + } + while ((sig = CURSIG(p)) != 0) postsig(sig); diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c index 3e5ca31ef7a..187cb43e4ae 100644 --- a/sys/kern/kern_time.c +++ b/sys/kern/kern_time.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_time.c,v 1.83 2013/10/06 01:27:50 guenther Exp $ */ +/* $OpenBSD: kern_time.c,v 1.84 2013/10/08 03:50:08 guenther Exp $ */ /* $NetBSD: kern_time.c,v 1.20 1996/02/18 11:57:06 fvdl Exp $ */ /* @@ -571,10 +571,6 @@ sys_setitimer(struct proc *p, void *v, register_t *retval) itimerround(&aitv.it_interval); s = splclock(); pr->ps_timer[which] = aitv; - if (which == ITIMER_VIRTUAL) - timeout_del(&pr->ps_virt_to); - if (which == ITIMER_PROF) - timeout_del(&pr->ps_prof_to); splx(s); } |