Skip to content

Commit c213c90

Browse files
mknyszekgopherbot
authored andcommitted
runtime: capture per-g trace state in a type
More tightening up of the tracer's interface. This increases the size of each G very slightly, which isn't great, but we stay within the same size class, so actually memory use will be unchanged. Change-Id: I7d1f5798edcf437c212beb1e1a2619eab833aafb Reviewed-on: https://go-review.googlesource.com/c/go/+/494188 TryBot-Result: Gopher Robot <gobot@golang.org> Auto-Submit: Michael Knyszek <mknyszek@google.com> Reviewed-by: Michael Pratt <mpratt@google.com> Run-TryBot: Michael Knyszek <mknyszek@google.com>
1 parent 1bb2f73 commit c213c90

File tree

4 files changed

+65
-58
lines changed

4 files changed

+65
-58
lines changed

src/runtime/proc.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1999,7 +1999,7 @@ func oneNewExtraM() {
19991999
mp.lockedg.set(gp)
20002000
gp.lockedm.set(mp)
20012001
gp.goid = sched.goidgen.Add(1)
2002-
gp.sysblocktraced = true
2002+
gp.trace.sysBlockTraced = true
20032003
if raceenabled {
20042004
gp.racectx = racegostart(abi.FuncPCABIInternal(newextram) + sys.PCQuantum)
20052005
}
@@ -2705,8 +2705,8 @@ func execute(gp *g, inheritTime bool) {
27052705
if traceEnabled() {
27062706
// GoSysExit has to happen when we have a P, but before GoStart.
27072707
// So we emit it here.
2708-
if gp.syscallsp != 0 && gp.sysblocktraced {
2709-
traceGoSysExit(gp.sysexitticks)
2708+
if gp.syscallsp != 0 && gp.trace.sysBlockTraced {
2709+
traceGoSysExit(gp.trace.sysExitTicks)
27102710
}
27112711
traceGoStart()
27122712
}
@@ -3856,7 +3856,7 @@ func reentersyscall(pc, sp uintptr) {
38563856
}
38573857

38583858
gp.m.syscalltick = gp.m.p.ptr().syscalltick
3859-
gp.sysblocktraced = true
3859+
gp.trace.sysBlockTraced = true
38603860
pp := gp.m.p.ptr()
38613861
pp.m = 0
38623862
gp.m.oldp.set(pp)
@@ -3917,7 +3917,7 @@ func entersyscallblock() {
39173917
gp.throwsplit = true
39183918
gp.stackguard0 = stackPreempt // see comment in entersyscall
39193919
gp.m.syscalltick = gp.m.p.ptr().syscalltick
3920-
gp.sysblocktraced = true
3920+
gp.trace.sysBlockTraced = true
39213921
gp.m.p.ptr().syscalltick++
39223922

39233923
// Leave SP around for GC and traceback.
@@ -4024,7 +4024,7 @@ func exitsyscall() {
40244024
return
40254025
}
40264026

4027-
gp.sysexitticks = 0
4027+
gp.trace.sysExitTicks = 0
40284028
if traceEnabled() {
40294029
// Wait till traceGoSysBlock event is emitted.
40304030
// This ensures consistency of the trace (the goroutine is started after it is blocked).
@@ -4035,7 +4035,7 @@ func exitsyscall() {
40354035
// Tracing code can invoke write barriers that cannot run without a P.
40364036
// So instead we remember the syscall exit time and emit the event
40374037
// in execute when we have a P.
4038-
gp.sysexitticks = cputicks()
4038+
gp.trace.sysExitTicks = cputicks()
40394039
}
40404040

40414041
gp.m.locks--

src/runtime/runtime2.go

Lines changed: 24 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -471,36 +471,35 @@ type g struct {
471471
// for stack shrinking.
472472
parkingOnChan atomic.Bool
473473

474-
raceignore int8 // ignore race detection events
475-
sysblocktraced bool // StartTrace has emitted EvGoInSyscall about this goroutine
476-
tracking bool // whether we're tracking this G for sched latency statistics
477-
trackingSeq uint8 // used to decide whether to track this G
478-
trackingStamp int64 // timestamp of when the G last started being tracked
479-
runnableTime int64 // the amount of time spent runnable, cleared when running, only used when tracking
480-
sysexitticks int64 // cputicks when syscall has returned (for tracing)
481-
traceseq uint64 // trace event sequencer
482-
tracelastp puintptr // last P emitted an event for this goroutine
483-
lockedm muintptr
484-
sig uint32
485-
writebuf []byte
486-
sigcode0 uintptr
487-
sigcode1 uintptr
488-
sigpc uintptr
489-
parentGoid uint64 // goid of goroutine that created this goroutine
490-
gopc uintptr // pc of go statement that created this goroutine
491-
ancestors *[]ancestorInfo // ancestor information goroutine(s) that created this goroutine (only used if debug.tracebackancestors)
492-
startpc uintptr // pc of goroutine function
493-
racectx uintptr
494-
waiting *sudog // sudog structures this g is waiting on (that have a valid elem ptr); in lock order
495-
cgoCtxt []uintptr // cgo traceback context
496-
labels unsafe.Pointer // profiler labels
497-
timer *timer // cached timer for time.Sleep
498-
selectDone atomic.Uint32 // are we participating in a select and did someone win the race?
474+
raceignore int8 // ignore race detection events
475+
tracking bool // whether we're tracking this G for sched latency statistics
476+
trackingSeq uint8 // used to decide whether to track this G
477+
trackingStamp int64 // timestamp of when the G last started being tracked
478+
runnableTime int64 // the amount of time spent runnable, cleared when running, only used when tracking
479+
lockedm muintptr
480+
sig uint32
481+
writebuf []byte
482+
sigcode0 uintptr
483+
sigcode1 uintptr
484+
sigpc uintptr
485+
parentGoid uint64 // goid of goroutine that created this goroutine
486+
gopc uintptr // pc of go statement that created this goroutine
487+
ancestors *[]ancestorInfo // ancestor information goroutine(s) that created this goroutine (only used if debug.tracebackancestors)
488+
startpc uintptr // pc of goroutine function
489+
racectx uintptr
490+
waiting *sudog // sudog structures this g is waiting on (that have a valid elem ptr); in lock order
491+
cgoCtxt []uintptr // cgo traceback context
492+
labels unsafe.Pointer // profiler labels
493+
timer *timer // cached timer for time.Sleep
494+
selectDone atomic.Uint32 // are we participating in a select and did someone win the race?
499495

500496
// goroutineProfiled indicates the status of this goroutine's stack for the
501497
// current in-progress goroutine profile
502498
goroutineProfiled goroutineProfileStateHolder
503499

500+
// Per-G tracer state.
501+
trace gTraceState
502+
504503
// Per-G GC state
505504

506505
// gcAssistBytes is this G's GC assist credit in terms of

src/runtime/sizeof_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ func TestSizeof(t *testing.T) {
2121
_32bit uintptr // size on 32bit platforms
2222
_64bit uintptr // size on 64bit platforms
2323
}{
24-
{runtime.G{}, 248, 400}, // g, but exported for testing
24+
{runtime.G{}, 252, 408}, // g, but exported for testing
2525
{runtime.Sudog{}, 56, 88}, // sudog, but exported for testing
2626
}
2727

src/runtime/trace.go

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,14 @@ var trace struct {
161161
buf traceBufPtr // global trace buffer, used when running without a p
162162
}
163163

164+
// gTraceState is per-G state for the tracer.
165+
type gTraceState struct {
166+
sysExitTicks int64 // cputicks when syscall has returned
167+
sysBlockTraced bool // StartTrace has emitted EvGoInSyscall about this goroutine
168+
seq uint64 // trace event sequencer
169+
lastP puintptr // last P emitted an event for this goroutine
170+
}
171+
164172
// traceLockInit initializes global trace locks.
165173
func traceLockInit() {
166174
lockInit(&trace.bufLock, lockRankTraceBuf)
@@ -269,33 +277,33 @@ func StartTrace() error {
269277
forEachGRace(func(gp *g) {
270278
status := readgstatus(gp)
271279
if status != _Gdead {
272-
gp.traceseq = 0
273-
gp.tracelastp = getg().m.p
280+
gp.trace.seq = 0
281+
gp.trace.lastP = getg().m.p
274282
// +PCQuantum because traceFrameForPC expects return PCs and subtracts PCQuantum.
275283
id := trace.stackTab.put([]uintptr{logicalStackSentinel, startPCforTrace(gp.startpc) + sys.PCQuantum})
276284
traceEvent(traceEvGoCreate, -1, gp.goid, uint64(id), stackID)
277285
}
278286
if status == _Gwaiting {
279287
// traceEvGoWaiting is implied to have seq=1.
280-
gp.traceseq++
288+
gp.trace.seq++
281289
traceEvent(traceEvGoWaiting, -1, gp.goid)
282290
}
283291
if status == _Gsyscall {
284-
gp.traceseq++
292+
gp.trace.seq++
285293
traceEvent(traceEvGoInSyscall, -1, gp.goid)
286294
} else if status == _Gdead && gp.m != nil && gp.m.isextra {
287295
// Trigger two trace events for the dead g in the extra m,
288296
// since the next event of the g will be traceEvGoSysExit in exitsyscall,
289297
// while calling from C thread to Go.
290-
gp.traceseq = 0
291-
gp.tracelastp = getg().m.p
298+
gp.trace.seq = 0
299+
gp.trace.lastP = getg().m.p
292300
// +PCQuantum because traceFrameForPC expects return PCs and subtracts PCQuantum.
293301
id := trace.stackTab.put([]uintptr{logicalStackSentinel, startPCforTrace(0) + sys.PCQuantum}) // no start pc
294302
traceEvent(traceEvGoCreate, -1, gp.goid, uint64(id), stackID)
295-
gp.traceseq++
303+
gp.trace.seq++
296304
traceEvent(traceEvGoInSyscall, -1, gp.goid)
297305
} else {
298-
gp.sysblocktraced = false
306+
gp.trace.sysBlockTraced = false
299307
}
300308
})
301309
traceProcStart()
@@ -1507,8 +1515,8 @@ func traceGCMarkAssistDone() {
15071515
}
15081516

15091517
func traceGoCreate(newg *g, pc uintptr) {
1510-
newg.traceseq = 0
1511-
newg.tracelastp = getg().m.p
1518+
newg.trace.seq = 0
1519+
newg.trace.lastP = getg().m.p
15121520
// +PCQuantum because traceFrameForPC expects return PCs and subtracts PCQuantum.
15131521
id := trace.stackTab.put([]uintptr{logicalStackSentinel, startPCforTrace(pc) + sys.PCQuantum})
15141522
traceEvent(traceEvGoCreate, 2, newg.goid, uint64(id))
@@ -1517,14 +1525,14 @@ func traceGoCreate(newg *g, pc uintptr) {
15171525
func traceGoStart() {
15181526
gp := getg().m.curg
15191527
pp := gp.m.p
1520-
gp.traceseq++
1528+
gp.trace.seq++
15211529
if pp.ptr().gcMarkWorkerMode != gcMarkWorkerNotWorker {
1522-
traceEvent(traceEvGoStartLabel, -1, gp.goid, gp.traceseq, trace.markWorkerLabels[pp.ptr().gcMarkWorkerMode])
1523-
} else if gp.tracelastp == pp {
1530+
traceEvent(traceEvGoStartLabel, -1, gp.goid, gp.trace.seq, trace.markWorkerLabels[pp.ptr().gcMarkWorkerMode])
1531+
} else if gp.trace.lastP == pp {
15241532
traceEvent(traceEvGoStartLocal, -1, gp.goid)
15251533
} else {
1526-
gp.tracelastp = pp
1527-
traceEvent(traceEvGoStart, -1, gp.goid, gp.traceseq)
1534+
gp.trace.lastP = pp
1535+
traceEvent(traceEvGoStart, -1, gp.goid, gp.trace.seq)
15281536
}
15291537
}
15301538

@@ -1534,13 +1542,13 @@ func traceGoEnd() {
15341542

15351543
func traceGoSched() {
15361544
gp := getg()
1537-
gp.tracelastp = gp.m.p
1545+
gp.trace.lastP = gp.m.p
15381546
traceEvent(traceEvGoSched, 1)
15391547
}
15401548

15411549
func traceGoPreempt() {
15421550
gp := getg()
1543-
gp.tracelastp = gp.m.p
1551+
gp.trace.lastP = gp.m.p
15441552
traceEvent(traceEvGoPreempt, 1)
15451553
}
15461554

@@ -1550,12 +1558,12 @@ func traceGoPark(traceEv byte, skip int) {
15501558

15511559
func traceGoUnpark(gp *g, skip int) {
15521560
pp := getg().m.p
1553-
gp.traceseq++
1554-
if gp.tracelastp == pp {
1561+
gp.trace.seq++
1562+
if gp.trace.lastP == pp {
15551563
traceEvent(traceEvGoUnblockLocal, skip, gp.goid)
15561564
} else {
1557-
gp.tracelastp = pp
1558-
traceEvent(traceEvGoUnblock, skip, gp.goid, gp.traceseq)
1565+
gp.trace.lastP = pp
1566+
traceEvent(traceEvGoUnblock, skip, gp.goid, gp.trace.seq)
15591567
}
15601568
}
15611569

@@ -1593,9 +1601,9 @@ func traceGoSysExit(ts int64) {
15931601
ts = 0
15941602
}
15951603
gp := getg().m.curg
1596-
gp.traceseq++
1597-
gp.tracelastp = gp.m.p
1598-
traceEvent(traceEvGoSysExit, -1, gp.goid, gp.traceseq, uint64(ts)/traceTickDiv)
1604+
gp.trace.seq++
1605+
gp.trace.lastP = gp.m.p
1606+
traceEvent(traceEvGoSysExit, -1, gp.goid, gp.trace.seq, uint64(ts)/traceTickDiv)
15991607
}
16001608

16011609
func traceGoSysBlock(pp *p) {
@@ -1723,6 +1731,6 @@ func traceOneNewExtraM(gp *g) {
17231731
// since the next event of the g will be traceEvGoSysExit in exitsyscall,
17241732
// while calling from C thread to Go.
17251733
traceGoCreate(gp, 0) // no start pc
1726-
gp.traceseq++
1734+
gp.trace.seq++
17271735
traceEvent(traceEvGoInSyscall, -1, gp.goid)
17281736
}

0 commit comments

Comments
 (0)