diff options
author | Michael Anthony Knyszek <mknyszek@google.com> | 2019-05-17 14:48:04 +0000 |
---|---|---|
committer | Michael Knyszek <mknyszek@google.com> | 2019-05-24 15:34:57 +0000 |
commit | 7ed7669c0d35768dbb73eb33d7dc0098e45421b1 (patch) | |
tree | 33210a5887e63784342843d563c604e3dbce1216 /src/runtime/mstats.go | |
parent | db3255536cdbdba9d6f38da9c3bb1faf55f63277 (diff) | |
download | go-7ed7669c0d35768dbb73eb33d7dc0098e45421b1.tar.gz go-7ed7669c0d35768dbb73eb33d7dc0098e45421b1.zip |
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/mstats.go')
-rw-r--r-- | src/runtime/mstats.go | 3 |
1 files changed, 3 insertions, 0 deletions
diff --git a/src/runtime/mstats.go b/src/runtime/mstats.go index 9250865ed1..421580eec3 100644 --- a/src/runtime/mstats.go +++ b/src/runtime/mstats.go @@ -470,6 +470,9 @@ func readGCStats(pauses *[]uint64) { }) } +// readGCStats_m must be called on the system stack because it acquires the heap +// lock. See mheap for details. +//go:systemstack func readGCStats_m(pauses *[]uint64) { p := *pauses // Calling code in runtime/debug should make the slice large enough. |