diff options
| author | Dan Scales <danscales@google.com> | 2020-04-15 12:35:24 -0700 |
|---|---|---|
| committer | Dan Scales <danscales@google.com> | 2020-05-07 20:45:42 +0000 |
| commit | f9640b88c7e5f4df3350643f3ec6c30c30e8678d (patch) | |
| tree | 3135a1d5eaa231190acd85f20b2eec0b9b48131c /src/runtime/stack.go | |
| parent | 33213039e5d806f93a11561609c804cef7c065b3 (diff) | |
| download | go-f9640b88c7e5f4df3350643f3ec6c30c30e8678d.tar.xz | |
runtime: incorporate Gscan acquire/release into lock ranking order
I added routines that can acquire/release a particular rank without
acquiring/releasing an associated lock. I added lockRankGscan as a rank
for acquiring/releasing the Gscan bit.
castogscanstatus() and casGtoPreemptScan() are acquires of the Gscan
bit. casfrom_Gscanstatus() is a release of the Gscan bit. casgstatus()
is like an acquire and release of the Gscan bit, since it will wait if
Gscan bit is currently set.
We have a cycle between hchan and Gscan. The acquisition of Gscan and
then hchan only happens in syncadjustsudogs() when the G is suspended,
so the main normal ordering (get hchan, then get Gscan) can't be
happening. So, I added a new rank lockRankHchanLeaf that is used when
acquiring hchan locks in syncadjustsudogs. This ranking is set so no
other locks can be acquired except other hchan locks.
Fixes #38922
Change-Id: I58ce526a74ba856cb42078f7b9901f2832e1d45c
Reviewed-on: https://go-review.googlesource.com/c/go/+/228417
Run-TryBot: Dan Scales <danscales@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
Diffstat (limited to 'src/runtime/stack.go')
| -rw-r--r-- | src/runtime/stack.go | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/src/runtime/stack.go b/src/runtime/stack.go index 6e1f07bf73..52e54171cb 100644 --- a/src/runtime/stack.go +++ b/src/runtime/stack.go @@ -794,7 +794,16 @@ func syncadjustsudogs(gp *g, used uintptr, adjinfo *adjustinfo) uintptr { var lastc *hchan for sg := gp.waiting; sg != nil; sg = sg.waitlink { if sg.c != lastc { - lock(&sg.c.lock) + // There is a ranking cycle here between gscan bit and + // hchan locks. Normally, we only allow acquiring hchan + // locks and then getting a gscan bit. In this case, we + // already have the gscan bit. We allow acquiring hchan + // locks here as a special case, since a deadlock can't + // happen because the G involved must already be + // suspended. So, we get a special hchan lock rank here + // that is lower than gscan, but doesn't allow acquiring + // any other locks other than hchan. + lockWithRank(&sg.c.lock, lockRankHchanLeaf) } lastc = sg.c } |
