mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
runtime: fix generation skew with trace reentrancy
Currently when performing multiple nested traceAcquires, we re-read trace.gen on subsequent reads. But this is invalid, since a generation transition may happen in between a traceAcquire and a nested traceAcquire. The first one will produce a traceLocker with a gen from the previous generation, and the second will produce a traceLocker from the next generation. (Note: generations cannot _complete_ advancement under traceAcquire, but trace.gen can move forward.) The end result is earlier events, from the nested traceAcquire, will write to a future generation, and then previous events will write to a past generation. This can break the trace. (There are also a lot of comments left over talking about the non-reentrancy of the tracer; we should look at those again.) Change-Id: I08ac8cc86d41ab3e6061c5de58d657b6ad0d19d8 Reviewed-on: https://go-review.googlesource.com/c/go/+/708397 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Michael Pratt <mpratt@google.com>
This commit is contained in:
parent
df33c17091
commit
dc9a3e2a65
1 changed files with 3 additions and 1 deletions
|
|
@ -29,6 +29,7 @@ type mTraceState struct {
|
||||||
buf [2][tracev2.NumExperiments]*traceBuf // Per-M traceBuf for writing. Indexed by trace.gen%2.
|
buf [2][tracev2.NumExperiments]*traceBuf // Per-M traceBuf for writing. Indexed by trace.gen%2.
|
||||||
link *m // Snapshot of alllink or freelink.
|
link *m // Snapshot of alllink or freelink.
|
||||||
reentered uint32 // Whether we've reentered tracing from within tracing.
|
reentered uint32 // Whether we've reentered tracing from within tracing.
|
||||||
|
entryGen uintptr // The generation value on first entry.
|
||||||
oldthrowsplit bool // gp.throwsplit upon calling traceLocker.writer. For debugging.
|
oldthrowsplit bool // gp.throwsplit upon calling traceLocker.writer. For debugging.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -212,7 +213,7 @@ func traceAcquireEnabled() traceLocker {
|
||||||
// that it is.
|
// that it is.
|
||||||
if mp.trace.seqlock.Load()%2 == 1 {
|
if mp.trace.seqlock.Load()%2 == 1 {
|
||||||
mp.trace.reentered++
|
mp.trace.reentered++
|
||||||
return traceLocker{mp, trace.gen.Load()}
|
return traceLocker{mp, mp.trace.entryGen}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Acquire the trace seqlock. This prevents traceAdvance from moving forward
|
// Acquire the trace seqlock. This prevents traceAdvance from moving forward
|
||||||
|
|
@ -240,6 +241,7 @@ func traceAcquireEnabled() traceLocker {
|
||||||
releasem(mp)
|
releasem(mp)
|
||||||
return traceLocker{}
|
return traceLocker{}
|
||||||
}
|
}
|
||||||
|
mp.trace.entryGen = gen
|
||||||
return traceLocker{mp, gen}
|
return traceLocker{mp, gen}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue