Source file
src/cmd/trace/goroutinegen.go
1
2
3
4
5 package main
6
7 import (
8 "internal/trace"
9 )
10
11 var _ generator = &goroutineGenerator{}
12
13 type goroutineGenerator struct {
14 globalRangeGenerator
15 globalMetricGenerator
16 stackSampleGenerator[trace.GoID]
17 logEventGenerator[trace.GoID]
18
19 gStates map[trace.GoID]*gState[trace.GoID]
20 focus trace.GoID
21 filter map[trace.GoID]struct{}
22 }
23
24 func newGoroutineGenerator(ctx *traceContext, focus trace.GoID, filter map[trace.GoID]struct{}) *goroutineGenerator {
25 gg := new(goroutineGenerator)
26 rg := func(ev *trace.Event) trace.GoID {
27 return ev.Goroutine()
28 }
29 gg.stackSampleGenerator.getResource = rg
30 gg.logEventGenerator.getResource = rg
31 gg.gStates = make(map[trace.GoID]*gState[trace.GoID])
32 gg.focus = focus
33 gg.filter = filter
34
35
36 if filter != nil {
37 ctx.SetResourceFilter(func(resource uint64) bool {
38 _, ok := filter[trace.GoID(resource)]
39 return ok
40 })
41 }
42 return gg
43 }
44
45 func (g *goroutineGenerator) Sync() {
46 g.globalRangeGenerator.Sync()
47 }
48
49 func (g *goroutineGenerator) GoroutineLabel(ctx *traceContext, ev *trace.Event) {
50 l := ev.Label()
51 g.gStates[l.Resource.Goroutine()].setLabel(l.Label)
52 }
53
54 func (g *goroutineGenerator) GoroutineRange(ctx *traceContext, ev *trace.Event) {
55 r := ev.Range()
56 switch ev.Kind() {
57 case trace.EventRangeBegin:
58 g.gStates[r.Scope.Goroutine()].rangeBegin(ev.Time(), r.Name, ev.Stack())
59 case trace.EventRangeActive:
60 g.gStates[r.Scope.Goroutine()].rangeActive(r.Name)
61 case trace.EventRangeEnd:
62 gs := g.gStates[r.Scope.Goroutine()]
63 gs.rangeEnd(ev.Time(), r.Name, ev.Stack(), ctx)
64 }
65 }
66
67 func (g *goroutineGenerator) GoroutineTransition(ctx *traceContext, ev *trace.Event) {
68 st := ev.StateTransition()
69 goID := st.Resource.Goroutine()
70
71
72
73 gs, ok := g.gStates[goID]
74 if !ok {
75 gs = newGState[trace.GoID](goID)
76 g.gStates[goID] = gs
77 }
78
79
80 gs.augmentName(st.Stack)
81
82
83 from, to := st.Goroutine()
84 if from == to {
85
86 return
87 }
88 if from.Executing() && !to.Executing() {
89 if to == trace.GoWaiting {
90
91 gs.block(ev.Time(), ev.Stack(), st.Reason, ctx)
92 } else {
93 gs.stop(ev.Time(), ev.Stack(), ctx)
94 }
95 }
96 if !from.Executing() && to.Executing() {
97 start := ev.Time()
98 if from == trace.GoUndetermined {
99
100 start = ctx.startTime
101 }
102 gs.start(start, goID, ctx)
103 }
104
105 if from == trace.GoWaiting {
106
107 gs.unblock(ev.Time(), ev.Stack(), ev.Goroutine(), ctx)
108 }
109 if from == trace.GoNotExist && to == trace.GoRunnable {
110
111 gs.created(ev.Time(), ev.Goroutine(), ev.Stack())
112 }
113 if from == trace.GoSyscall && to != trace.GoRunning {
114
115 gs.syscallEnd(ev.Time(), true, ctx)
116 gs.blockedSyscallEnd(ev.Time(), ev.Stack(), ctx)
117 } else if from == trace.GoSyscall {
118
119 gs.syscallEnd(ev.Time(), false, ctx)
120 }
121
122
123 if to == trace.GoSyscall {
124 start := ev.Time()
125 if from == trace.GoUndetermined {
126
127 start = ctx.startTime
128 }
129
130
131
132 gs.syscallBegin(start, goID, ev.Stack())
133 }
134
135
136 _, inMarkAssist := gs.activeRanges["GC mark assist"]
137 ctx.GoroutineTransition(ctx.elapsed(ev.Time()), viewerGState(from, inMarkAssist), viewerGState(to, inMarkAssist))
138 }
139
140 func (g *goroutineGenerator) ProcRange(ctx *traceContext, ev *trace.Event) {
141
142
143 }
144
145 func (g *goroutineGenerator) ProcTransition(ctx *traceContext, ev *trace.Event) {
146
147 }
148
149 func (g *goroutineGenerator) Finish(ctx *traceContext) {
150 ctx.SetResourceType("G")
151
152
153 g.globalRangeGenerator.Finish(ctx)
154
155
156 for id, gs := range g.gStates {
157 gs.finish(ctx)
158
159
160 ctx.Resource(uint64(id), gs.name())
161 }
162
163
164 if g.focus != trace.NoGoroutine {
165 ctx.Focus(uint64(g.focus))
166 }
167 }
168
View as plain text