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 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.seqlock.Load()%2 == 1 {
215 mp.trace.reentered++
216 return traceLocker{mp, mp.trace.entryGen}
217 }
218
219
220
221
222
223
224
225 seq := mp.trace.seqlock.Add(1)
226 if debugTraceReentrancy && seq%2 != 1 {
227 throw("bad use of trace.seqlock")
228 }
229
230
231
232
233
234
235
236
237
238 gen := trace.gen.Load()
239 if gen == 0 {
240 mp.trace.seqlock.Add(1)
241 releasem(mp)
242 return traceLocker{}
243 }
244 mp.trace.entryGen = gen
245 return traceLocker{mp, gen}
246 }
247
248
249
250
251
252
253 func (tl traceLocker) ok() bool {
254 return tl.gen != 0
255 }
256
257
258
259
260
261
262 func traceRelease(tl traceLocker) {
263 if tl.mp.trace.reentered > 0 {
264 tl.mp.trace.reentered--
265 } else {
266 seq := tl.mp.trace.seqlock.Add(1)
267 if debugTraceReentrancy && seq%2 != 0 {
268 print("runtime: seq=", seq, "\n")
269 throw("bad use of trace.seqlock")
270 }
271 }
272 releasem(tl.mp)
273 }
274
275
276
277
278 func traceExitingSyscall() {
279 trace.exitingSyscall.Add(1)
280 }
281
282
283 func traceExitedSyscall() {
284 trace.exitingSyscall.Add(-1)
285 }
286
287
288 func (tl traceLocker) Gomaxprocs(procs int32) {
289 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvProcsChange, traceArg(procs), tl.stack(1))
290 }
291
292
293
294
295 func (tl traceLocker) ProcStart() {
296 pp := tl.mp.p.ptr()
297
298
299
300 tl.eventWriter(tracev2.GoSyscall, tracev2.ProcIdle).event(tracev2.EvProcStart, traceArg(pp.id), pp.trace.nextSeq(tl.gen))
301 }
302
303
304 func (tl traceLocker) ProcStop(pp *p) {
305
306
307 tl.eventWriter(tracev2.GoSyscall, tracev2.ProcRunning).event(tracev2.EvProcStop)
308 }
309
310
311
312
313
314 func (tl traceLocker) GCActive() {
315 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvGCActive, traceArg(trace.seqGC))
316
317
318 trace.seqGC++
319 }
320
321
322
323
324
325 func (tl traceLocker) GCStart() {
326 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvGCBegin, traceArg(trace.seqGC), tl.stack(3))
327
328
329 trace.seqGC++
330 }
331
332
333
334
335
336 func (tl traceLocker) GCDone() {
337 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvGCEnd, traceArg(trace.seqGC))
338
339
340 trace.seqGC++
341 }
342
343
344 func (tl traceLocker) STWStart(reason stwReason) {
345
346
347 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvSTWBegin, tl.string(reason.String()), tl.stack(2))
348 }
349
350
351 func (tl traceLocker) STWDone() {
352
353
354 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvSTWEnd)
355 }
356
357
358
359
360
361
362
363
364 func (tl traceLocker) GCSweepStart() {
365
366
367 pp := tl.mp.p.ptr()
368 if pp.trace.maySweep {
369 throw("double traceGCSweepStart")
370 }
371 pp.trace.maySweep, pp.trace.swept, pp.trace.reclaimed = true, 0, 0
372 }
373
374
375
376
377
378
379
380
381
382 func (tl traceLocker) GCSweepSpan(bytesSwept uintptr) {
383 pp := tl.mp.p.ptr()
384 if pp.trace.maySweep {
385 if pp.trace.swept == 0 {
386 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvGCSweepBegin, tl.stack(1))
387 pp.trace.inSweep = true
388 }
389 pp.trace.swept += bytesSwept
390 }
391 }
392
393
394
395
396
397
398 func (tl traceLocker) GCSweepDone() {
399 pp := tl.mp.p.ptr()
400 if !pp.trace.maySweep {
401 throw("missing traceGCSweepStart")
402 }
403 if pp.trace.inSweep {
404 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvGCSweepEnd, traceArg(pp.trace.swept), traceArg(pp.trace.reclaimed))
405 pp.trace.inSweep = false
406 }
407 pp.trace.maySweep = false
408 }
409
410
411 func (tl traceLocker) GCMarkAssistStart() {
412 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvGCMarkAssistBegin, tl.stack(1))
413 }
414
415
416 func (tl traceLocker) GCMarkAssistDone() {
417 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvGCMarkAssistEnd)
418 }
419
420
421 func (tl traceLocker) GoCreate(newg *g, pc uintptr, blocked bool) {
422 newg.trace.setStatusTraced(tl.gen)
423 ev := tracev2.EvGoCreate
424 if blocked {
425 ev = tracev2.EvGoCreateBlocked
426 }
427 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(ev, traceArg(newg.goid), tl.startPC(pc), tl.stack(2))
428 }
429
430
431
432
433 func (tl traceLocker) GoStart() {
434 gp := getg().m.curg
435 pp := gp.m.p
436 w := tl.eventWriter(tracev2.GoRunnable, tracev2.ProcRunning)
437 w.event(tracev2.EvGoStart, traceArg(gp.goid), gp.trace.nextSeq(tl.gen))
438 if pp.ptr().gcMarkWorkerMode != gcMarkWorkerNotWorker {
439 w.event(tracev2.EvGoLabel, trace.markWorkerLabels[tl.gen%2][pp.ptr().gcMarkWorkerMode])
440 }
441 }
442
443
444
445
446 func (tl traceLocker) GoEnd() {
447 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvGoDestroy)
448 }
449
450
451 func (tl traceLocker) GoSched() {
452 tl.GoStop(traceGoStopGoSched)
453 }
454
455
456 func (tl traceLocker) GoPreempt() {
457 tl.GoStop(traceGoStopPreempted)
458 }
459
460
461 func (tl traceLocker) GoStop(reason traceGoStopReason) {
462 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvGoStop, trace.goStopReasons[tl.gen%2][reason], tl.stack(0))
463 }
464
465
466
467
468
469 func (tl traceLocker) GoPark(reason traceBlockReason, skip int) {
470 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvGoBlock, trace.goBlockReasons[tl.gen%2][reason], tl.stack(skip))
471 }
472
473
474 func (tl traceLocker) GoUnpark(gp *g, skip int) {
475
476 tl.emitUnblockStatus(gp, tl.gen)
477 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvGoUnblock, traceArg(gp.goid), gp.trace.nextSeq(tl.gen), tl.stack(skip))
478 }
479
480
481
482 func (tl traceLocker) GoSwitch(nextg *g, destroy bool) {
483
484 tl.emitUnblockStatus(nextg, tl.gen)
485 w := tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning)
486 ev := tracev2.EvGoSwitch
487 if destroy {
488 ev = tracev2.EvGoSwitchDestroy
489 }
490 w.event(ev, traceArg(nextg.goid), nextg.trace.nextSeq(tl.gen))
491 }
492
493
494
495 func (tl traceLocker) emitUnblockStatus(gp *g, gen uintptr) {
496 if !gp.trace.statusWasTraced(gen) && gp.trace.acquireStatus(gen) {
497
498
499
500 tl.writer().writeGoStatus(gp.goid, -1, tracev2.GoWaiting, gp.inMarkAssist, 0).end()
501 }
502 }
503
504
505
506
507 func (tl traceLocker) GoSysCall() {
508
509 pp := tl.mp.p.ptr()
510 pp.trace.mSyscallID = int64(tl.mp.procid)
511 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvGoSyscallBegin, pp.trace.nextSeq(tl.gen), tl.stack(1))
512 }
513
514
515
516
517
518
519
520
521
522
523 func (tl traceLocker) GoSysExit(lostP bool) {
524 ev := tracev2.EvGoSyscallEnd
525 procStatus := tracev2.ProcSyscall
526 if lostP {
527 ev = tracev2.EvGoSyscallEndBlocked
528 procStatus = tracev2.ProcRunning
529 } else {
530 tl.mp.p.ptr().trace.mSyscallID = -1
531 }
532 tl.eventWriter(tracev2.GoSyscall, procStatus).event(ev)
533 }
534
535
536
537
538 func (tl traceLocker) ProcSteal(pp *p) {
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 tl.mp.curg != nil && tl.mp.curg.syscallsp != 0 {
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
597
598
599
600 tl.rawEventWriter().event(tracev2.EvGoCreateSyscall, traceArg(gp.goid))
601 }
602
603
604
605
606
607 func (tl traceLocker) GoDestroySyscall() {
608
609 if gp := tl.mp.curg; gp != nil && !gp.trace.statusWasTraced(tl.gen) && gp.trace.acquireStatus(tl.gen) {
610 tl.writer().writeGoStatus(gp.goid, int64(tl.mp.procid), tracev2.GoSyscall, false, 0 ).end()
611 }
612
613
614
615
616 tl.rawEventWriter().event(tracev2.EvGoDestroySyscall)
617 }
618
619
620
621
622
623
624
625 func trace_userTaskCreate(id, parentID uint64, taskType string) {
626 tl := traceAcquire()
627 if !tl.ok() {
628
629 return
630 }
631 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvUserTaskBegin, traceArg(id), traceArg(parentID), tl.string(taskType), tl.stack(3))
632 traceRelease(tl)
633 }
634
635
636
637
638 func trace_userTaskEnd(id uint64) {
639 tl := traceAcquire()
640 if !tl.ok() {
641
642 return
643 }
644 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvUserTaskEnd, traceArg(id), tl.stack(2))
645 traceRelease(tl)
646 }
647
648
649
650
651
652
653
654 func trace_userRegion(id, mode uint64, name string) {
655 tl := traceAcquire()
656 if !tl.ok() {
657
658 return
659 }
660 var ev tracev2.EventType
661 switch mode {
662 case 0:
663 ev = tracev2.EvUserRegionBegin
664 case 1:
665 ev = tracev2.EvUserRegionEnd
666 default:
667 return
668 }
669 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(ev, traceArg(id), tl.string(name), tl.stack(3))
670 traceRelease(tl)
671 }
672
673
674
675
676 func trace_userLog(id uint64, category, message string) {
677 tl := traceAcquire()
678 if !tl.ok() {
679
680 return
681 }
682 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvUserLog, traceArg(id), tl.string(category), tl.uniqueString(message), tl.stack(3))
683 traceRelease(tl)
684 }
685
686
687
688
689
690
691
692 func traceThreadDestroy(mp *m) {
693 assertLockHeld(&sched.lock)
694
695
696
697
698
699
700
701
702 seq := mp.trace.seqlock.Add(1)
703 if debugTraceReentrancy && seq%2 != 1 {
704 throw("bad use of trace.seqlock")
705 }
706 systemstack(func() {
707 lock(&trace.lock)
708 for i := range mp.trace.buf {
709 for exp, buf := range mp.trace.buf[i] {
710 if buf != nil {
711
712
713 traceBufFlush(buf, uintptr(i))
714 mp.trace.buf[i][exp] = nil
715 }
716 }
717 }
718 unlock(&trace.lock)
719 })
720 seq1 := mp.trace.seqlock.Add(1)
721 if seq1 != seq+1 {
722 print("runtime: seq1=", seq1, "\n")
723 throw("bad use of trace.seqlock")
724 }
725 }
726
View as plain text