diff options
author | 2015-02-09 13:41:24 +0000 | |
---|---|---|
committer | 2015-02-09 13:41:24 +0000 | |
commit | f9b05df0d4f8e471b577e1bbe3e088420c11d56b (patch) | |
tree | b63d0579313d5ca537805b3d78089869da7f792d | |
parent | unifdef have gettext. don't have it, won't have it. (diff) | |
download | wireguard-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.c | 29 | ||||
-rw-r--r-- | sys/kern/init_sysent.c | 4 | ||||
-rw-r--r-- | sys/kern/kern_sig.c | 17 | ||||
-rw-r--r-- | sys/kern/syscalls.master | 4 |
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 |