}
o.gStates[newgid] = &gState{id: newgid, status: go122.GoRunnable, seq: makeSeq(gen, 0)}
return curCtx, true, nil
- case go122.EvGoDestroy, go122.EvGoStop, go122.EvGoBlock, go122.EvGoSyscallBegin:
+ case go122.EvGoDestroy, go122.EvGoStop, go122.EvGoBlock:
// These are goroutine events that all require an active running
// goroutine on some thread. They must *always* be advance-able,
// since running goroutines are bound to their M.
// Goroutine blocked. It's waiting now and not running on this M.
state.status = go122.GoWaiting
newCtx.G = NoGoroutine
- case go122.EvGoSyscallBegin:
- // Goroutine entered a syscall. It's still running on this P and M.
- state.status = go122.GoSyscall
- pState, ok := o.pStates[curCtx.P]
- if !ok {
- return curCtx, false, fmt.Errorf("uninitialized proc %d found during %s", curCtx.P, go122.EventString(typ))
- }
- pState.status = go122.ProcSyscall
}
return curCtx, true, nil
case go122.EvGoStart:
// N.B. No context to validate. Basically anything can unblock
// a goroutine (e.g. sysmon).
return curCtx, true, nil
+ case go122.EvGoSyscallBegin:
+ // Entering a syscall requires an active running goroutine with a
+ // proc on some thread. It is always advancable.
+ if err := validateCtx(curCtx, event.UserGoReqs); err != nil {
+ return curCtx, false, err
+ }
+ state, ok := o.gStates[curCtx.G]
+ if !ok {
+ return curCtx, false, fmt.Errorf("event %s for goroutine (%v) that doesn't exist", go122.EventString(typ), curCtx.G)
+ }
+ if state.status != go122.GoRunning {
+ return curCtx, false, fmt.Errorf("%s event for goroutine that's not %s", go122.EventString(typ), GoRunning)
+ }
+ // Goroutine entered a syscall. It's still running on this P and M.
+ state.status = go122.GoSyscall
+ pState, ok := o.pStates[curCtx.P]
+ if !ok {
+ return curCtx, false, fmt.Errorf("uninitialized proc %d found during %s", curCtx.P, go122.EventString(typ))
+ }
+ pState.status = go122.ProcSyscall
+ // Validate the P sequence number on the event and advance it.
+ //
+ // We have a P sequence number for what is supposed to be a goroutine event
+ // so that we can correctly model P stealing. Without this sequence number here,
+ // the syscall from which a ProcSteal event is stealing can be ambiguous in the
+ // face of broken timestamps. See the go122-syscall-steal-proc-ambiguous test for
+ // more details.
+ //
+ // Note that because this sequence number only exists as a tool for disambiguation,
+ // we can enforce that we have the right sequence number at this point; we don't need
+ // to back off and see if any other events will advance. This is a running P.
+ pSeq := makeSeq(gen, ev.args[0])
+ if !pSeq.succeeds(pState.seq) {
+ return curCtx, false, fmt.Errorf("failed to advance %s: can't make sequence: %s -> %s", go122.EventString(typ), pState.seq, pSeq)
+ }
+ pState.seq = pSeq
+ return curCtx, true, nil
case go122.EvGoSyscallEnd:
// This event is always advance-able because it happens on the same
// thread that EvGoSyscallStart happened, and the goroutine can't leave