Skip to content

Commit 9745e88

Browse files
committed
runtime: use rwmutex for execLock
Currently the execLock is a mutex, which has the unfortunate side-effect of serializing all thread creation. This replaces it with an rwmutex so threads can be created in parallel, but exec still blocks thread creation. Fixes #20738. Change-Id: Ia8f30a92053c3d28af460b0da71176abe5fd074b Reviewed-on: https://go-review.googlesource.com/47072 Run-TryBot: Austin Clements <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent 8083297 commit 9745e88

File tree

1 file changed

+8
-9
lines changed

1 file changed

+8
-9
lines changed

src/runtime/proc.go

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1617,9 +1617,7 @@ func unlockextra(mp *m) {
16171617

16181618
// execLock serializes exec and clone to avoid bugs or unspecified behaviour
16191619
// around exec'ing while creating/destroying threads. See issue #19546.
1620-
//
1621-
// TODO: look into using a rwmutex, to avoid serializing thread creation.
1622-
var execLock mutex
1620+
var execLock rwmutex
16231621

16241622
// Create a new m. It will start off with a call to fn, or else the scheduler.
16251623
// fn needs to be static and not a heap allocated closure.
@@ -1640,14 +1638,14 @@ func newm(fn func(), _p_ *p) {
16401638
if msanenabled {
16411639
msanwrite(unsafe.Pointer(&ts), unsafe.Sizeof(ts))
16421640
}
1643-
lock(&execLock)
1641+
execLock.rlock() // Prevent process clone.
16441642
asmcgocall(_cgo_thread_start, unsafe.Pointer(&ts))
1645-
unlock(&execLock)
1643+
execLock.runlock()
16461644
return
16471645
}
1648-
lock(&execLock)
1646+
execLock.rlock() // Prevent process clone.
16491647
newosproc(mp, unsafe.Pointer(mp.g0.stack.hi))
1650-
unlock(&execLock)
1648+
execLock.runlock()
16511649
}
16521650

16531651
// Stops execution of the current m until new work is available.
@@ -2870,13 +2868,14 @@ func syscall_runtime_AfterForkInChild() {
28702868
// Called from syscall package before Exec.
28712869
//go:linkname syscall_runtime_BeforeExec syscall.runtime_BeforeExec
28722870
func syscall_runtime_BeforeExec() {
2873-
lock(&execLock)
2871+
// Prevent thread creation during exec.
2872+
execLock.lock()
28742873
}
28752874

28762875
// Called from syscall package after Exec.
28772876
//go:linkname syscall_runtime_AfterExec syscall.runtime_AfterExec
28782877
func syscall_runtime_AfterExec() {
2879-
unlock(&execLock)
2878+
execLock.unlock()
28802879
}
28812880

28822881
// Allocate a new g, with a stack big enough for stacksize bytes.

0 commit comments

Comments
 (0)