From 9745e88b224d517018ba8421972a0de5dd1c231c Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Wed, 28 Jun 2017 15:58:59 -0400 Subject: [PATCH] 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 Reviewed-by: Ian Lance Taylor --- src/runtime/proc.go | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/runtime/proc.go b/src/runtime/proc.go index b360f20ee7..9f8729a19b 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -1617,9 +1617,7 @@ func unlockextra(mp *m) { // execLock serializes exec and clone to avoid bugs or unspecified behaviour // around exec'ing while creating/destroying threads. See issue #19546. -// -// TODO: look into using a rwmutex, to avoid serializing thread creation. -var execLock mutex +var execLock rwmutex // Create a new m. It will start off with a call to fn, or else the scheduler. // fn needs to be static and not a heap allocated closure. @@ -1640,14 +1638,14 @@ func newm(fn func(), _p_ *p) { if msanenabled { msanwrite(unsafe.Pointer(&ts), unsafe.Sizeof(ts)) } - lock(&execLock) + execLock.rlock() // Prevent process clone. asmcgocall(_cgo_thread_start, unsafe.Pointer(&ts)) - unlock(&execLock) + execLock.runlock() return } - lock(&execLock) + execLock.rlock() // Prevent process clone. newosproc(mp, unsafe.Pointer(mp.g0.stack.hi)) - unlock(&execLock) + execLock.runlock() } // Stops execution of the current m until new work is available. @@ -2870,13 +2868,14 @@ func syscall_runtime_AfterForkInChild() { // Called from syscall package before Exec. //go:linkname syscall_runtime_BeforeExec syscall.runtime_BeforeExec func syscall_runtime_BeforeExec() { - lock(&execLock) + // Prevent thread creation during exec. + execLock.lock() } // Called from syscall package after Exec. //go:linkname syscall_runtime_AfterExec syscall.runtime_AfterExec func syscall_runtime_AfterExec() { - unlock(&execLock) + execLock.unlock() } // Allocate a new g, with a stack big enough for stacksize bytes. -- 2.50.0