mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
runtime: add general suspendG/resumeG
Currently, the process of suspending a goroutine is tied to stack scanning. In preparation for non-cooperative preemption, this CL abstracts this into general purpose suspendG/resumeG functions. suspendG and resumeG closely follow the existing scang and restartg functions with one exception: the addition of a _Gpreempted status. Currently, preemption tasks (stack scanning) are carried out by the target goroutine if it's in _Grunning. In this new approach, the task is always carried out by the goroutine that called suspendG. Thus, we need a reliable way to drive the target goroutine out of _Grunning until the requesting goroutine is ready to resume it. The new _Gpreempted state provides the handshake: when a runnable goroutine responds to a preemption request, it now parks itself and enters _Gpreempted. The requesting goroutine races to put it in _Gwaiting, which gives it ownership, but also the responsibility to start it again. This CL adds several TODOs about improving the synchronization on the G status. The existing code already has these problems; we're just taking note of them. The next CL will remove the now-dead scang and preemptscan. For #10958, #24543. Change-Id: I16dbf87bea9d50399cc86719c156f48e67198f16 Reviewed-on: https://go-review.googlesource.com/c/go/+/201137 Run-TryBot: Austin Clements <austin@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
parent
46e0d724b3
commit
3f834114ab
6 changed files with 313 additions and 11 deletions
|
|
@ -78,6 +78,13 @@ const (
|
|||
// stack is owned by the goroutine that put it in _Gcopystack.
|
||||
_Gcopystack // 8
|
||||
|
||||
// _Gpreempted means this goroutine stopped itself for a
|
||||
// suspendG preemption. It is like _Gwaiting, but nothing is
|
||||
// yet responsible for ready()ing it. Some suspendG must CAS
|
||||
// the status to _Gwaiting to take responsibility for
|
||||
// ready()ing this G.
|
||||
_Gpreempted // 9
|
||||
|
||||
// _Gscan combined with one of the above states other than
|
||||
// _Grunning indicates that GC is scanning the stack. The
|
||||
// goroutine is not executing user code and the stack is owned
|
||||
|
|
@ -89,11 +96,12 @@ const (
|
|||
//
|
||||
// atomicstatus&~Gscan gives the state the goroutine will
|
||||
// return to when the scan completes.
|
||||
_Gscan = 0x1000
|
||||
_Gscanrunnable = _Gscan + _Grunnable // 0x1001
|
||||
_Gscanrunning = _Gscan + _Grunning // 0x1002
|
||||
_Gscansyscall = _Gscan + _Gsyscall // 0x1003
|
||||
_Gscanwaiting = _Gscan + _Gwaiting // 0x1004
|
||||
_Gscan = 0x1000
|
||||
_Gscanrunnable = _Gscan + _Grunnable // 0x1001
|
||||
_Gscanrunning = _Gscan + _Grunning // 0x1002
|
||||
_Gscansyscall = _Gscan + _Gsyscall // 0x1003
|
||||
_Gscanwaiting = _Gscan + _Gwaiting // 0x1004
|
||||
_Gscanpreempted = _Gscan + _Gpreempted // 0x1009
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -411,6 +419,7 @@ type g struct {
|
|||
waitsince int64 // approx time when the g become blocked
|
||||
waitreason waitReason // if status==Gwaiting
|
||||
preempt bool // preemption signal, duplicates stackguard0 = stackpreempt
|
||||
preemptStop bool // transition to _Gpreempted on preemption; otherwise, just deschedule
|
||||
paniconfault bool // panic (instead of crash) on unexpected fault address
|
||||
preemptscan bool // preempted g does scan for gc
|
||||
gcscandone bool // g has scanned stack; protected by _Gscan bit in status
|
||||
|
|
@ -906,6 +915,7 @@ const (
|
|||
waitReasonTraceReaderBlocked // "trace reader (blocked)"
|
||||
waitReasonWaitForGCCycle // "wait for GC cycle"
|
||||
waitReasonGCWorkerIdle // "GC worker (idle)"
|
||||
waitReasonPreempted // "preempted"
|
||||
)
|
||||
|
||||
var waitReasonStrings = [...]string{
|
||||
|
|
@ -934,6 +944,7 @@ var waitReasonStrings = [...]string{
|
|||
waitReasonTraceReaderBlocked: "trace reader (blocked)",
|
||||
waitReasonWaitForGCCycle: "wait for GC cycle",
|
||||
waitReasonGCWorkerIdle: "GC worker (idle)",
|
||||
waitReasonPreempted: "preempted",
|
||||
}
|
||||
|
||||
func (w waitReason) String() string {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue