]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: use rwmutex for execLock
authorAustin Clements <austin@google.com>
Wed, 28 Jun 2017 19:58:59 +0000 (15:58 -0400)
committerAustin Clements <austin@google.com>
Wed, 28 Jun 2017 22:08:59 +0000 (22:08 +0000)
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 <austin@google.com>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/runtime/proc.go

index b360f20ee776075410ce383401438540211d53ff..9f8729a19b3d1c0544c0e6c1352de5ab0e58d771 100644 (file)
@@ -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.