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