]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: make stack barrier locking more robust
authorAustin Clements <austin@google.com>
Thu, 19 Nov 2015 18:26:43 +0000 (13:26 -0500)
committerAustin Clements <austin@google.com>
Mon, 23 Nov 2015 19:13:15 +0000 (19:13 +0000)
The stack barrier locking functions use a simple cas lock because they
need to support trylock, but currently don't increment g.m.locks. This
is okay right now because they always run on the system stack or the
signal stack and are hence non-preemtible, but this could lead to
difficult-to-reproduce deadlocks if these conditions change in the
future.

Make these functions more robust by incrementing g.m.locks and making
them nosplit to enforce non-preemtibility.

Change-Id: I73d60a35bd2ad2d81c73aeb20dbd37665730eb1b
Reviewed-on: https://go-review.googlesource.com/17058
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ingo Oeser <nightlyone@googlemail.com>
Reviewed-by: Russ Cox <rsc@golang.org>
src/runtime/mstkbar.go

index 6f5b4598538a2cb1b47640d795456746aba15b67..1c1c2eaf0a323c37546fa0196aff2b629a198e69 100644 (file)
@@ -300,16 +300,26 @@ func setNextBarrierPC(pc uintptr) {
 // This is necessary because a sigprof during barrier installation or
 // removal could observe inconsistencies between the stkbar array and
 // the stack itself and crash.
+//
+//go:nosplit
 func gcLockStackBarriers(gp *g) {
+       acquirem()
        for !atomic.Cas(&gp.stackLock, 0, 1) {
                osyield()
        }
 }
 
+//go:nosplit
 func gcTryLockStackBarriers(gp *g) bool {
-       return atomic.Cas(&gp.stackLock, 0, 1)
+       mp := acquirem()
+       result := atomic.Cas(&gp.stackLock, 0, 1)
+       if !result {
+               releasem(mp)
+       }
+       return result
 }
 
 func gcUnlockStackBarriers(gp *g) {
        atomic.Store(&gp.stackLock, 0)
+       releasem(getg().m)
 }