diff options
author | Michael Pratt <mpratt@google.com> | 2020-12-23 15:05:37 -0500 |
---|---|---|
committer | Michael Pratt <mpratt@google.com> | 2021-03-05 22:09:52 +0000 |
commit | d85083911d6ea742901933a544467dad55bb381f (patch) | |
tree | f8f826d01c3ff45af5908c8a1d71befe4439f97c /src/runtime/mprof.go | |
parent | 39bdd41d03725878f1fd6f8b500ba6700f03bdad (diff) | |
download | go-d85083911d6ea742901933a544467dad55bb381f.tar.gz go-d85083911d6ea742901933a544467dad55bb381f.zip |
runtime: encapsulate access to allgs
Correctly accessing allgs is a bit hairy. Some paths need to lock
allglock, some don't. Those that don't are safest using atomicAllG, but
usage is not consistent.
Rather than doing this ad-hoc, move all access* through forEachG /
forEachGRace, the locking and atomic versions, respectively. This will
make it easier to ensure safe access.
* markroot is the only exception, as it has a far-removed guarantee of
safe access via an atomic load of allglen far before actual use.
Change-Id: Ie1c7a8243e155ae2b4bc3143577380c695680e89
Reviewed-on: https://go-review.googlesource.com/c/go/+/279994
Trust: Michael Pratt <mpratt@google.com>
Run-TryBot: Michael Pratt <mpratt@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Diffstat (limited to 'src/runtime/mprof.go')
-rw-r--r-- | src/runtime/mprof.go | 35 |
1 files changed, 19 insertions, 16 deletions
diff --git a/src/runtime/mprof.go b/src/runtime/mprof.go index 128498d69b..c94b8f7cae 100644 --- a/src/runtime/mprof.go +++ b/src/runtime/mprof.go @@ -731,12 +731,13 @@ func goroutineProfileWithLabels(p []StackRecord, labels []unsafe.Pointer) (n int stopTheWorld("profile") + // World is stopped, no locking required. n = 1 - for _, gp1 := range allgs { + forEachGRace(func(gp1 *g) { if isOK(gp1) { n++ } - } + }) if n <= len(p) { ok = true @@ -757,21 +758,23 @@ func goroutineProfileWithLabels(p []StackRecord, labels []unsafe.Pointer) (n int } // Save other goroutines. - for _, gp1 := range allgs { - if isOK(gp1) { - if len(r) == 0 { - // Should be impossible, but better to return a - // truncated profile than to crash the entire process. - break - } - saveg(^uintptr(0), ^uintptr(0), gp1, &r[0]) - if labels != nil { - lbl[0] = gp1.labels - lbl = lbl[1:] - } - r = r[1:] + forEachGRace(func(gp1 *g) { + if !isOK(gp1) { + return } - } + + if len(r) == 0 { + // Should be impossible, but better to return a + // truncated profile than to crash the entire process. + return + } + saveg(^uintptr(0), ^uintptr(0), gp1, &r[0]) + if labels != nil { + lbl[0] = gp1.labels + lbl = lbl[1:] + } + r = r[1:] + }) } startTheWorld() |