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(1))
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 if heapGoal == ^uint64(0) {
578
579 heapGoal = 0
580 }
581 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvHeapGoal, traceArg(heapGoal))
582 }
583
584
585
586
587
588
589
590 func (tl traceLocker) GoCreateSyscall(gp *g) {
591
592
593 gp.trace.setStatusTraced(tl.gen)
594 tl.eventWriter(tracev2.GoBad, tracev2.ProcBad).event(tracev2.EvGoCreateSyscall, traceArg(gp.goid))
595 }
596
597
598
599
600
601
602
603 func (tl traceLocker) GoDestroySyscall() {
604
605
606 tl.eventWriter(tracev2.GoSyscall, tracev2.ProcBad).event(tracev2.EvGoDestroySyscall)
607 }
608
609
610
611
612
613
614
615 func trace_userTaskCreate(id, parentID uint64, taskType string) {
616 tl := traceAcquire()
617 if !tl.ok() {
618
619 return
620 }
621 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvUserTaskBegin, traceArg(id), traceArg(parentID), tl.string(taskType), tl.stack(3))
622 traceRelease(tl)
623 }
624
625
626
627
628 func trace_userTaskEnd(id uint64) {
629 tl := traceAcquire()
630 if !tl.ok() {
631
632 return
633 }
634 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvUserTaskEnd, traceArg(id), tl.stack(2))
635 traceRelease(tl)
636 }
637
638
639
640
641
642
643
644 func trace_userRegion(id, mode uint64, name string) {
645 tl := traceAcquire()
646 if !tl.ok() {
647
648 return
649 }
650 var ev tracev2.EventType
651 switch mode {
652 case 0:
653 ev = tracev2.EvUserRegionBegin
654 case 1:
655 ev = tracev2.EvUserRegionEnd
656 default:
657 return
658 }
659 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(ev, traceArg(id), tl.string(name), tl.stack(3))
660 traceRelease(tl)
661 }
662
663
664
665
666 func trace_userLog(id uint64, category, message string) {
667 tl := traceAcquire()
668 if !tl.ok() {
669
670 return
671 }
672 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvUserLog, traceArg(id), tl.string(category), tl.uniqueString(message), tl.stack(3))
673 traceRelease(tl)
674 }
675
676
677
678
679
680
681
682 func traceThreadDestroy(mp *m) {
683 assertLockHeld(&sched.lock)
684
685
686
687
688
689
690
691
692 seq := mp.trace.seqlock.Add(1)
693 if debugTraceReentrancy && seq%2 != 1 {
694 throw("bad use of trace.seqlock")
695 }
696 systemstack(func() {
697 lock(&trace.lock)
698 for i := range mp.trace.buf {
699 for exp, buf := range mp.trace.buf[i] {
700 if buf != nil {
701
702
703 traceBufFlush(buf, uintptr(i))
704 mp.trace.buf[i][exp] = nil
705 }
706 }
707 }
708 unlock(&trace.lock)
709 })
710 seq1 := mp.trace.seqlock.Add(1)
711 if seq1 != seq+1 {
712 print("runtime: seq1=", seq1, "\n")
713 throw("bad use of trace.seqlock")
714 }
715 }
716
View as plain text