aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/trace.go
diff options
context:
space:
mode:
authorMichael Anthony Knyszek <mknyszek@google.com>2019-06-17 19:03:09 +0000
committerMichael Knyszek <mknyszek@google.com>2019-09-04 15:53:59 +0000
commit7b294cdd8df0a9523010f6ffc80c59e64578f34b (patch)
treede99a04805ee03f4db41c3e011e085779bcaaf15 /src/runtime/trace.go
parent033299fab66b08d434be30e05d11f7db63efa71c (diff)
downloadgo-7b294cdd8df0a9523010f6ffc80c59e64578f34b.tar.gz
go-7b294cdd8df0a9523010f6ffc80c59e64578f34b.zip
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>
Diffstat (limited to 'src/runtime/trace.go')
-rw-r--r--src/runtime/trace.go17
1 files changed, 10 insertions, 7 deletions
diff --git a/src/runtime/trace.go b/src/runtime/trace.go
index 08e92d2efe..d074783550 100644
--- a/src/runtime/trace.go
+++ b/src/runtime/trace.go
@@ -180,9 +180,12 @@ 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.
- stopTheWorld("start tracing")
+ // 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")
// 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
@@ -193,7 +196,7 @@ func StartTrace() error {
if trace.enabled || trace.shutdown {
unlock(&trace.bufLock)
- startTheWorld()
+ startTheWorldGC()
return errorString("tracing is already enabled")
}
@@ -264,7 +267,7 @@ func StartTrace() error {
unlock(&trace.bufLock)
- startTheWorld()
+ startTheWorldGC()
return nil
}
@@ -273,14 +276,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.
- stopTheWorld("stop tracing")
+ stopTheWorldGC("stop tracing")
// See the comment in StartTrace.
lock(&trace.bufLock)
if !trace.enabled {
unlock(&trace.bufLock)
- startTheWorld()
+ startTheWorldGC()
return
}
@@ -317,7 +320,7 @@ func StopTrace() {
trace.shutdown = true
unlock(&trace.bufLock)
- startTheWorld()
+ startTheWorldGC()
// 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.