runtime: minimize time between lockextra/unlockextra

This doesn't fix a bug, but may improve performance in programs that
have many concurrent calls from C to Go.  The old code made several
system calls between lockextra and unlockextra.  That could be happening
while another thread is spinning acquiring lockextra.  This changes the
code to not make any system calls while holding the lock.

Change-Id: I50576478e478670c3d6429ad4e1b7d80f98a19d8
Reviewed-on: https://go-review.googlesource.com/18548
Reviewed-by: Russ Cox <rsc@golang.org>
This commit is contained in:
Ian Lance Taylor 2016-01-12 15:34:03 -08:00
parent f36ee8c249
commit efd93a412e
11 changed files with 25 additions and 21 deletions

View File

@ -147,8 +147,8 @@ func msigsave(mp *m) {
}
//go:nosplit
func msigrestore(mp *m) {
sigprocmask(_SIG_SETMASK, &mp.sigmask, nil)
func msigrestore(sigmask sigset) {
sigprocmask(_SIG_SETMASK, &sigmask, nil)
}
//go:nosplit

View File

@ -123,8 +123,8 @@ func msigsave(mp *m) {
}
//go:nosplit
func msigrestore(mp *m) {
sigprocmask(_SIG_SETMASK, &mp.sigmask, nil)
func msigrestore(sigmask sigset) {
sigprocmask(_SIG_SETMASK, &sigmask, nil)
}
//go:nosplit

View File

@ -126,8 +126,8 @@ func msigsave(mp *m) {
}
//go:nosplit
func msigrestore(mp *m) {
sigprocmask(_SIG_SETMASK, &mp.sigmask, nil)
func msigrestore(sigmask sigset) {
sigprocmask(_SIG_SETMASK, &sigmask, nil)
}
//go:nosplit

View File

@ -213,9 +213,8 @@ func msigsave(mp *m) {
}
//go:nosplit
func msigrestore(mp *m) {
smask := &mp.sigmask
rtsigprocmask(_SIG_SETMASK, smask, nil, int32(unsafe.Sizeof(*smask)))
func msigrestore(sigmask sigset) {
rtsigprocmask(_SIG_SETMASK, &sigmask, nil, int32(unsafe.Sizeof(sigmask)))
}
//go:nosplit

View File

@ -22,7 +22,7 @@ func msigsave(mp *m) {
}
//go:nosplit
func msigrestore(mp *m) {
func msigrestore(sigmask sigset) {
}
//go:nosplit

View File

@ -144,8 +144,8 @@ func msigsave(mp *m) {
}
//go:nosplit
func msigrestore(mp *m) {
sigprocmask(_SIG_SETMASK, &mp.sigmask, nil)
func msigrestore(sigmask sigset) {
sigprocmask(_SIG_SETMASK, &sigmask, nil)
}
//go:nosplit

View File

@ -156,8 +156,8 @@ func msigsave(mp *m) {
}
//go:nosplit
func msigrestore(mp *m) {
sigprocmask(_SIG_SETMASK, mp.sigmask)
func msigrestore(sigmask sigset) {
sigprocmask(_SIG_SETMASK, sigmask)
}
//go:nosplit

View File

@ -26,7 +26,7 @@ func mpreinit(mp *m) {
func msigsave(mp *m) {
}
func msigrestore(mp *m) {
func msigrestore(sigmask sigset) {
}
func sigblock() {

View File

@ -391,7 +391,7 @@ func msigsave(mp *m) {
}
//go:nosplit
func msigrestore(mp *m) {
func msigrestore(sigmask sigset) {
}
//go:nosplit

View File

@ -198,8 +198,8 @@ func msigsave(mp *m) {
}
//go:nosplit
func msigrestore(mp *m) {
sigprocmask(_SIG_SETMASK, &mp.sigmask, nil)
func msigrestore(sigmask sigset) {
sigprocmask(_SIG_SETMASK, &sigmask, nil)
}
//go:nosplit
@ -540,6 +540,7 @@ func sigaltstack(ss *sigaltstackt, oss *sigaltstackt) /* int32 */ {
//go:nosplit
//go:nowritebarrierrec
//go:noescape
func sigprocmask(how int32, set *sigset, oset *sigset) /* int32 */ {
sysvicall3(&libc_sigprocmask, uintptr(how), uintptr(unsafe.Pointer(set)), uintptr(unsafe.Pointer(oset)))
}

View File

@ -1427,20 +1427,24 @@ func dropm() {
// After the call to setg we can only call nosplit functions
// with no pointer manipulation.
mp := getg().m
mnext := lockextra(true)
mp.schedlink.set(mnext)
// Block signals before unminit.
// Unminit unregisters the signal handling stack (but needs g on some systems).
// Setg(nil) clears g, which is the signal handler's cue not to run Go handlers.
// It's important not to try to handle a signal between those two steps.
sigmask := mp.sigmask
sigblock()
unminit()
mnext := lockextra(true)
mp.schedlink.set(mnext)
setg(nil)
msigrestore(mp)
// Commit the release of mp.
unlockextra(mp)
msigrestore(sigmask)
}
// A helper function for EnsureDropM.