summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpelikan <pelikan@openbsd.org>2015-02-09 13:41:24 +0000
committerpelikan <pelikan@openbsd.org>2015-02-09 13:41:24 +0000
commitf9b05df0d4f8e471b577e1bbe3e088420c11d56b (patch)
treeb63d0579313d5ca537805b3d78089869da7f792d
parentunifdef have gettext. don't have it, won't have it. (diff)
downloadwireguard-openbsd-f9b05df0d4f8e471b577e1bbe3e088420c11d56b.tar.xz
wireguard-openbsd-f9b05df0d4f8e471b577e1bbe3e088420c11d56b.zip
make sigprocmask(2) not take the kernel lock
Tests on a 4-core CPU show setjmp(3) run four times as fast under load. discussed on tech@ some time ago, now by kettenis and guenther, ok deraadt
-rw-r--r--sys/compat/linux/linux_signal.c29
-rw-r--r--sys/kern/init_sysent.c4
-rw-r--r--sys/kern/kern_sig.c17
-rw-r--r--sys/kern/syscalls.master4
4 files changed, 20 insertions, 34 deletions
diff --git a/sys/compat/linux/linux_signal.c b/sys/compat/linux/linux_signal.c
index 22a03ae8dc9..b4d474f7205 100644
--- a/sys/compat/linux/linux_signal.c
+++ b/sys/compat/linux/linux_signal.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: linux_signal.c,v 1.17 2014/03/26 05:23:42 guenther Exp $ */
+/* $OpenBSD: linux_signal.c,v 1.18 2015/02/09 13:41:24 pelikan Exp $ */
/* $NetBSD: linux_signal.c,v 1.10 1996/04/04 23:51:36 christos Exp $ */
/*
@@ -584,7 +584,6 @@ linux_sys_sigprocmask(p, v, retval)
linux_old_sigset_t ss;
sigset_t bs;
int error = 0;
- int s;
*retval = 0;
@@ -604,19 +603,18 @@ linux_sys_sigprocmask(p, v, retval)
linux_old_to_bsd_sigset(&ss, &bs);
- s = splhigh();
-
+ bs &= ~sigcantmask;
switch (SCARG(uap, how)) {
case LINUX_SIG_BLOCK:
- p->p_sigmask |= bs & ~sigcantmask;
+ atomic_setbits_int(&p->p_sigmask, bs);
break;
case LINUX_SIG_UNBLOCK:
- p->p_sigmask &= ~bs;
+ atomic_clearbits_int(&p->p_sigmask, bs);
break;
case LINUX_SIG_SETMASK:
- p->p_sigmask = bs & ~sigcantmask;
+ p->p_sigmask = bs;
break;
default:
@@ -624,8 +622,6 @@ linux_sys_sigprocmask(p, v, retval)
break;
}
- splx(s);
-
return (error);
}
@@ -644,7 +640,6 @@ linux_sys_rt_sigprocmask(p, v, retval)
linux_sigset_t ls;
sigset_t bs;
int error = 0;
- int s;
if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
return (EINVAL);
@@ -667,19 +662,18 @@ linux_sys_rt_sigprocmask(p, v, retval)
linux_to_bsd_sigset(&ls, &bs);
- s = splhigh();
-
+ bs &= ~sigcantmask;
switch (SCARG(uap, how)) {
case LINUX_SIG_BLOCK:
- p->p_sigmask |= bs & ~sigcantmask;
+ atomic_setbits_int(&p->p_sigmask, bs);
break;
case LINUX_SIG_UNBLOCK:
- p->p_sigmask &= ~bs;
+ atomic_clearbits_int(&p->p_sigmask, bs);
break;
case LINUX_SIG_SETMASK:
- p->p_sigmask = bs & ~sigcantmask;
+ p->p_sigmask = bs;
break;
default:
@@ -687,8 +681,6 @@ linux_sys_rt_sigprocmask(p, v, retval)
break;
}
- splx(s);
-
return (error);
}
@@ -727,16 +719,13 @@ linux_sys_sigsetmask(p, v, retval)
} */ *uap = v;
linux_old_sigset_t mask;
sigset_t bsdsig;
- int s;
bsd_to_linux_old_sigset(&p->p_sigmask, (linux_old_sigset_t *)retval);
mask = SCARG(uap, mask);
bsd_to_linux_old_sigset(&bsdsig, &mask);
- s = splhigh();
p->p_sigmask = bsdsig & ~sigcantmask;
- splx(s);
return (0);
}
diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c
index edcb7a510c4..ba8df68d0a4 100644
--- a/sys/kern/init_sysent.c
+++ b/sys/kern/init_sysent.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: init_sysent.c,v 1.162 2015/02/09 13:34:49 deraadt Exp $ */
+/* $OpenBSD: init_sysent.c,v 1.163 2015/02/09 13:41:24 pelikan Exp $ */
/*
* System call switch table.
@@ -124,7 +124,7 @@ struct sysent sysent[] = {
sys_sigaction }, /* 46 = sigaction */
{ 0, 0, SY_NOLOCK | 0,
sys_getgid }, /* 47 = getgid */
- { 2, s(struct sys_sigprocmask_args), 0,
+ { 2, s(struct sys_sigprocmask_args), SY_NOLOCK | 0,
sys_sigprocmask }, /* 48 = sigprocmask */
{ 2, s(struct sys_getlogin_args), 0,
sys_getlogin }, /* 49 = getlogin */
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index dfbab676fd4..761502cb24e 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_sig.c,v 1.177 2014/12/19 05:59:21 tedu Exp $ */
+/* $OpenBSD: kern_sig.c,v 1.178 2015/02/09 13:41:24 pelikan Exp $ */
/* $NetBSD: kern_sig.c,v 1.54 1996/04/22 01:38:32 christos Exp $ */
/*
@@ -439,28 +439,25 @@ sys_sigprocmask(struct proc *p, void *v, register_t *retval)
syscallarg(sigset_t) mask;
} */ *uap = v;
int error = 0;
- int s;
sigset_t mask;
*retval = p->p_sigmask;
- mask = SCARG(uap, mask);
- s = splhigh();
+ mask = SCARG(uap, mask) &~ sigcantmask;
switch (SCARG(uap, how)) {
case SIG_BLOCK:
- p->p_sigmask |= mask &~ sigcantmask;
+ atomic_setbits_int(&p->p_sigmask, mask);
break;
case SIG_UNBLOCK:
- p->p_sigmask &= ~mask;
+ atomic_clearbits_int(&p->p_sigmask, mask);
break;
case SIG_SETMASK:
- p->p_sigmask = mask &~ sigcantmask;
+ p->p_sigmask = mask;
break;
default:
error = EINVAL;
break;
}
- splx(s);
return (error);
}
@@ -754,7 +751,7 @@ trapsignal(struct proc *p, int signum, u_long trapno, int code,
p->p_ru.ru_nsignals++;
(*pr->ps_emul->e_sendsig)(ps->ps_sigact[signum], signum,
p->p_sigmask, trapno, code, sigval);
- p->p_sigmask |= ps->ps_catchmask[signum];
+ atomic_setbits_int(&p->p_sigmask, ps->ps_catchmask[signum]);
if ((ps->ps_sigreset & mask) != 0) {
ps->ps_sigcatch &= ~mask;
if (signum != SIGCONT && sigprop[signum] & SA_IGNORE)
@@ -1378,7 +1375,7 @@ postsig(int signum)
} else {
returnmask = p->p_sigmask;
}
- p->p_sigmask |= ps->ps_catchmask[signum];
+ atomic_setbits_int(&p->p_sigmask, ps->ps_catchmask[signum]);
if ((ps->ps_sigreset & mask) != 0) {
ps->ps_sigcatch &= ~mask;
if (signum != SIGCONT && sigprop[signum] & SA_IGNORE)
diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
index f981e71ed32..59e4f8e084f 100644
--- a/sys/kern/syscalls.master
+++ b/sys/kern/syscalls.master
@@ -1,4 +1,4 @@
-; $OpenBSD: syscalls.master,v 1.150 2015/02/09 13:34:19 deraadt Exp $
+; $OpenBSD: syscalls.master,v 1.151 2015/02/09 13:41:24 pelikan Exp $
; $NetBSD: syscalls.master,v 1.32 1996/04/23 10:24:21 mycroft Exp $
; @(#)syscalls.master 8.2 (Berkeley) 1/13/94
@@ -125,7 +125,7 @@
const struct sigaction *nsa, \
struct sigaction *osa); }
47 STD NOLOCK { gid_t sys_getgid(void); }
-48 STD { int sys_sigprocmask(int how, sigset_t mask); }
+48 STD NOLOCK { int sys_sigprocmask(int how, sigset_t mask); }
49 STD { int sys_getlogin(char *namebuf, u_int namelen); }
50 STD { int sys_setlogin(const char *namebuf); }
#ifdef ACCOUNTING