@@ -235,6 +235,12 @@ func parseEvents(rawEvents []rawEvent) (events []*Event, err error) {
235
235
EvGoBlockSelect , EvGoBlockSync , EvGoBlockCond , EvGoBlockNet ,
236
236
EvGoSysBlock :
237
237
lastG = 0
238
+ case EvGoSysExit :
239
+ if e .Args [1 ] != 0 {
240
+ // EvGoSysExit emission is delayed until the thread has a P.
241
+ // Give it the real timestamp.
242
+ e .Ts = int64 (e .Args [1 ])
243
+ }
238
244
}
239
245
events = append (events , e )
240
246
}
@@ -423,7 +429,12 @@ func postProcessTrace(events []*Event) error {
423
429
g1 .state = gWaiting
424
430
gs [ev .Args [0 ]] = g1
425
431
case EvGoInSyscall :
426
- // this case is intentionally left blank
432
+ g1 := gs [ev .Args [0 ]]
433
+ if g1 .state != gRunnable {
434
+ return fmt .Errorf ("g %v is not runnable before EvGoInSyscall (offset %v, time %v)" , ev .Args [0 ], ev .Off , ev .Ts )
435
+ }
436
+ g1 .state = gWaiting
437
+ gs [ev .Args [0 ]] = g1
427
438
case EvGoCreate :
428
439
if err := checkRunning (p , g , ev ); err != nil {
429
440
return err
@@ -498,17 +509,18 @@ func postProcessTrace(events []*Event) error {
498
509
if err := checkRunning (p , g , ev ); err != nil {
499
510
return err
500
511
}
501
- g .state = gRunnable
512
+ g .state = gWaiting
502
513
g .evStart .Link = ev
503
514
g .evStart = nil
504
515
p .g = 0
505
516
case EvGoSysExit :
506
- if g .state != gRunnable {
507
- return fmt .Errorf ("g %v is not runnable during syscall exit (offset %v, time %v)" , ev .G , ev .Off , ev .Ts )
517
+ if g .state != gWaiting {
518
+ return fmt .Errorf ("g %v is not waiting during syscall exit (offset %v, time %v)" , ev .G , ev .Off , ev .Ts )
508
519
}
509
520
if g .ev != nil && g .ev .Type == EvGoSysCall {
510
521
g .ev .Link = ev
511
522
}
523
+ g .state = gRunnable
512
524
g .ev = ev
513
525
case EvGoSleep , EvGoBlock , EvGoBlockSend , EvGoBlockRecv ,
514
526
EvGoBlockSelect , EvGoBlockSync , EvGoBlockCond , EvGoBlockNet :
@@ -638,6 +650,18 @@ func (l eventList) Swap(i, j int) {
638
650
l [i ], l [j ] = l [j ], l [i ]
639
651
}
640
652
653
+ // Print dumps events to stdout. For debugging.
654
+ func Print (events []* Event ) {
655
+ for _ , ev := range events {
656
+ desc := EventDescriptions [ev .Type ]
657
+ fmt .Printf ("%v %v p=%v g=%v off=%v" , ev .Ts , desc .Name , ev .P , ev .G , ev .Off )
658
+ for i , a := range desc .Args {
659
+ fmt .Printf (" %v=%v" , a , ev .Args [i ])
660
+ }
661
+ fmt .Printf ("\n " )
662
+ }
663
+ }
664
+
641
665
// Event types in the trace.
642
666
// Verbatim copy from src/runtime/trace.go.
643
667
const (
@@ -670,7 +694,7 @@ const (
670
694
EvGoBlockCond = 26 // goroutine blocks on Cond [timestamp, stack]
671
695
EvGoBlockNet = 27 // goroutine blocks on network [timestamp, stack]
672
696
EvGoSysCall = 28 // syscall enter [timestamp, stack]
673
- EvGoSysExit = 29 // syscall exit [timestamp, goroutine id]
697
+ EvGoSysExit = 29 // syscall exit [timestamp, goroutine id, real timestamp ]
674
698
EvGoSysBlock = 30 // syscall blocks [timestamp]
675
699
EvGoWaiting = 31 // denotes that goroutine is blocked when tracing starts [goroutine id]
676
700
EvGoInSyscall = 32 // denotes that goroutine is in syscall when tracing starts [goroutine id]
@@ -715,7 +739,7 @@ var EventDescriptions = [EvCount]struct {
715
739
EvGoBlockCond : {"GoBlockCond" , true , []string {}},
716
740
EvGoBlockNet : {"GoBlockNet" , true , []string {}},
717
741
EvGoSysCall : {"GoSysCall" , true , []string {}},
718
- EvGoSysExit : {"GoSysExit" , false , []string {"g" }},
742
+ EvGoSysExit : {"GoSysExit" , false , []string {"g" , "ts" }},
719
743
EvGoSysBlock : {"GoSysBlock" , false , []string {}},
720
744
EvGoWaiting : {"GoWaiting" , false , []string {"g" }},
721
745
EvGoInSyscall : {"GoInSyscall" , false , []string {"g" }},
0 commit comments