aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/mcache.go
diff options
context:
space:
mode:
authorMichael Anthony Knyszek <mknyszek@google.com>2019-05-17 14:48:04 +0000
committerMichael Knyszek <mknyszek@google.com>2019-05-24 15:34:57 +0000
commit7ed7669c0d35768dbb73eb33d7dc0098e45421b1 (patch)
tree33210a5887e63784342843d563c604e3dbce1216 /src/runtime/mcache.go
parentdb3255536cdbdba9d6f38da9c3bb1faf55f63277 (diff)
downloadgo-7ed7669c0d35768dbb73eb33d7dc0098e45421b1.tar.xz
runtime: ensure mheap lock stack growth invariant is maintained
Currently there's an invariant in the runtime wherein the heap lock can only be acquired on the system stack, otherwise a self-deadlock could occur if the stack grows while the lock is held. This invariant is upheld and documented in a number of situations (e.g. allocManual, freeManual) but there are other places where the invariant is either not maintained at all which risks self-deadlock (e.g. setGCPercent, gcResetMarkState, allocmcache) or is maintained but undocumented (e.g. gcSweep, readGCStats_m). This change adds go:systemstack to any function that acquires the heap lock or adds a systemstack(func() { ... }) around the critical section, where appropriate. It also documents the invariant on (*mheap).lock directly and updates repetitive documentation to refer to that comment. Fixes #32105. Change-Id: I702b1290709c118b837389c78efde25c51a2cafb Reviewed-on: https://go-review.googlesource.com/c/go/+/177857 Run-TryBot: Michael Knyszek <mknyszek@google.com> Reviewed-by: Austin Clements <austin@google.com>
Diffstat (limited to 'src/runtime/mcache.go')
-rw-r--r--src/runtime/mcache.go11
1 files changed, 7 insertions, 4 deletions
diff --git a/src/runtime/mcache.go b/src/runtime/mcache.go
index 7895e489bc..0cb21f7190 100644
--- a/src/runtime/mcache.go
+++ b/src/runtime/mcache.go
@@ -83,10 +83,13 @@ type stackfreelist struct {
var emptymspan mspan
func allocmcache() *mcache {
- lock(&mheap_.lock)
- c := (*mcache)(mheap_.cachealloc.alloc())
- c.flushGen = mheap_.sweepgen
- unlock(&mheap_.lock)
+ var c *mcache
+ systemstack(func() {
+ lock(&mheap_.lock)
+ c = (*mcache)(mheap_.cachealloc.alloc())
+ c.flushGen = mheap_.sweepgen
+ unlock(&mheap_.lock)
+ })
for i := range c.alloc {
c.alloc[i] = &emptymspan
}