mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
runtime: don't hold worldsema across mark phase
This change makes it so that worldsema isn't held across the mark phase. This means that various operations like ReadMemStats may now stop the world during the mark phase, reducing latency on such operations. Only three such operations are still no longer allowed to occur during marking: GOMAXPROCS, StartTrace, and StopTrace. For the former it's because any change to GOMAXPROCS impacts GC mark background worker scheduling and the details there are tricky. For the latter two it's because tracing needs to observe consistent GC start and GC end events, and if StartTrace or StopTrace may stop the world during marking, then it's possible for it to see a GC end event without a start or GC start event without an end, respectively. To ensure that GOMAXPROCS and StartTrace/StopTrace cannot proceed until marking is complete, the runtime now holds a new semaphore, gcsema, across the mark phase just like it used to with worldsema. Fixes #19812. Change-Id: I15d43ed184f711b3d104e8f267fb86e335f86bf9 Reviewed-on: https://go-review.googlesource.com/c/go/+/182657 Run-TryBot: Michael Knyszek <mknyszek@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
parent
033299fab6
commit
7b294cdd8d
5 changed files with 62 additions and 13 deletions
|
|
@ -962,8 +962,23 @@ func restartg(gp *g) {
|
|||
// goroutines.
|
||||
func stopTheWorld(reason string) {
|
||||
semacquire(&worldsema)
|
||||
getg().m.preemptoff = reason
|
||||
systemstack(stopTheWorldWithSema)
|
||||
gp := getg()
|
||||
gp.m.preemptoff = reason
|
||||
systemstack(func() {
|
||||
// Mark the goroutine which called stopTheWorld preemptible so its
|
||||
// stack may be scanned.
|
||||
// This lets a mark worker scan us while we try to stop the world
|
||||
// since otherwise we could get in a mutual preemption deadlock.
|
||||
// We must not modify anything on the G stack because a stack shrink
|
||||
// may occur. A stack shrink is otherwise OK though because in order
|
||||
// to return from this function (and to leave the system stack) we
|
||||
// must have preempted all goroutines, including any attempting
|
||||
// to scan our stack, in which case, any stack shrinking will
|
||||
// have already completed by the time we exit.
|
||||
casgstatus(gp, _Grunning, _Gwaiting)
|
||||
stopTheWorldWithSema()
|
||||
casgstatus(gp, _Gwaiting, _Grunning)
|
||||
})
|
||||
}
|
||||
|
||||
// startTheWorld undoes the effects of stopTheWorld.
|
||||
|
|
@ -975,10 +990,31 @@ func startTheWorld() {
|
|||
getg().m.preemptoff = ""
|
||||
}
|
||||
|
||||
// Holding worldsema grants an M the right to try to stop the world
|
||||
// and prevents gomaxprocs from changing concurrently.
|
||||
// stopTheWorldGC has the same effect as stopTheWorld, but blocks
|
||||
// until the GC is not running. It also blocks a GC from starting
|
||||
// until startTheWorldGC is called.
|
||||
func stopTheWorldGC(reason string) {
|
||||
semacquire(&gcsema)
|
||||
stopTheWorld(reason)
|
||||
}
|
||||
|
||||
// startTheWorldGC undoes the effects of stopTheWorldGC.
|
||||
func startTheWorldGC() {
|
||||
startTheWorld()
|
||||
semrelease(&gcsema)
|
||||
}
|
||||
|
||||
// Holding worldsema grants an M the right to try to stop the world.
|
||||
var worldsema uint32 = 1
|
||||
|
||||
// Holding gcsema grants the M the right to block a GC, and blocks
|
||||
// until the current GC is done. In particular, it prevents gomaxprocs
|
||||
// from changing concurrently.
|
||||
//
|
||||
// TODO(mknyszek): Once gomaxprocs and the execution tracer can handle
|
||||
// being changed/enabled during a GC, remove this.
|
||||
var gcsema uint32 = 1
|
||||
|
||||
// stopTheWorldWithSema is the core implementation of stopTheWorld.
|
||||
// The caller is responsible for acquiring worldsema and disabling
|
||||
// preemption first and then should stopTheWorldWithSema on the system
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue