Skip to content

Commit

Permalink
Revert "runtime: don't hold worldsema across mark phase"
Browse files Browse the repository at this point in the history
This reverts commit 7b294cd, CL 182657.

Reason for revert: This change may be causing latency problems
for applications which call ReadMemStats, because it may cause
all goroutines to stop until the GC completes.

https://golang.org/cl/215157 fixes this problem, but it's too
late in the cycle to land that.

Updates golang#19812.

Change-Id: Iaa26f4dec9b06b9db2a771a44e45f58d0aa8f26d
Reviewed-on: https://go-review.googlesource.com/c/go/+/216358
Run-TryBot: Michael Knyszek <[email protected]>
TryBot-Result: Gobot Gobot <[email protected]>
Reviewed-by: Cherry Zhang <[email protected]>
  • Loading branch information
mknyszek committed Jan 24, 2020
1 parent ad3cef1 commit 64c22b7
Show file tree
Hide file tree
Showing 5 changed files with 13 additions and 62 deletions.
4 changes: 2 additions & 2 deletions src/runtime/debug.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ func GOMAXPROCS(n int) int {
return ret
}

stopTheWorldGC("GOMAXPROCS")
stopTheWorld("GOMAXPROCS")

// newprocs will be processed by startTheWorld
newprocs = int32(n)

startTheWorldGC()
startTheWorld()
return ret
}

Expand Down
9 changes: 0 additions & 9 deletions src/runtime/mgc.go
Original file line number Diff line number Diff line change
Expand Up @@ -1269,7 +1269,6 @@ func gcStart(trigger gcTrigger) {
}

// Ok, we're doing it! Stop everybody else
semacquire(&gcsema)
semacquire(&worldsema)

if trace.enabled {
Expand Down Expand Up @@ -1375,7 +1374,6 @@ func gcStart(trigger gcTrigger) {
Gosched()
}

semrelease(&worldsema)
semrelease(&work.startSema)
}

Expand Down Expand Up @@ -1438,10 +1436,6 @@ top:
return
}

// forEachP needs worldsema to execute, and we'll need it to
// stop the world later, so acquire worldsema now.
semacquire(&worldsema)

// Flush all local buffers and collect flushedWork flags.
gcMarkDoneFlushed = 0
systemstack(func() {
Expand Down Expand Up @@ -1502,7 +1496,6 @@ top:
// work to do. Keep going. It's possible the
// transition condition became true again during the
// ragged barrier, so re-check it.
semrelease(&worldsema)
goto top
}

Expand Down Expand Up @@ -1579,7 +1572,6 @@ top:
now := startTheWorldWithSema(true)
work.pauseNS += now - work.pauseStart
})
semrelease(&worldsema)
goto top
}
}
Expand Down Expand Up @@ -1797,7 +1789,6 @@ func gcMarkTermination(nextTriggerRatio float64) {
}

semrelease(&worldsema)
semrelease(&gcsema)
// Careful: another GC cycle may start now.

releasem(mp)
Expand Down
44 changes: 4 additions & 40 deletions src/runtime/proc.go
Original file line number Diff line number Diff line change
Expand Up @@ -857,23 +857,8 @@ func casGFromPreempted(gp *g, old, new uint32) bool {
// goroutines.
func stopTheWorld(reason string) {
semacquire(&worldsema)
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)
})
getg().m.preemptoff = reason
systemstack(stopTheWorldWithSema)
}

// startTheWorld undoes the effects of stopTheWorld.
Expand All @@ -885,31 +870,10 @@ func startTheWorld() {
getg().m.preemptoff = ""
}

// 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.
// Holding worldsema grants an M the right to try to stop the world
// and prevents gomaxprocs from changing concurrently.
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
Expand Down
17 changes: 7 additions & 10 deletions src/runtime/trace.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,12 +180,9 @@ func traceBufPtrOf(b *traceBuf) traceBufPtr {
// Most clients should use the runtime/trace package or the testing package's
// -test.trace flag instead of calling StartTrace directly.
func StartTrace() error {
// Stop the world so that we can take a consistent snapshot
// Stop the world, so that we can take a consistent snapshot
// of all goroutines at the beginning of the trace.
// Do not stop the world during GC so we ensure we always see
// a consistent view of GC-related events (e.g. a start is always
// paired with an end).
stopTheWorldGC("start tracing")
stopTheWorld("start tracing")

// We are in stop-the-world, but syscalls can finish and write to trace concurrently.
// Exitsyscall could check trace.enabled long before and then suddenly wake up
Expand All @@ -196,7 +193,7 @@ func StartTrace() error {

if trace.enabled || trace.shutdown {
unlock(&trace.bufLock)
startTheWorldGC()
startTheWorld()
return errorString("tracing is already enabled")
}

Expand Down Expand Up @@ -267,7 +264,7 @@ func StartTrace() error {

unlock(&trace.bufLock)

startTheWorldGC()
startTheWorld()
return nil
}

Expand All @@ -276,14 +273,14 @@ func StartTrace() error {
func StopTrace() {
// Stop the world so that we can collect the trace buffers from all p's below,
// and also to avoid races with traceEvent.
stopTheWorldGC("stop tracing")
stopTheWorld("stop tracing")

// See the comment in StartTrace.
lock(&trace.bufLock)

if !trace.enabled {
unlock(&trace.bufLock)
startTheWorldGC()
startTheWorld()
return
}

Expand Down Expand Up @@ -320,7 +317,7 @@ func StopTrace() {
trace.shutdown = true
unlock(&trace.bufLock)

startTheWorldGC()
startTheWorld()

// The world is started but we've set trace.shutdown, so new tracing can't start.
// Wait for the trace reader to flush pending buffers and stop.
Expand Down
1 change: 0 additions & 1 deletion src/runtime/trace/trace_stack_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,6 @@ func TestTraceSymbolize(t *testing.T) {
}},
{trace.EvGomaxprocs, []frame{
{"runtime.startTheWorld", 0}, // this is when the current gomaxprocs is logged.
{"runtime.startTheWorldGC", 0},
{"runtime.GOMAXPROCS", 0},
{"runtime/trace_test.TestTraceSymbolize", 0},
{"testing.tRunner", 0},
Expand Down

0 comments on commit 64c22b7

Please sign in to comment.