mirror of
https://github.com/golang/go
synced 2024-11-23 19:30:05 -07:00
runtime: avoid double-scanning of stacks
Currently there's a race between stopg scanning another G's stack and the G reaching a preemption point and scanning its own stack. When this race occurs, the G's stack is scanned twice. Currently this is okay, so this race is benign. However, we will shortly be adding stack barriers during the first stack scan, so scanning will no longer be idempotent. To prepare for this, this change ensures that each stack is scanned only once during each GC phase by checking the flag that indicates that the stack has been scanned in this phase before scanning the stack. Change-Id: Id9f4d5e2e5b839bc3f200ec1723a4a12dd677ab4 Reviewed-on: https://go-review.googlesource.com/10458 Reviewed-by: Rick Hudson <rlh@golang.org>
This commit is contained in:
parent
3f6e69aca5
commit
724f8298a8
@ -258,6 +258,9 @@ func gcAssistAlloc(size uintptr, allowAssist bool) {
|
||||
// work is done here.
|
||||
//go:nowritebarrier
|
||||
func gcphasework(gp *g) {
|
||||
if gp.gcworkdone {
|
||||
return
|
||||
}
|
||||
switch gcphase {
|
||||
default:
|
||||
throw("gcphasework in bad gcphase")
|
||||
|
@ -743,8 +743,11 @@ func newstack() {
|
||||
}
|
||||
if gp.preemptscan {
|
||||
for !castogscanstatus(gp, _Gwaiting, _Gscanwaiting) {
|
||||
// Likely to be racing with the GC as it sees a _Gwaiting and does the stack scan.
|
||||
// If so this stack will be scanned twice which does not change correctness.
|
||||
// Likely to be racing with the GC as
|
||||
// it sees a _Gwaiting and does the
|
||||
// stack scan. If so, gcworkdone will
|
||||
// be set and gcphasework will simply
|
||||
// return.
|
||||
}
|
||||
gcphasework(gp)
|
||||
casfrom_Gscanstatus(gp, _Gscanwaiting, _Gwaiting)
|
||||
|
Loading…
Reference in New Issue
Block a user