Skip to content

Commit

Permalink
runtime: make stack barrier locking more robust
Browse files Browse the repository at this point in the history
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 <[email protected]>
TryBot-Result: Gobot Gobot <[email protected]>
Reviewed-by: Ingo Oeser <[email protected]>
Reviewed-by: Russ Cox <[email protected]>
  • Loading branch information
aclements committed Nov 23, 2015
1 parent 0417872 commit 22e57c6
Showing 1 changed file with 11 additions and 1 deletion.
12 changes: 11 additions & 1 deletion src/runtime/mstkbar.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

0 comments on commit 22e57c6

Please sign in to comment.