aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/debugcall.go
diff options
context:
space:
mode:
authorMichael Anthony Knyszek <mknyszek@google.com>2023-07-27 19:04:04 +0000
committerGopher Robot <gobot@golang.org>2023-11-09 22:34:25 +0000
commitf119abb65dbe42f6cb40db698b54be3668357934 (patch)
tree1cb07931c9e0f488724462616283a3d7ca3cc723 /src/runtime/debugcall.go
parente3585c67576bc1b0b161448b617eb2725e9c9d69 (diff)
downloadgo-f119abb65dbe42f6cb40db698b54be3668357934.tar.xz
runtime: refactor runtime->tracer API to appear more like a lock
Currently the execution tracer synchronizes with itself using very heavyweight operations. As a result, it's totally fine for most of the tracer code to look like: if traceEnabled() { traceXXX(...) } However, if we want to make that synchronization more lightweight (as issue #60773 proposes), then this is insufficient. In particular, we need to make sure the tracer can't observe an inconsistency between g atomicstatus and the event that would be emitted for a particular g transition. This means making the g status change appear to happen atomically with the corresponding trace event being written out from the perspective of the tracer. This requires a change in API to something more like a lock. While we're here, we might as well make sure that trace events can *only* be emitted while this lock is held. This change introduces such an API: traceAcquire, which returns a value that can emit events, and traceRelease, which requires the value that was returned by traceAcquire. In practice, this won't be a real lock, it'll be more like a seqlock. For the current tracer, this API is completely overkill and the value returned by traceAcquire basically just checks trace.enabled. But it's necessary for the tracer described in #60773 and we can implement that more cleanly if we do this refactoring now instead of later. For #60773. Change-Id: Ibb9ff5958376339fafc2b5180aef65cf2ba18646 Reviewed-on: https://go-review.googlesource.com/c/go/+/515635 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: Michael Knyszek <mknyszek@google.com> Reviewed-by: Michael Pratt <mpratt@google.com>
Diffstat (limited to 'src/runtime/debugcall.go')
-rw-r--r--src/runtime/debugcall.go24
1 files changed, 15 insertions, 9 deletions
diff --git a/src/runtime/debugcall.go b/src/runtime/debugcall.go
index 98ab413ff4..5dd83063ff 100644
--- a/src/runtime/debugcall.go
+++ b/src/runtime/debugcall.go
@@ -166,10 +166,12 @@ func debugCallWrap(dispatch uintptr) {
gp.schedlink = 0
// Park the calling goroutine.
- if traceEnabled() {
- traceGoPark(traceBlockDebugCall, 1)
- }
+ trace := traceAcquire()
casGToWaiting(gp, _Grunning, waitReasonDebugCall)
+ if trace.ok() {
+ trace.GoPark(traceBlockDebugCall, 1)
+ traceRelease(trace)
+ }
dropg()
// Directly execute the new goroutine. The debug
@@ -225,19 +227,23 @@ func debugCallWrap1() {
// Switch back to the calling goroutine. At some point
// the scheduler will schedule us again and we'll
// finish exiting.
- if traceEnabled() {
- traceGoSched()
- }
+ trace := traceAcquire()
casgstatus(gp, _Grunning, _Grunnable)
+ if trace.ok() {
+ trace.GoSched()
+ traceRelease(trace)
+ }
dropg()
lock(&sched.lock)
globrunqput(gp)
unlock(&sched.lock)
- if traceEnabled() {
- traceGoUnpark(callingG, 0)
- }
+ trace = traceAcquire()
casgstatus(callingG, _Gwaiting, _Grunnable)
+ if trace.ok() {
+ trace.GoUnpark(callingG, 0)
+ traceRelease(trace)
+ }
execute(callingG, true)
})
}