aboutsummaryrefslogtreecommitdiff
path: root/src/runtime
diff options
context:
space:
mode:
authorMichael Anthony Knyszek <mknyszek@google.com>2021-11-03 18:49:51 +0000
committerMichael Knyszek <mknyszek@google.com>2021-11-05 17:52:30 +0000
commitdf1837799d418eed6b4921cd1252dd8eae76cd98 (patch)
tree48e37a8198b3aef339b91bebf78e0f2abc658637 /src/runtime
parent6f32d2050d7f0a9d0c529a1a7a21aa8c1d63fa20 (diff)
downloadgo-df1837799d418eed6b4921cd1252dd8eae76cd98.tar.xz
runtime: make consistentHeapStats acquire/release nosplit
consistentHeapStats is updated during a stack allocation, so a stack growth during an acquire or release could cause another acquire to happen before the operation completes fully. This may lead to an invalid sequence number. Fixes #49395. Change-Id: I41ce3393dff80201793e053d4d6394d7b211a5b7 Reviewed-on: https://go-review.googlesource.com/c/go/+/361158 Trust: Michael Knyszek <mknyszek@google.com> Reviewed-by: Michael Pratt <mpratt@google.com> Reviewed-by: Austin Clements <austin@google.com>
Diffstat (limited to 'src/runtime')
-rw-r--r--src/runtime/mstats.go16
1 files changed, 15 insertions, 1 deletions
diff --git a/src/runtime/mstats.go b/src/runtime/mstats.go
index 341ba9a936..c2303e5b8e 100644
--- a/src/runtime/mstats.go
+++ b/src/runtime/mstats.go
@@ -790,7 +790,15 @@ type consistentHeapStats struct {
//
// The caller's P must not change between acquire and
// release. This also means that the caller should not
-// acquire a P or release its P in between.
+// acquire a P or release its P in between. A P also must
+// not acquire a given consistentHeapStats if it hasn't
+// yet released it.
+//
+// nosplit because a stack growth in this function could
+// lead to a stack allocation that could reenter the
+// function.
+//
+//go:nosplit
func (m *consistentHeapStats) acquire() *heapStatsDelta {
if pp := getg().m.p.ptr(); pp != nil {
seq := atomic.Xadd(&pp.statsSeq, 1)
@@ -814,6 +822,12 @@ func (m *consistentHeapStats) acquire() *heapStatsDelta {
// The caller's P must not change between acquire and
// release. This also means that the caller should not
// acquire a P or release its P in between.
+//
+// nosplit because a stack growth in this function could
+// lead to a stack allocation that causes another acquire
+// before this operation has completed.
+//
+//go:nosplit
func (m *consistentHeapStats) release() {
if pp := getg().m.p.ptr(); pp != nil {
seq := atomic.Xadd(&pp.statsSeq, 1)