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