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
539
540 func (tl traceLocker) ProcSteal(pp *p, inSyscall bool) {
541
542 mStolenFrom := pp.trace.mSyscallID
543 pp.trace.mSyscallID = -1
544
545
546
547
548
549
550 if !pp.trace.statusWasTraced(tl.gen) && pp.trace.acquireStatus(tl.gen) {
551
552
553 tl.writer().writeProcStatus(uint64(pp.id), tracev2.ProcSyscallAbandoned, pp.trace.inSweep).end()
554 }
555
556
557
558
559
560
561
562 goStatus := tracev2.GoRunning
563 procStatus := tracev2.ProcRunning
564 if inSyscall {
565 goStatus = tracev2.GoSyscall
566 procStatus = tracev2.ProcSyscallAbandoned
567 }
568 tl.eventWriter(goStatus, procStatus).event(tracev2.EvProcSteal, traceArg(pp.id), pp.trace.nextSeq(tl.gen), traceArg(mStolenFrom))
569 }
570
571
572 func (tl traceLocker) HeapAlloc(live uint64) {
573 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvHeapAlloc, traceArg(live))
574 }
575
576
577 func (tl traceLocker) HeapGoal() {
578 heapGoal := gcController.heapGoal()
579
580
581 if heapGoal == ^uint64(0) || gcController.gcPercent.Load() < 0 {
582
583 heapGoal = 0
584 }
585 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvHeapGoal, traceArg(heapGoal))
586 }
587
588
589
590
591
592
593
594 func (tl traceLocker) GoCreateSyscall(gp *g) {
595
596
597 gp.trace.setStatusTraced(tl.gen)
598 tl.eventWriter(tracev2.GoBad, tracev2.ProcBad).event(tracev2.EvGoCreateSyscall, traceArg(gp.goid))
599 }
600
601
602
603
604
605
606
607 func (tl traceLocker) GoDestroySyscall() {
608
609
610 tl.eventWriter(tracev2.GoSyscall, tracev2.ProcBad).event(tracev2.EvGoDestroySyscall)
611 }
612
613
614
615
616
617
618
619 func trace_userTaskCreate(id, parentID uint64, taskType string) {
620 tl := traceAcquire()
621 if !tl.ok() {
622
623 return
624 }
625 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvUserTaskBegin, traceArg(id), traceArg(parentID), tl.string(taskType), tl.stack(3))
626 traceRelease(tl)
627 }
628
629
630
631
632 func trace_userTaskEnd(id uint64) {
633 tl := traceAcquire()
634 if !tl.ok() {
635
636 return
637 }
638 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvUserTaskEnd, traceArg(id), tl.stack(2))
639 traceRelease(tl)
640 }
641
642
643
644
645
646
647
648 func trace_userRegion(id, mode uint64, name string) {
649 tl := traceAcquire()
650 if !tl.ok() {
651
652 return
653 }
654 var ev tracev2.EventType
655 switch mode {
656 case 0:
657 ev = tracev2.EvUserRegionBegin
658 case 1:
659 ev = tracev2.EvUserRegionEnd
660 default:
661 return
662 }
663 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(ev, traceArg(id), tl.string(name), tl.stack(3))
664 traceRelease(tl)
665 }
666
667
668
669
670 func trace_userLog(id uint64, category, message string) {
671 tl := traceAcquire()
672 if !tl.ok() {
673
674 return
675 }
676 tl.eventWriter(tracev2.GoRunning, tracev2.ProcRunning).event(tracev2.EvUserLog, traceArg(id), tl.string(category), tl.uniqueString(message), tl.stack(3))
677 traceRelease(tl)
678 }
679
680
681
682
683
684
685
686 func traceThreadDestroy(mp *m) {
687 assertLockHeld(&sched.lock)
688
689
690
691
692
693
694
695
696 seq := mp.trace.seqlock.Add(1)
697 if debugTraceReentrancy && seq%2 != 1 {
698 throw("bad use of trace.seqlock")
699 }
700 systemstack(func() {
701 lock(&trace.lock)
702 for i := range mp.trace.buf {
703 for exp, buf := range mp.trace.buf[i] {
704 if buf != nil {
705
706
707 traceBufFlush(buf, uintptr(i))
708 mp.trace.buf[i][exp] = nil
709 }
710 }
711 }
712 unlock(&trace.lock)
713 })
714 seq1 := mp.trace.seqlock.Add(1)
715 if seq1 != seq+1 {
716 print("runtime: seq1=", seq1, "\n")
717 throw("bad use of trace.seqlock")
718 }
719 }
720
View as plain text