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