summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_clock.c
diff options
context:
space:
mode:
authorguenther <guenther@openbsd.org>2013-10-08 03:50:06 +0000
committerguenther <guenther@openbsd.org>2013-10-08 03:50:06 +0000
commita554f8d9c26f17ff529f06b95d7012ef0acf0fc6 (patch)
treebef7ec274b156d91bea80729c0556b6621f8cfd1 /sys/kern/kern_clock.c
parentIf a thread sends a signal to its own process, then have that thread (diff)
downloadwireguard-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/kern_clock.c')
-rw-r--r--sys/kern/kern_clock.c49
1 files changed, 12 insertions, 37 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);
+ }
}
/*