Source file
src/runtime/traceruntime.go
1
2
3
4
5
6
7 package runtime
8
9 import (
10 "internal/runtime/atomic"
11 "internal/trace/tracev2"
12 _ "unsafe"
13 )
14
15
16 type gTraceState struct {
17 traceSchedResourceState
18 }
19
20
21 func (s *gTraceState) reset() {
22 s.seq = [2]uint64{}
23
24 }
25
26
27 type mTraceState struct {
28 writing atomic.Bool
29 buf [2][tracev2.NumExperiments]*traceBuf
30 link *m
31 reentered uint32
32 entryGen uintptr
33 oldthrowsplit bool
34 }
35
36
37 type pTraceState struct {
38 traceSchedResourceState
39
40
41 mSyscallID int64
42
43
44
45
46 maySweep bool
47
48
49 inSweep bool
50
51
52
53 swept, reclaimed uintptr
54 }
55
56
57 func traceLockInit() {
58
59
60 lockInit(&trace.stringTab[0].lock, lockRankTraceStrings)
61 lockInit(&trace.stringTab[0].tab.mem.lock, lockRankTraceStrings)
62 lockInit(&trace.stringTab[1].lock, lockRankTraceStrings)
63 lockInit(&trace.stringTab[1].tab.mem.lock, lockRankTraceStrings)
64 lockInit(&trace.stackTab[0].tab.mem.lock, lockRankTraceStackTab)
65 lockInit(&trace.stackTab[1].tab.mem.lock, lockRankTraceStackTab)
66 lockInit(&trace.typeTab[0].tab.mem.lock, lockRankTraceTypeTab)
67 lockInit(&trace.typeTab[1].tab.mem.lock, lockRankTraceTypeTab)
68 lockInit(&trace.lock, lockRankTrace)
69 }
70
71
72
73
74
75
76
77 func lockRankMayTraceFlush() {
78 lockWithRankMayAcquire(&trace.lock, getLockRank(&trace.lock))
79 }
80
81
82
83
84
85
86
87
88 type traceBlockReason uint8
89
90 const (
91 traceBlockGeneric traceBlockReason = iota
92 traceBlockForever
93 traceBlockNet
94 traceBlockSelect
95 traceBlockCondWait
96 traceBlockSync
97 traceBlockChanSend
98 traceBlockChanRecv
99 traceBlockGCMarkAssist
100 traceBlockGCSweep
101 traceBlockSystemGoroutine
102 traceBlockPreempted
103 traceBlockDebugCall
104 traceBlockUntilGCEnds
105 traceBlockSleep
106 traceBlockGCWeakToStrongWait
107 traceBlockSynctest
108 )
109
110 var traceBlockReasonStrings = [...]string{
111 traceBlockGeneric: "unspecified",
112 traceBlockForever: "forever",
113 traceBlockNet: "network",
114 traceBlockSelect: "select",
115 traceBlockCondWait: "sync.(*Cond).Wait",
116 traceBlockSync: "sync",
117 traceBlockChanSend: "chan send",
118 traceBlockChanRecv: "chan receive",
119 traceBlockGCMarkAssist: "GC mark assist wait for work",
120 traceBlockGCSweep: "GC background sweeper wait",
121 traceBlockSystemGoroutine: "system goroutine wait",
122 traceBlockPreempted: "preempted",
123 traceBlockDebugCall: "wait for debug call",
124 traceBlockUntilGCEnds: "wait until GC ends",
125 traceBlockSleep: "sleep",
126 traceBlockGCWeakToStrongWait: "GC weak to strong wait",
127 traceBlockSynctest: "synctest",
128 }
129
130
131
132
133
134 type traceGoStopReason uint8
135
136 const (
137 traceGoStopGeneric traceGoStopReason = iota
138 traceGoStopGoSched
139 traceGoStopPreempted
140 )
141
142 var traceGoStopReasonStrings = [...]string{
143 traceGoStopGeneric: "unspecified",
144 traceGoStopGoSched: "runtime.Gosched",
145 traceGoStopPreempted: "preempted",
146 }
147
148
149
150
151 func traceEnabled() bool {
152 return trace.enabled
153 }
154
155
156
157
158
159 func traceAllocFreeEnabled() bool {
160 return trace.enabledWithAllocFree
161 }
162
163
164 func traceShuttingDown() bool {
165 return trace.shutdown.Load()
166 }
167
168
169
170
171 type traceLocker struct {
172 mp *m
173 gen uintptr
174 }
175
176
177
178
179
180
181 const debugTraceReentrancy = false
182
183
184
185
186
187
188 func traceAcquire() traceLocker {
189 if !traceEnabled() {
190 return traceLocker{}
191 }
192 return traceAcquireEnabled()
193 }
194
195
196
197
198
199
200
201
202 func traceAcquireEnabled() traceLocker {
203
204
205
206 lockRankMayTraceFlush()
207
208
209 mp := acquirem()
210
211
212
213
214 if mp.trace.writing.Load() {
215 mp.trace.reentered++
216 return traceLocker{mp, mp.trace.entryGen}
217 }
218
219
220
221
222
223
224
225 mp.trace.writing.Store(true)
226
227
228
229
230
231
232
233
234
235 gen := trace.gen.Load()
236 if gen == 0 {
237 mp.trace.writing.Store(false)
238 releasem(mp)
239 return traceLocker{}
240 }
241 mp.trace.entryGen = gen
242 return traceLocker{mp, gen}
243 }
244
245
246
247
248
249
250 func (tl traceLocker) ok() bool {
251 return tl.gen != 0
252 }
253
254
255
256
257
258
259 func traceRelease(tl traceLocker) {
260 if tl.mp.trace.reentered > 0 {
261 tl.mp.trace.reentered--
262 } else {
263 tl.mp.trace.writing.Store(false)
264 }
265 releasem(tl.mp)
266 }
267
268
269
270
271 func traceExitingSyscall() {
272 trace.exitingSyscall.Add(1)
273 }
274
275
276 func traceExitedSyscall() {
277 trace.exitingSyscall.Add(-1)
278 }
279
280
281 func (tl traceLocker) Gomaxprocs(procs int32) {
282 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvProcsChange, traceArg(procs), tl.stack(1))
283 }
284
285
286
287
288 func (tl traceLocker) ProcStart() {
289 pp := tl.mp.p.ptr()
290
291
292
293 tl.eventWriter(tracev2.GoSyscall, tracev2.ProcIdle).event(tracev2.EvProcStart, traceArg(pp.id), pp.trace.nextSeq(tl.gen))
294 }
295
296
297 func (tl traceLocker) ProcStop(pp *p) {
298
299
300 tl.eventWriter(tracev2.GoSyscall, tracev2.ProcRunning).event(tracev2.EvProcStop)
301 }
302
303
304
305
306
307 func (tl traceLocker) GCActive() {
308 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvGCActive, traceArg(trace.seqGC))
309
310
311 trace.seqGC++
312 }
313
314
315
316
317
318 func (tl traceLocker) GCStart() {
319 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvGCBegin, traceArg(trace.seqGC), tl.stack(3))
320
321
322 trace.seqGC++
323 }
324
325
326
327
328
329 func (tl traceLocker) GCDone() {
330 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvGCEnd, traceArg(trace.seqGC))
331
332
333 trace.seqGC++
334 }
335
336
337 func (tl traceLocker) STWStart(reason stwReason) {
338
339
340 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvSTWBegin, tl.string(reason.String()), tl.stack(2))
341 }
342
343
344 func (tl traceLocker) STWDone() {
345
346
347 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvSTWEnd)
348 }
349
350
351
352
353
354
355
356
357 func (tl traceLocker) GCSweepStart() {
358
359
360 pp := tl.mp.p.ptr()
361 if pp.trace.maySweep {
362 throw("double traceGCSweepStart")
363 }
364 pp.trace.maySweep, pp.trace.swept, pp.trace.reclaimed = true, 0, 0
365 }
366
367
368
369
370
371
372
373
374
375 func (tl traceLocker) GCSweepSpan(bytesSwept uintptr) {
376 pp := tl.mp.p.ptr()
377 if pp.trace.maySweep {
378 if pp.trace.swept == 0 {
379 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvGCSweepBegin, tl.stack(1))
380 pp.trace.inSweep = true
381 }
382 pp.trace.swept += bytesSwept
383 }
384 }
385
386
387
388
389
390
391 func (tl traceLocker) GCSweepDone() {
392 pp := tl.mp.p.ptr()
393 if !pp.trace.maySweep {
394 throw("missing traceGCSweepStart")
395 }
396 if pp.trace.inSweep {
397 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvGCSweepEnd, traceArg(pp.trace.swept), traceArg(pp.trace.reclaimed))
398 pp.trace.inSweep = false
399 }
400 pp.trace.maySweep = false
401 }
402
403
404 func (tl traceLocker) GCMarkAssistStart() {
405 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvGCMarkAssistBegin, tl.stack(1))
406 }
407
408
409 func (tl traceLocker) GCMarkAssistDone() {
410 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvGCMarkAssistEnd)
411 }
412
413
414 func (tl traceLocker) GoCreate(newg *g, pc uintptr, blocked bool) {
415 newg.trace.setStatusTraced(tl.gen)
416 ev := tracev2.EvGoCreate
417 if blocked {
418 ev = tracev2.EvGoCreateBlocked
419 }
420 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(ev, traceArg(newg.goid), tl.startPC(pc), tl.stack(2))
421 }
422
423
424
425
426 func (tl traceLocker) GoStart() {
427 gp := getg().m.curg
428 pp := gp.m.p
429 w := tl.eventWriter(tracev2.GoRunnable, tracev2.ProcRunning)
430 w.event(tracev2.EvGoStart, traceArg(gp.goid), gp.trace.nextSeq(tl.gen))
431 if pp.ptr().gcMarkWorkerMode != gcMarkWorkerNotWorker {
432 w.event(tracev2.EvGoLabel, trace.markWorkerLabels[tl.gen%2][pp.ptr().gcMarkWorkerMode])
433 }
434 }
435
436
437
438
439 func (tl traceLocker) GoEnd() {
440 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvGoDestroy)
441 }
442
443
444 func (tl traceLocker) GoSched() {
445 tl.GoStop(traceGoStopGoSched)
446 }
447
448
449 func (tl traceLocker) GoPreempt() {
450 tl.GoStop(traceGoStopPreempted)
451 }
452
453
454 func (tl traceLocker) GoStop(reason traceGoStopReason) {
455 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvGoStop, trace.goStopReasons[tl.gen%2][reason], tl.stack(0))
456 }
457
458
459
460
461
462 func (tl traceLocker) GoPark(reason traceBlockReason, skip int) {
463 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvGoBlock, trace.goBlockReasons[tl.gen%2][reason], tl.stack(skip))
464 }
465
466
467 func (tl traceLocker) GoUnpark(gp *g, skip int) {
468
469 tl.emitUnblockStatus(gp, tl.gen)
470 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvGoUnblock, traceArg(gp.goid), gp.trace.nextSeq(tl.gen), tl.stack(skip))
471 }
472
473
474
475 func (tl traceLocker) GoSwitch(nextg *g, destroy bool) {
476
477 tl.emitUnblockStatus(nextg, tl.gen)
478 w := tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning)
479 ev := tracev2.EvGoSwitch
480 if destroy {
481 ev = tracev2.EvGoSwitchDestroy
482 }
483 w.event(ev, traceArg(nextg.goid), nextg.trace.nextSeq(tl.gen))
484 }
485
486
487
488 func (tl traceLocker) emitUnblockStatus(gp *g, gen uintptr) {
489 if !gp.trace.statusWasTraced(gen) && gp.trace.acquireStatus(gen) {
490
491
492
493 tl.writer().writeGoStatus(gp.goid, -1, tracev2.GoWaiting, gp.inMarkAssist, 0).end()
494 }
495 }
496
497
498
499
500 func (tl traceLocker) GoSysCall() {
501
502 pp := tl.mp.p.ptr()
503 pp.trace.mSyscallID = int64(tl.mp.procid)
504 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvGoSyscallBegin, pp.trace.nextSeq(tl.gen), tl.stack(1))
505 }
506
507
508
509
510
511
512
513
514
515
516 func (tl traceLocker) GoSysExit(lostP bool) {
517 ev := tracev2.EvGoSyscallEnd
518 procStatus := tracev2.ProcSyscall
519 if lostP {
520 ev = tracev2.EvGoSyscallEndBlocked
521 procStatus = tracev2.ProcRunning
522 } else {
523 tl.mp.p.ptr().trace.mSyscallID = -1
524 }
525 tl.eventWriter(tracev2.GoSyscall, procStatus).event(ev)
526 }
527
528
529
530
531 func (tl traceLocker) ProcSteal(pp *p) {
532
533 mStolenFrom := pp.trace.mSyscallID
534 pp.trace.mSyscallID = -1
535
536
537
538
539
540
541 if !pp.trace.statusWasTraced(tl.gen) && pp.trace.acquireStatus(tl.gen) {
542
543
544 tl.writer().writeProcStatus(uint64(pp.id), tracev2.ProcSyscallAbandoned, pp.trace.inSweep).end()
545 }
546
547
548
549
550
551
552
553 goStatus := tracev2.GoRunning
554 procStatus := tracev2.ProcRunning
555 if tl.mp.curg != nil && tl.mp.curg.syscallsp != 0 {
556 goStatus = tracev2.GoSyscall
557 procStatus = tracev2.ProcSyscallAbandoned
558 }
559 tl.eventWriter(goStatus, procStatus).event(tracev2.EvProcSteal, traceArg(pp.id), pp.trace.nextSeq(tl.gen), traceArg(mStolenFrom))
560 }
561
562
563 func (tl traceLocker) HeapAlloc(live uint64) {
564 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvHeapAlloc, traceArg(live))
565 }
566
567
568 func (tl traceLocker) HeapGoal() {
569 heapGoal := gcController.heapGoal()
570
571
572 if heapGoal == ^uint64(0) || gcController.gcPercent.Load() < 0 {
573
574 heapGoal = 0
575 }
576 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvHeapGoal, traceArg(heapGoal))
577 }
578
579
580
581
582
583
584
585 func (tl traceLocker) GoCreateSyscall(gp *g) {
586
587
588 gp.trace.setStatusTraced(tl.gen)
589
590
591
592
593 tl.rawEventWriter().event(tracev2.EvGoCreateSyscall, traceArg(gp.goid))
594 }
595
596
597
598
599
600 func (tl traceLocker) GoDestroySyscall() {
601
602 if gp := tl.mp.curg; gp != nil && !gp.trace.statusWasTraced(tl.gen) && gp.trace.acquireStatus(tl.gen) {
603 tl.writer().writeGoStatus(gp.goid, int64(tl.mp.procid), tracev2.GoSyscall, false, 0 ).end()
604 }
605
606
607
608
609 tl.rawEventWriter().event(tracev2.EvGoDestroySyscall)
610 }
611
612
613
614
615
616
617
618 func trace_userTaskCreate(id, parentID uint64, taskType string) {
619 tl := traceAcquire()
620 if !tl.ok() {
621
622 return
623 }
624 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvUserTaskBegin, traceArg(id), traceArg(parentID), tl.string(taskType), tl.stack(3))
625 traceRelease(tl)
626 }
627
628
629
630
631 func trace_userTaskEnd(id uint64) {
632 tl := traceAcquire()
633 if !tl.ok() {
634
635 return
636 }
637 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvUserTaskEnd, traceArg(id), tl.stack(2))
638 traceRelease(tl)
639 }
640
641
642
643
644
645
646
647 func trace_userRegion(id, mode uint64, name string) {
648 tl := traceAcquire()
649 if !tl.ok() {
650
651 return
652 }
653 var ev tracev2.EventType
654 switch mode {
655 case 0:
656 ev = tracev2.EvUserRegionBegin
657 case 1:
658 ev = tracev2.EvUserRegionEnd
659 default:
660 return
661 }
662 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(ev, traceArg(id), tl.string(name), tl.stack(3))
663 traceRelease(tl)
664 }
665
666
667
668
669 func trace_userLog(id uint64, category, message string) {
670 tl := traceAcquire()
671 if !tl.ok() {
672
673 return
674 }
675 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvUserLog, traceArg(id), tl.string(category), tl.uniqueString(message), tl.stack(3))
676 traceRelease(tl)
677 }
678
679
680
681
682
683
684
685 func traceThreadDestroy(mp *m) {
686 assertLockHeld(&sched.lock)
687
688
689
690
691
692
693
694
695 if debugTraceReentrancy && mp.trace.writing.Load() {
696 throw("bad use of trace.writing")
697 }
698 mp.trace.writing.Store(true)
699 systemstack(func() {
700 lock(&trace.lock)
701 for i := range mp.trace.buf {
702 for exp, buf := range mp.trace.buf[i] {
703 if buf != nil {
704
705
706 traceBufFlush(buf, uintptr(i))
707 mp.trace.buf[i][exp] = nil
708 }
709 }
710 }
711 unlock(&trace.lock)
712 })
713 mp.trace.writing.Store(false)
714 }
715
View as plain text