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