// Copyright 2023 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package trace

import (
	"fmt"
	"slices"
	"strings"

	"internal/trace/tracev2"
	"internal/trace/version"
)

// ordering emulates Go scheduler state for both validation and
// for putting events in the right order.
//
// The interface to ordering consists of two methods: Advance
// and Next. Advance is called to try and advance an event and
// add completed events to the ordering. Next is used to pick
// off events in the ordering.
type ordering struct {
	traceVer    version.Version
	gStates     map[GoID]*gState
	pStates     map[ProcID]*pState // TODO: The keys are dense, so this can be a slice.
	mStates     map[ThreadID]*mState
	activeTasks map[TaskID]taskState
	gcSeq       uint64
	gcState     gcState
	initialGen  uint64
	queue       queue[Event]
}

// Advance checks if it's valid to proceed with ev which came from thread m.
//
// It assumes the gen value passed to it is monotonically increasing across calls.
//
// If any error is returned, then the trace is broken and trace parsing must cease.
// If it's not valid to advance with ev, but no error was encountered, the caller
// should attempt to advance with other candidate events from other threads. If the
// caller runs out of candidates, the trace is invalid.
//
// If this returns true, Next is guaranteed to return a complete event. However,
// multiple events may be added to the ordering, so the caller should (but is not
// required to) continue to call Next until it is exhausted.
func (o *ordering) Advance(ev *baseEvent, evt *evTable, m ThreadID, gen uint64) (bool, error) {
	if o.initialGen == 0 {
		// Set the initial gen if necessary.
		o.initialGen = gen
	}

	var curCtx, newCtx schedCtx
	curCtx.M = m
	newCtx.M = m

	var ms *mState
	if m == NoThread {
		curCtx.P = NoProc
		curCtx.G = NoGoroutine
		newCtx = curCtx
	} else {
		// Pull out or create the mState for this event.
		var ok bool
		ms, ok = o.mStates[m]
		if !ok {
			ms = &mState{
				g: NoGoroutine,
				p: NoProc,
			}
			o.mStates[m] = ms
		}
		curCtx.P = ms.p
		curCtx.G = ms.g
		newCtx = curCtx
	}

	f := orderingDispatch[ev.typ]
	if f == nil {
		return false, fmt.Errorf("bad event type found while ordering: %v", ev.typ)
	}
	newCtx, ok, err := f(o, ev, evt, m, gen, curCtx)
	if err == nil && ok && ms != nil {
		// Update the mState for this event.
		ms.p = newCtx.P
		ms.g = newCtx.G
	}
	return ok, err
}

func (o *ordering) evName(typ tracev2.EventType) string {
	return o.traceVer.EventName(typ)
}

type orderingHandleFunc func(o *ordering, ev *baseEvent, evt *evTable, m ThreadID, gen uint64, curCtx schedCtx) (schedCtx, bool, error)

var orderingDispatch = [256]orderingHandleFunc{
	// Procs.
	tracev2.EvProcsChange: (*ordering).advanceAnnotation,
	tracev2.EvProcStart:   (*ordering).advanceProcStart,
	tracev2.EvProcStop:    (*ordering).advanceProcStop,
	tracev2.EvProcSteal:   (*ordering).advanceProcSteal,
	tracev2.EvProcStatus:  (*ordering).advanceProcStatus,

	// Goroutines.
	tracev2.EvGoCreate:            (*ordering).advanceGoCreate,
	tracev2.EvGoCreateSyscall:     (*ordering).advanceGoCreateSyscall,
	tracev2.EvGoStart:             (*ordering).advanceGoStart,
	tracev2.EvGoDestroy:           (*ordering).advanceGoStopExec,
	tracev2.EvGoDestroySyscall:    (*ordering).advanceGoDestroySyscall,
	tracev2.EvGoStop:              (*ordering).advanceGoStopExec,
	tracev2.EvGoBlock:             (*ordering).advanceGoStopExec,
	tracev2.EvGoUnblock:           (*ordering).advanceGoUnblock,
	tracev2.EvGoSyscallBegin:      (*ordering).advanceGoSyscallBegin,
	tracev2.EvGoSyscallEnd:        (*ordering).advanceGoSyscallEnd,
	tracev2.EvGoSyscallEndBlocked: (*ordering).advanceGoSyscallEndBlocked,
	tracev2.EvGoStatus:            (*ordering).advanceGoStatus,

	// STW.
	tracev2.EvSTWBegin: (*ordering).advanceGoRangeBegin,
	tracev2.EvSTWEnd:   (*ordering).advanceGoRangeEnd,

	// GC events.
	tracev2.EvGCActive:           (*ordering).advanceGCActive,
	tracev2.EvGCBegin:            (*ordering).advanceGCBegin,
	tracev2.EvGCEnd:              (*ordering).advanceGCEnd,
	tracev2.EvGCSweepActive:      (*ordering).advanceGCSweepActive,
	tracev2.EvGCSweepBegin:       (*ordering).advanceGCSweepBegin,
	tracev2.EvGCSweepEnd:         (*ordering).advanceGCSweepEnd,
	tracev2.EvGCMarkAssistActive: (*ordering).advanceGoRangeActive,
	tracev2.EvGCMarkAssistBegin:  (*ordering).advanceGoRangeBegin,
	tracev2.EvGCMarkAssistEnd:    (*ordering).advanceGoRangeEnd,
	tracev2.EvHeapAlloc:          (*ordering).advanceHeapMetric,
	tracev2.EvHeapGoal:           (*ordering).advanceHeapMetric,

	// Annotations.
	tracev2.EvGoLabel:         (*ordering).advanceAnnotation,
	tracev2.EvUserTaskBegin:   (*ordering).advanceUserTaskBegin,
	tracev2.EvUserTaskEnd:     (*ordering).advanceUserTaskEnd,
	tracev2.EvUserRegionBegin: (*ordering).advanceUserRegionBegin,
	tracev2.EvUserRegionEnd:   (*ordering).advanceUserRegionEnd,
	tracev2.EvUserLog:         (*ordering).advanceAnnotation,

	// Coroutines. Added in Go 1.23.
	tracev2.EvGoSwitch:        (*ordering).advanceGoSwitch,
	tracev2.EvGoSwitchDestroy: (*ordering).advanceGoSwitch,
	tracev2.EvGoCreateBlocked: (*ordering).advanceGoCreate,

	// GoStatus event with a stack. Added in Go 1.23.
	tracev2.EvGoStatusStack: (*ordering).advanceGoStatus,

	// Experimental events.

	// Experimental heap span events. Added in Go 1.23.
	tracev2.EvSpan:      (*ordering).advanceAllocFree,
	tracev2.EvSpanAlloc: (*ordering).advanceAllocFree,
	tracev2.EvSpanFree:  (*ordering).advanceAllocFree,

	// Experimental heap object events. Added in Go 1.23.
	tracev2.EvHeapObject:      (*ordering).advanceAllocFree,
	tracev2.EvHeapObjectAlloc: (*ordering).advanceAllocFree,
	tracev2.EvHeapObjectFree:  (*ordering).advanceAllocFree,

	// Experimental goroutine stack events. Added in Go 1.23.
	tracev2.EvGoroutineStack:      (*ordering).advanceAllocFree,
	tracev2.EvGoroutineStackAlloc: (*ordering).advanceAllocFree,
	tracev2.EvGoroutineStackFree:  (*ordering).advanceAllocFree,
}

func (o *ordering) advanceProcStatus(ev *baseEvent, evt *evTable, m ThreadID, gen uint64, curCtx schedCtx) (schedCtx, bool, error) {
	pid := ProcID(ev.args[0])
	status := tracev2.ProcStatus(ev.args[1])
	if int(status) >= len(tracev2ProcStatus2ProcState) {
		return curCtx, false, fmt.Errorf("invalid status for proc %d: %d", pid, status)
	}
	oldState := tracev2ProcStatus2ProcState[status]
	if s, ok := o.pStates[pid]; ok {
		if status == tracev2.ProcSyscallAbandoned && s.status == tracev2.ProcSyscall {
			// ProcSyscallAbandoned is a special case of ProcSyscall. It indicates a
			// potential loss of information, but if we're already in ProcSyscall,
			// we haven't lost the relevant information. Promote the status and advance.
			oldState = ProcRunning
			ev.args[1] = uint64(tracev2.ProcSyscall)
		} else if status == tracev2.ProcSyscallAbandoned && s.status == tracev2.ProcSyscallAbandoned {
			// If we're passing through ProcSyscallAbandoned, then there's no promotion
			// to do. We've lost the M that this P is associated with. However it got there,
			// it's going to appear as idle in the API, so pass through as idle.
			oldState = ProcIdle
			ev.args[1] = uint64(tracev2.ProcSyscallAbandoned)
		} else if s.status != status {
			return curCtx, false, fmt.Errorf("inconsistent status for proc %d: old %v vs. new %v", pid, s.status, status)
		}
		s.seq = makeSeq(gen, 0) // Reset seq.
	} else {
		o.pStates[pid] = &pState{id: pid, status: status, seq: makeSeq(gen, 0)}
		if gen == o.initialGen {
			oldState = ProcUndetermined
		} else {
			oldState = ProcNotExist
		}
	}
	ev.extra(version.Go122)[0] = uint64(oldState) // Smuggle in the old state for StateTransition.

	// Bind the proc to the new context, if it's running.
	newCtx := curCtx
	if status == tracev2.ProcRunning || status == tracev2.ProcSyscall {
		newCtx.P = pid
	}
	// If we're advancing through ProcSyscallAbandoned *but* oldState is running then we've
	// promoted it to ProcSyscall. However, because it's ProcSyscallAbandoned, we know this
	// P is about to get stolen and its status very likely isn't being emitted by the same
	// thread it was bound to. Since this status is Running -> Running and Running is binding,
	// we need to make sure we emit it in the right context: the context to which it is bound.
	// Find it, and set our current context to it.
	if status == tracev2.ProcSyscallAbandoned && oldState == ProcRunning {
		// N.B. This is slow but it should be fairly rare.
		found := false
		for mid, ms := range o.mStates {
			if ms.p == pid {
				curCtx.M = mid
				curCtx.P = pid
				curCtx.G = ms.g
				found = true
			}
		}
		if !found {
			return curCtx, false, fmt.Errorf("failed to find sched context for proc %d that's about to be stolen", pid)
		}
	}
	o.queue.push(Event{table: evt, ctx: curCtx, base: *ev})
	return newCtx, true, nil
}

func (o *ordering) advanceProcStart(ev *baseEvent, evt *evTable, m ThreadID, gen uint64, curCtx schedCtx) (schedCtx, bool, error) {
	pid := ProcID(ev.args[0])
	seq := makeSeq(gen, ev.args[1])

	// Try to advance. We might fail here due to sequencing, because the P hasn't
	// had a status emitted, or because we already have a P and we're in a syscall,
	// and we haven't observed that it was stolen from us yet.
	state, ok := o.pStates[pid]
	if !ok || state.status != tracev2.ProcIdle || !seq.succeeds(state.seq) || curCtx.P != NoProc {
		// We can't make an inference as to whether this is bad. We could just be seeing
		// a ProcStart on a different M before the proc's state was emitted, or before we
		// got to the right point in the trace.
		//
		// Note that we also don't advance here if we have a P and we're in a syscall.
		return curCtx, false, nil
	}
	// We can advance this P. Check some invariants.
	//
	// We might have a goroutine if a goroutine is exiting a syscall.
	reqs := schedReqs{M: mustHave, P: mustNotHave, G: mayHave}
	if err := validateCtx(curCtx, reqs); err != nil {
		return curCtx, false, err
	}
	state.status = tracev2.ProcRunning
	state.seq = seq
	newCtx := curCtx
	newCtx.P = pid
	o.queue.push(Event{table: evt, ctx: curCtx, base: *ev})
	return newCtx, true, nil
}

func (o *ordering) advanceProcStop(ev *baseEvent, evt *evTable, m ThreadID, gen uint64, curCtx schedCtx) (schedCtx, bool, error) {
	// We must be able to advance this P.
	//
	// There are 2 ways a P can stop: ProcStop and ProcSteal. ProcStop is used when the P
	// is stopped by the same M that started it, while ProcSteal is used when another M
	// steals the P by stopping it from a distance.
	//
	// Since a P is bound to an M, and we're stopping on the same M we started, it must
	// always be possible to advance the current M's P from a ProcStop. This is also why
	// ProcStop doesn't need a sequence number.
	state, ok := o.pStates[curCtx.P]
	if !ok {
		return curCtx, false, fmt.Errorf("event %s for proc (%v) that doesn't exist", o.evName(ev.typ), curCtx.P)
	}
	if state.status != tracev2.ProcRunning && state.status != tracev2.ProcSyscall {
		return curCtx, false, fmt.Errorf("%s event for proc that's not %s or %s", o.evName(ev.typ), tracev2.ProcRunning, tracev2.ProcSyscall)
	}
	reqs := schedReqs{M: mustHave, P: mustHave, G: mayHave}
	if err := validateCtx(curCtx, reqs); err != nil {
		return curCtx, false, err
	}
	state.status = tracev2.ProcIdle
	newCtx := curCtx
	newCtx.P = NoProc
	o.queue.push(Event{table: evt, ctx: curCtx, base: *ev})
	return newCtx, true, nil
}

func (o *ordering) advanceProcSteal(ev *baseEvent, evt *evTable, m ThreadID, gen uint64, curCtx schedCtx) (schedCtx, bool, error) {
	pid := ProcID(ev.args[0])
	seq := makeSeq(gen, ev.args[1])
	state, ok := o.pStates[pid]
	if !ok || (state.status != tracev2.ProcSyscall && state.status != tracev2.ProcSyscallAbandoned) || !seq.succeeds(state.seq) {
		// We can't make an inference as to whether this is bad. We could just be seeing
		// a ProcStart on a different M before the proc's state was emitted, or before we
		// got to the right point in the trace.
		return curCtx, false, nil
	}
	// We can advance this P. Check some invariants.
	reqs := schedReqs{M: mustHave, P: mayHave, G: mayHave}
	if err := validateCtx(curCtx, reqs); err != nil {
		return curCtx, false, err
	}
	// Smuggle in the P state that let us advance so we can surface information to the event.
	// Specifically, we need to make sure that the event is interpreted not as a transition of
	// ProcRunning -> ProcIdle but ProcIdle -> ProcIdle instead.
	//
	// ProcRunning is binding, but we may be running with a P on the current M and we can't
	// bind another P. This P is about to go ProcIdle anyway.
	oldStatus := state.status
	ev.extra(version.Go122)[0] = uint64(oldStatus)

	// Update the P's status and sequence number.
	state.status = tracev2.ProcIdle
	state.seq = seq

	// If we've lost information then don't try to do anything with the M.
	// It may have moved on and we can't be sure.
	if oldStatus == tracev2.ProcSyscallAbandoned {
		o.queue.push(Event{table: evt, ctx: curCtx, base: *ev})
		return curCtx, true, nil
	}

	// Validate that the M we're stealing from is what we expect.
	mid := ThreadID(ev.args[2]) // The M we're stealing from.

	newCtx := curCtx
	if mid == curCtx.M {
		// We're stealing from ourselves. This behaves like a ProcStop.
		if curCtx.P != pid {
			return curCtx, false, fmt.Errorf("tried to self-steal proc %d (thread %d), but got proc %d instead", pid, mid, curCtx.P)
		}
		newCtx.P = NoProc
		o.queue.push(Event{table: evt, ctx: curCtx, base: *ev})
		return newCtx, true, nil
	}

	// We're stealing from some other M.
	mState, ok := o.mStates[mid]
	if !ok {
		return curCtx, false, fmt.Errorf("stole proc from non-existent thread %d", mid)
	}

	// Make sure we're actually stealing the right P.
	if mState.p != pid {
		return curCtx, false, fmt.Errorf("tried to steal proc %d from thread %d, but got proc %d instead", pid, mid, mState.p)
	}

	// Tell the M it has no P so it can proceed.
	//
	// This is safe because we know the P was in a syscall and
	// the other M must be trying to get out of the syscall.
	// GoSyscallEndBlocked cannot advance until the corresponding
	// M loses its P.
	mState.p = NoProc
	o.queue.push(Event{table: evt, ctx: curCtx, base: *ev})
	return newCtx, true, nil
}

func (o *ordering) advanceGoStatus(ev *baseEvent, evt *evTable, m ThreadID, gen uint64, curCtx schedCtx) (schedCtx, bool, error) {
	gid := GoID(ev.args[0])
	mid := ThreadID(ev.args[1])
	status := tracev2.GoStatus(ev.args[2])

	if int(status) >= len(tracev2GoStatus2GoState) {
		return curCtx, false, fmt.Errorf("invalid status for goroutine %d: %d", gid, status)
	}
	oldState := tracev2GoStatus2GoState[status]
	if s, ok := o.gStates[gid]; ok {
		if s.status != status {
			return curCtx, false, fmt.Errorf("inconsistent status for goroutine %d: old %v vs. new %v", gid, s.status, status)
		}
		s.seq = makeSeq(gen, 0) // Reset seq.
	} else if gen == o.initialGen {
		// Set the state.
		o.gStates[gid] = &gState{id: gid, status: status, seq: makeSeq(gen, 0)}
		oldState = GoUndetermined
	} else {
		return curCtx, false, fmt.Errorf("found goroutine status for new goroutine after the first generation: id=%v status=%v", gid, status)
	}
	ev.args[2] = uint64(oldState)<<32 | uint64(status) // Smuggle in the old state for StateTransition.

	newCtx := curCtx
	switch status {
	case tracev2.GoRunning:
		// Bind the goroutine to the new context, since it's running.
		newCtx.G = gid
	case tracev2.GoSyscall:
		if mid == NoThread {
			return curCtx, false, fmt.Errorf("found goroutine %d in syscall without a thread", gid)
		}
		// Is the syscall on this thread? If so, bind it to the context.
		// Otherwise, we're talking about a G sitting in a syscall on an M.
		// Validate the named M.
		if mid == curCtx.M {
			if gen != o.initialGen && curCtx.G != gid {
				// If this isn't the first generation, we *must* have seen this
				// binding occur already. Even if the G was blocked in a syscall
				// for multiple generations since trace start, we would have seen
				// a previous GoStatus event that bound the goroutine to an M.
				return curCtx, false, fmt.Errorf("inconsistent thread for syscalling goroutine %d: thread has goroutine %d", gid, curCtx.G)
			}
			newCtx.G = gid
			break
		}
		// Now we're talking about a thread and goroutine that have been
		// blocked on a syscall for the entire generation. This case must
		// not have a P; the runtime makes sure that all Ps are traced at
		// the beginning of a generation, which involves taking a P back
		// from every thread.
		ms, ok := o.mStates[mid]
		if ok {
			// This M has been seen. That means we must have seen this
			// goroutine go into a syscall on this thread at some point.
			if ms.g != gid {
				// But the G on the M doesn't match. Something's wrong.
				return curCtx, false, fmt.Errorf("inconsistent thread for syscalling goroutine %d: thread has goroutine %d", gid, ms.g)
			}
			// This case is just a Syscall->Syscall event, which needs to
			// appear as having the G currently bound to this M.
			curCtx.G = ms.g
		} else if !ok {
			// The M hasn't been seen yet. That means this goroutine
			// has just been sitting in a syscall on this M. Create
			// a state for it.
			o.mStates[mid] = &mState{g: gid, p: NoProc}
			// Don't set curCtx.G in this case because this event is the
			// binding event (and curCtx represents the "before" state).
		}
		// Update the current context to the M we're talking about.
		curCtx.M = mid
	}
	o.queue.push(Event{table: evt, ctx: curCtx, base: *ev})
	return newCtx, true, nil
}

func (o *ordering) advanceGoCreate(ev *baseEvent, evt *evTable, m ThreadID, gen uint64, curCtx schedCtx) (schedCtx, bool, error) {
	// Goroutines must be created on a running P, but may or may not be created
	// by a running goroutine.
	reqs := schedReqs{M: mustHave, P: mustHave, G: mayHave}
	if err := validateCtx(curCtx, reqs); err != nil {
		return curCtx, false, err
	}
	// If we have a goroutine, it must be running.
	if state, ok := o.gStates[curCtx.G]; ok && state.status != tracev2.GoRunning {
		return curCtx, false, fmt.Errorf("%s event for goroutine that's not %s", o.evName(ev.typ), GoRunning)
	}
	// This goroutine created another. Add a state for it.
	newgid := GoID(ev.args[0])
	if _, ok := o.gStates[newgid]; ok {
		return curCtx, false, fmt.Errorf("tried to create goroutine (%v) that already exists", newgid)
	}
	status := tracev2.GoRunnable
	if ev.typ == tracev2.EvGoCreateBlocked {
		status = tracev2.GoWaiting
	}
	o.gStates[newgid] = &gState{id: newgid, status: status, seq: makeSeq(gen, 0)}
	o.queue.push(Event{table: evt, ctx: curCtx, base: *ev})
	return curCtx, true, nil
}

func (o *ordering) advanceGoStopExec(ev *baseEvent, evt *evTable, m ThreadID, gen uint64, curCtx schedCtx) (schedCtx, bool, error) {
	// 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.
	if err := validateCtx(curCtx, 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", o.evName(ev.typ), curCtx.G)
	}
	if state.status != tracev2.GoRunning {
		return curCtx, false, fmt.Errorf("%s event for goroutine that's not %s", o.evName(ev.typ), GoRunning)
	}
	// Handle each case slightly differently; we just group them together
	// because they have shared preconditions.
	newCtx := curCtx
	switch ev.typ {
	case tracev2.EvGoDestroy:
		// This goroutine is exiting itself.
		delete(o.gStates, curCtx.G)
		newCtx.G = NoGoroutine
	case tracev2.EvGoStop:
		// Goroutine stopped (yielded). It's runnable but not running on this M.
		state.status = tracev2.GoRunnable
		newCtx.G = NoGoroutine
	case tracev2.EvGoBlock:
		// Goroutine blocked. It's waiting now and not running on this M.
		state.status = tracev2.GoWaiting
		newCtx.G = NoGoroutine
	}
	o.queue.push(Event{table: evt, ctx: curCtx, base: *ev})
	return newCtx, true, nil
}

func (o *ordering) advanceGoStart(ev *baseEvent, evt *evTable, m ThreadID, gen uint64, curCtx schedCtx) (schedCtx, bool, error) {
	gid := GoID(ev.args[0])
	seq := makeSeq(gen, ev.args[1])
	state, ok := o.gStates[gid]
	if !ok || state.status != tracev2.GoRunnable || !seq.succeeds(state.seq) {
		// We can't make an inference as to whether this is bad. We could just be seeing
		// a GoStart on a different M before the goroutine was created, before it had its
		// state emitted, or before we got to the right point in the trace yet.
		return curCtx, false, nil
	}
	// We can advance this goroutine. Check some invariants.
	reqs := schedReqs{M: mustHave, P: mustHave, G: mustNotHave}
	if err := validateCtx(curCtx, reqs); err != nil {
		return curCtx, false, err
	}
	state.status = tracev2.GoRunning
	state.seq = seq
	newCtx := curCtx
	newCtx.G = gid
	o.queue.push(Event{table: evt, ctx: curCtx, base: *ev})
	return newCtx, true, nil
}

func (o *ordering) advanceGoUnblock(ev *baseEvent, evt *evTable, m ThreadID, gen uint64, curCtx schedCtx) (schedCtx, bool, error) {
	// N.B. These both reference the goroutine to unblock, not the current goroutine.
	gid := GoID(ev.args[0])
	seq := makeSeq(gen, ev.args[1])
	state, ok := o.gStates[gid]
	if !ok || state.status != tracev2.GoWaiting || !seq.succeeds(state.seq) {
		// We can't make an inference as to whether this is bad. We could just be seeing
		// a GoUnblock on a different M before the goroutine was created and blocked itself,
		// before it had its state emitted, or before we got to the right point in the trace yet.
		return curCtx, false, nil
	}
	state.status = tracev2.GoRunnable
	state.seq = seq
	// N.B. No context to validate. Basically anything can unblock
	// a goroutine (e.g. sysmon).
	o.queue.push(Event{table: evt, ctx: curCtx, base: *ev})
	return curCtx, true, nil
}

func (o *ordering) advanceGoSwitch(ev *baseEvent, evt *evTable, m ThreadID, gen uint64, curCtx schedCtx) (schedCtx, bool, error) {
	// GoSwitch and GoSwitchDestroy represent a trio of events:
	// - Unblock of the goroutine to switch to.
	// - Block or destroy of the current goroutine.
	// - Start executing the next goroutine.
	//
	// Because it acts like a GoStart for the next goroutine, we can
	// only advance it if the sequence numbers line up.
	//
	// The current goroutine on the thread must be actively running.
	if err := validateCtx(curCtx, userGoReqs); err != nil {
		return curCtx, false, err
	}
	curGState, ok := o.gStates[curCtx.G]
	if !ok {
		return curCtx, false, fmt.Errorf("event %s for goroutine (%v) that doesn't exist", o.evName(ev.typ), curCtx.G)
	}
	if curGState.status != tracev2.GoRunning {
		return curCtx, false, fmt.Errorf("%s event for goroutine that's not %s", o.evName(ev.typ), GoRunning)
	}
	nextg := GoID(ev.args[0])
	seq := makeSeq(gen, ev.args[1]) // seq is for nextg, not curCtx.G.
	nextGState, ok := o.gStates[nextg]
	if !ok || nextGState.status != tracev2.GoWaiting || !seq.succeeds(nextGState.seq) {
		// We can't make an inference as to whether this is bad. We could just be seeing
		// a GoSwitch on a different M before the goroutine was created, before it had its
		// state emitted, or before we got to the right point in the trace yet.
		return curCtx, false, nil
	}
	o.queue.push(Event{table: evt, ctx: curCtx, base: *ev})

	// Update the state of the executing goroutine and emit an event for it
	// (GoSwitch and GoSwitchDestroy will be interpreted as GoUnblock events
	// for nextg).
	switch ev.typ {
	case tracev2.EvGoSwitch:
		// Goroutine blocked. It's waiting now and not running on this M.
		curGState.status = tracev2.GoWaiting

		// Emit a GoBlock event.
		// TODO(mknyszek): Emit a reason.
		o.queue.push(makeEvent(evt, curCtx, tracev2.EvGoBlock, ev.time, 0 /* no reason */, 0 /* no stack */))
	case tracev2.EvGoSwitchDestroy:
		// This goroutine is exiting itself.
		delete(o.gStates, curCtx.G)

		// Emit a GoDestroy event.
		o.queue.push(makeEvent(evt, curCtx, tracev2.EvGoDestroy, ev.time))
	}
	// Update the state of the next goroutine.
	nextGState.status = tracev2.GoRunning
	nextGState.seq = seq
	newCtx := curCtx
	newCtx.G = nextg

	// Queue an event for the next goroutine starting to run.
	startCtx := curCtx
	startCtx.G = NoGoroutine
	o.queue.push(makeEvent(evt, startCtx, tracev2.EvGoStart, ev.time, uint64(nextg), ev.args[1]))
	return newCtx, true, nil
}

func (o *ordering) advanceGoSyscallBegin(ev *baseEvent, evt *evTable, m ThreadID, gen uint64, curCtx schedCtx) (schedCtx, bool, error) {
	// Entering a syscall requires an active running goroutine with a
	// proc on some thread. It is always advancable.
	if err := validateCtx(curCtx, 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", o.evName(ev.typ), curCtx.G)
	}
	if state.status != tracev2.GoRunning {
		return curCtx, false, fmt.Errorf("%s event for goroutine that's not %s", o.evName(ev.typ), GoRunning)
	}
	// Goroutine entered a syscall. It's still running on this P and M.
	state.status = tracev2.GoSyscall
	pState, ok := o.pStates[curCtx.P]
	if !ok {
		return curCtx, false, fmt.Errorf("uninitialized proc %d found during %s", curCtx.P, o.evName(ev.typ))
	}
	pState.status = tracev2.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", o.evName(ev.typ), pState.seq, pSeq)
	}
	pState.seq = pSeq
	o.queue.push(Event{table: evt, ctx: curCtx, base: *ev})
	return curCtx, true, nil
}

func (o *ordering) advanceGoSyscallEnd(ev *baseEvent, evt *evTable, m ThreadID, gen uint64, curCtx schedCtx) (schedCtx, bool, error) {
	// This event is always advance-able because it happens on the same
	// thread that EvGoSyscallStart happened, and the goroutine can't leave
	// that thread until its done.
	if err := validateCtx(curCtx, 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", o.evName(ev.typ), curCtx.G)
	}
	if state.status != tracev2.GoSyscall {
		return curCtx, false, fmt.Errorf("%s event for goroutine that's not %s", o.evName(ev.typ), GoRunning)
	}
	state.status = tracev2.GoRunning

	// Transfer the P back to running from syscall.
	pState, ok := o.pStates[curCtx.P]
	if !ok {
		return curCtx, false, fmt.Errorf("uninitialized proc %d found during %s", curCtx.P, o.evName(ev.typ))
	}
	if pState.status != tracev2.ProcSyscall {
		return curCtx, false, fmt.Errorf("expected proc %d in state %v, but got %v instead", curCtx.P, tracev2.ProcSyscall, pState.status)
	}
	pState.status = tracev2.ProcRunning
	o.queue.push(Event{table: evt, ctx: curCtx, base: *ev})
	return curCtx, true, nil
}

func (o *ordering) advanceGoSyscallEndBlocked(ev *baseEvent, evt *evTable, m ThreadID, gen uint64, curCtx schedCtx) (schedCtx, bool, error) {
	// This event becomes advanceable when its P is not in a syscall state
	// (lack of a P altogether is also acceptable for advancing).
	// The transfer out of ProcSyscall can happen either voluntarily via
	// ProcStop or involuntarily via ProcSteal. We may also acquire a new P
	// before we get here (after the transfer out) but that's OK: that new
	// P won't be in the ProcSyscall state anymore.
	//
	// Basically: while we have a preemptible P, don't advance, because we
	// *know* from the event that we're going to lose it at some point during
	// the syscall. We shouldn't advance until that happens.
	if curCtx.P != NoProc {
		pState, ok := o.pStates[curCtx.P]
		if !ok {
			return curCtx, false, fmt.Errorf("uninitialized proc %d found during %s", curCtx.P, o.evName(ev.typ))
		}
		if pState.status == tracev2.ProcSyscall {
			return curCtx, false, nil
		}
	}
	// As mentioned above, we may have a P here if we ProcStart
	// before this event.
	if err := validateCtx(curCtx, schedReqs{M: mustHave, P: mayHave, G: mustHave}); 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", o.evName(ev.typ), curCtx.G)
	}
	if state.status != tracev2.GoSyscall {
		return curCtx, false, fmt.Errorf("%s event for goroutine that's not %s", o.evName(ev.typ), GoRunning)
	}
	newCtx := curCtx
	newCtx.G = NoGoroutine
	state.status = tracev2.GoRunnable
	o.queue.push(Event{table: evt, ctx: curCtx, base: *ev})
	return newCtx, true, nil
}

func (o *ordering) advanceGoCreateSyscall(ev *baseEvent, evt *evTable, m ThreadID, gen uint64, curCtx schedCtx) (schedCtx, bool, error) {
	// This event indicates that a goroutine is effectively
	// being created out of a cgo callback. Such a goroutine
	// is 'created' in the syscall state.
	if err := validateCtx(curCtx, schedReqs{M: mustHave, P: mayHave, G: mustNotHave}); err != nil {
		return curCtx, false, err
	}
	// This goroutine is effectively being created. Add a state for it.
	newgid := GoID(ev.args[0])
	if _, ok := o.gStates[newgid]; ok {
		return curCtx, false, fmt.Errorf("tried to create goroutine (%v) in syscall that already exists", newgid)
	}
	o.gStates[newgid] = &gState{id: newgid, status: tracev2.GoSyscall, seq: makeSeq(gen, 0)}
	// Goroutine is executing. Bind it to the context.
	newCtx := curCtx
	newCtx.G = newgid
	o.queue.push(Event{table: evt, ctx: curCtx, base: *ev})
	return newCtx, true, nil
}

func (o *ordering) advanceGoDestroySyscall(ev *baseEvent, evt *evTable, m ThreadID, gen uint64, curCtx schedCtx) (schedCtx, bool, error) {
	// This event indicates that a goroutine created for a
	// cgo callback is disappearing, either because the callback
	// ending or the C thread that called it is being destroyed.
	//
	// Also, treat this as if we lost our P too.
	// The thread ID may be reused by the platform and we'll get
	// really confused if we try to steal the P is this is running
	// with later. The new M with the same ID could even try to
	// steal back this P from itself!
	//
	// The runtime is careful to make sure that any GoCreateSyscall
	// event will enter the runtime emitting events for reacquiring a P.
	//
	// Note: we might have a P here. The P might not be released
	// eagerly by the runtime, and it might get stolen back later
	// (or never again, if the program is going to exit).
	if err := validateCtx(curCtx, schedReqs{M: mustHave, P: mayHave, G: mustHave}); err != nil {
		return curCtx, false, err
	}
	// Check to make sure the goroutine exists in the right state.
	state, ok := o.gStates[curCtx.G]
	if !ok {
		return curCtx, false, fmt.Errorf("event %s for goroutine (%v) that doesn't exist", o.evName(ev.typ), curCtx.G)
	}
	if state.status != tracev2.GoSyscall {
		return curCtx, false, fmt.Errorf("%s event for goroutine that's not %v", o.evName(ev.typ), GoSyscall)
	}
	// This goroutine is exiting itself.
	delete(o.gStates, curCtx.G)
	newCtx := curCtx
	newCtx.G = NoGoroutine

	// If we have a proc, then we're dissociating from it now. See the comment at the top of the case.
	if curCtx.P != NoProc {
		pState, ok := o.pStates[curCtx.P]
		if !ok {
			return curCtx, false, fmt.Errorf("found invalid proc %d during %s", curCtx.P, o.evName(ev.typ))
		}
		if pState.status != tracev2.ProcSyscall {
			return curCtx, false, fmt.Errorf("proc %d in unexpected state %s during %s", curCtx.P, pState.status, o.evName(ev.typ))
		}
		// See the go122-create-syscall-reuse-thread-id test case for more details.
		pState.status = tracev2.ProcSyscallAbandoned
		newCtx.P = NoProc

		// Queue an extra self-ProcSteal event.
		extra := makeEvent(evt, curCtx, tracev2.EvProcSteal, ev.time, uint64(curCtx.P))
		extra.base.extra(version.Go122)[0] = uint64(tracev2.ProcSyscall)
		o.queue.push(extra)
	}
	o.queue.push(Event{table: evt, ctx: curCtx, base: *ev})
	return newCtx, true, nil
}

func (o *ordering) advanceUserTaskBegin(ev *baseEvent, evt *evTable, m ThreadID, gen uint64, curCtx schedCtx) (schedCtx, bool, error) {
	// Handle tasks. Tasks are interesting because:
	// - There's no Begin event required to reference a task.
	// - End for a particular task ID can appear multiple times.
	// As a result, there's very little to validate. The only
	// thing we have to be sure of is that a task didn't begin
	// after it had already begun. Task IDs are allowed to be
	// reused, so we don't care about a Begin after an End.
	id := TaskID(ev.args[0])
	if _, ok := o.activeTasks[id]; ok {
		return curCtx, false, fmt.Errorf("task ID conflict: %d", id)
	}
	// Get the parent ID, but don't validate it. There's no guarantee
	// we actually have information on whether it's active.
	parentID := TaskID(ev.args[1])
	if parentID == BackgroundTask {
		// Note: a value of 0 here actually means no parent, *not* the
		// background task. Automatic background task attachment only
		// applies to regions.
		parentID = NoTask
		ev.args[1] = uint64(NoTask)
	}

	// Validate the name and record it. We'll need to pass it through to
	// EvUserTaskEnd.
	nameID := stringID(ev.args[2])
	name, ok := evt.strings.get(nameID)
	if !ok {
		return curCtx, false, fmt.Errorf("invalid string ID %v for %v event", nameID, ev.typ)
	}
	o.activeTasks[id] = taskState{name: name, parentID: parentID}
	if err := validateCtx(curCtx, userGoReqs); err != nil {
		return curCtx, false, err
	}
	o.queue.push(Event{table: evt, ctx: curCtx, base: *ev})
	return curCtx, true, nil
}

func (o *ordering) advanceUserTaskEnd(ev *baseEvent, evt *evTable, m ThreadID, gen uint64, curCtx schedCtx) (schedCtx, bool, error) {
	id := TaskID(ev.args[0])
	if ts, ok := o.activeTasks[id]; ok {
		// Smuggle the task info. This may happen in a different generation,
		// which may not have the name in its string table. Add it to the extra
		// strings table so we can look it up later.
		ev.extra(version.Go122)[0] = uint64(ts.parentID)
		ev.extra(version.Go122)[1] = uint64(evt.addExtraString(ts.name))
		delete(o.activeTasks, id)
	} else {
		// Explicitly clear the task info.
		ev.extra(version.Go122)[0] = uint64(NoTask)
		ev.extra(version.Go122)[1] = uint64(evt.addExtraString(""))
	}
	if err := validateCtx(curCtx, userGoReqs); err != nil {
		return curCtx, false, err
	}
	o.queue.push(Event{table: evt, ctx: curCtx, base: *ev})
	return curCtx, true, nil
}

func (o *ordering) advanceUserRegionBegin(ev *baseEvent, evt *evTable, m ThreadID, gen uint64, curCtx schedCtx) (schedCtx, bool, error) {
	if err := validateCtx(curCtx, userGoReqs); err != nil {
		return curCtx, false, err
	}
	tid := TaskID(ev.args[0])
	nameID := stringID(ev.args[1])
	name, ok := evt.strings.get(nameID)
	if !ok {
		return curCtx, false, fmt.Errorf("invalid string ID %v for %v event", nameID, ev.typ)
	}
	gState, ok := o.gStates[curCtx.G]
	if !ok {
		return curCtx, false, fmt.Errorf("encountered EvUserRegionBegin without known state for current goroutine %d", curCtx.G)
	}
	if err := gState.beginRegion(userRegion{tid, name}); err != nil {
		return curCtx, false, err
	}
	o.queue.push(Event{table: evt, ctx: curCtx, base: *ev})
	return curCtx, true, nil
}

func (o *ordering) advanceUserRegionEnd(ev *baseEvent, evt *evTable, m ThreadID, gen uint64, curCtx schedCtx) (schedCtx, bool, error) {
	if err := validateCtx(curCtx, userGoReqs); err != nil {
		return curCtx, false, err
	}
	tid := TaskID(ev.args[0])
	nameID := stringID(ev.args[1])
	name, ok := evt.strings.get(nameID)
	if !ok {
		return curCtx, false, fmt.Errorf("invalid string ID %v for %v event", nameID, ev.typ)
	}
	gState, ok := o.gStates[curCtx.G]
	if !ok {
		return curCtx, false, fmt.Errorf("encountered EvUserRegionEnd without known state for current goroutine %d", curCtx.G)
	}
	if err := gState.endRegion(userRegion{tid, name}); err != nil {
		return curCtx, false, err
	}
	o.queue.push(Event{table: evt, ctx: curCtx, base: *ev})
	return curCtx, true, nil
}

// Handle the GC mark phase.
//
// We have sequence numbers for both start and end because they
// can happen on completely different threads. We want an explicit
// partial order edge between start and end here, otherwise we're
// relying entirely on timestamps to make sure we don't advance a
// GCEnd for a _different_ GC cycle if timestamps are wildly broken.
func (o *ordering) advanceGCActive(ev *baseEvent, evt *evTable, m ThreadID, gen uint64, curCtx schedCtx) (schedCtx, bool, error) {
	seq := ev.args[0]
	if gen == o.initialGen {
		if o.gcState != gcUndetermined {
			return curCtx, false, fmt.Errorf("GCActive in the first generation isn't first GC event")
		}
		o.gcSeq = seq
		o.gcState = gcRunning
		o.queue.push(Event{table: evt, ctx: curCtx, base: *ev})
		return curCtx, true, nil
	}
	if seq != o.gcSeq+1 {
		// This is not the right GC cycle.
		return curCtx, false, nil
	}
	if o.gcState != gcRunning {
		return curCtx, false, fmt.Errorf("encountered GCActive while GC was not in progress")
	}
	o.gcSeq = seq
	if err := validateCtx(curCtx, userGoReqs); err != nil {
		return curCtx, false, err
	}
	o.queue.push(Event{table: evt, ctx: curCtx, base: *ev})
	return curCtx, true, nil
}

func (o *ordering) advanceGCBegin(ev *baseEvent, evt *evTable, m ThreadID, gen uint64, curCtx schedCtx) (schedCtx, bool, error) {
	seq := ev.args[0]
	if o.gcState == gcUndetermined {
		o.gcSeq = seq
		o.gcState = gcRunning
		o.queue.push(Event{table: evt, ctx: curCtx, base: *ev})
		return curCtx, true, nil
	}
	if seq != o.gcSeq+1 {
		// This is not the right GC cycle.
		return curCtx, false, nil
	}
	if o.gcState == gcRunning {
		return curCtx, false, fmt.Errorf("encountered GCBegin while GC was already in progress")
	}
	o.gcSeq = seq
	o.gcState = gcRunning
	if err := validateCtx(curCtx, userGoReqs); err != nil {
		return curCtx, false, err
	}
	o.queue.push(Event{table: evt, ctx: curCtx, base: *ev})
	return curCtx, true, nil
}

func (o *ordering) advanceGCEnd(ev *baseEvent, evt *evTable, m ThreadID, gen uint64, curCtx schedCtx) (schedCtx, bool, error) {
	seq := ev.args[0]
	if seq != o.gcSeq+1 {
		// This is not the right GC cycle.
		return curCtx, false, nil
	}
	if o.gcState == gcNotRunning {
		return curCtx, false, fmt.Errorf("encountered GCEnd when GC was not in progress")
	}
	if o.gcState == gcUndetermined {
		return curCtx, false, fmt.Errorf("encountered GCEnd when GC was in an undetermined state")
	}
	o.gcSeq = seq
	o.gcState = gcNotRunning
	if err := validateCtx(curCtx, userGoReqs); err != nil {
		return curCtx, false, err
	}
	o.queue.push(Event{table: evt, ctx: curCtx, base: *ev})
	return curCtx, true, nil
}

func (o *ordering) advanceAnnotation(ev *baseEvent, evt *evTable, m ThreadID, gen uint64, curCtx schedCtx) (schedCtx, bool, error) {
	// Handle simple instantaneous events that require a G.
	if err := validateCtx(curCtx, userGoReqs); err != nil {
		return curCtx, false, err
	}
	o.queue.push(Event{table: evt, ctx: curCtx, base: *ev})
	return curCtx, true, nil
}

func (o *ordering) advanceHeapMetric(ev *baseEvent, evt *evTable, m ThreadID, gen uint64, curCtx schedCtx) (schedCtx, bool, error) {
	// Handle allocation metrics, which don't require a G.
	if err := validateCtx(curCtx, schedReqs{M: mustHave, P: mustHave, G: mayHave}); err != nil {
		return curCtx, false, err
	}
	o.queue.push(Event{table: evt, ctx: curCtx, base: *ev})
	return curCtx, true, nil
}

func (o *ordering) advanceGCSweepBegin(ev *baseEvent, evt *evTable, m ThreadID, gen uint64, curCtx schedCtx) (schedCtx, bool, error) {
	// Handle sweep, which is bound to a P and doesn't require a G.
	if err := validateCtx(curCtx, schedReqs{M: mustHave, P: mustHave, G: mayHave}); err != nil {
		return curCtx, false, err
	}
	if err := o.pStates[curCtx.P].beginRange(makeRangeType(ev.typ, 0)); err != nil {
		return curCtx, false, err
	}
	o.queue.push(Event{table: evt, ctx: curCtx, base: *ev})
	return curCtx, true, nil
}

func (o *ordering) advanceGCSweepActive(ev *baseEvent, evt *evTable, m ThreadID, gen uint64, curCtx schedCtx) (schedCtx, bool, error) {
	pid := ProcID(ev.args[0])
	// N.B. In practice Ps can't block while they're sweeping, so this can only
	// ever reference curCtx.P. However, be lenient about this like we are with
	// GCMarkAssistActive; there's no reason the runtime couldn't change to block
	// in the middle of a sweep.
	pState, ok := o.pStates[pid]
	if !ok {
		return curCtx, false, fmt.Errorf("encountered GCSweepActive for unknown proc %d", pid)
	}
	if err := pState.activeRange(makeRangeType(ev.typ, 0), gen == o.initialGen); err != nil {
		return curCtx, false, err
	}
	o.queue.push(Event{table: evt, ctx: curCtx, base: *ev})
	return curCtx, true, nil
}

func (o *ordering) advanceGCSweepEnd(ev *baseEvent, evt *evTable, m ThreadID, gen uint64, curCtx schedCtx) (schedCtx, bool, error) {
	if err := validateCtx(curCtx, schedReqs{M: mustHave, P: mustHave, G: mayHave}); err != nil {
		return curCtx, false, err
	}
	_, err := o.pStates[curCtx.P].endRange(ev.typ)
	if err != nil {
		return curCtx, false, err
	}
	o.queue.push(Event{table: evt, ctx: curCtx, base: *ev})
	return curCtx, true, nil
}

func (o *ordering) advanceGoRangeBegin(ev *baseEvent, evt *evTable, m ThreadID, gen uint64, curCtx schedCtx) (schedCtx, bool, error) {
	// Handle special goroutine-bound event ranges.
	if err := validateCtx(curCtx, userGoReqs); err != nil {
		return curCtx, false, err
	}
	desc := stringID(0)
	if ev.typ == tracev2.EvSTWBegin {
		desc = stringID(ev.args[0])
	}
	gState, ok := o.gStates[curCtx.G]
	if !ok {
		return curCtx, false, fmt.Errorf("encountered event of type %d without known state for current goroutine %d", ev.typ, curCtx.G)
	}
	if err := gState.beginRange(makeRangeType(ev.typ, desc)); err != nil {
		return curCtx, false, err
	}
	o.queue.push(Event{table: evt, ctx: curCtx, base: *ev})
	return curCtx, true, nil
}

func (o *ordering) advanceGoRangeActive(ev *baseEvent, evt *evTable, m ThreadID, gen uint64, curCtx schedCtx) (schedCtx, bool, error) {
	gid := GoID(ev.args[0])
	// N.B. Like GoStatus, this can happen at any time, because it can
	// reference a non-running goroutine. Don't check anything about the
	// current scheduler context.
	gState, ok := o.gStates[gid]
	if !ok {
		return curCtx, false, fmt.Errorf("uninitialized goroutine %d found during %s", gid, o.evName(ev.typ))
	}
	if err := gState.activeRange(makeRangeType(ev.typ, 0), gen == o.initialGen); err != nil {
		return curCtx, false, err
	}
	o.queue.push(Event{table: evt, ctx: curCtx, base: *ev})
	return curCtx, true, nil
}

func (o *ordering) advanceGoRangeEnd(ev *baseEvent, evt *evTable, m ThreadID, gen uint64, curCtx schedCtx) (schedCtx, bool, error) {
	if err := validateCtx(curCtx, userGoReqs); err != nil {
		return curCtx, false, err
	}
	gState, ok := o.gStates[curCtx.G]
	if !ok {
		return curCtx, false, fmt.Errorf("encountered event of type %d without known state for current goroutine %d", ev.typ, curCtx.G)
	}
	desc, err := gState.endRange(ev.typ)
	if err != nil {
		return curCtx, false, err
	}
	if ev.typ == tracev2.EvSTWEnd {
		// Smuggle the kind into the event.
		// Don't use ev.extra here so we have symmetry with STWBegin.
		ev.args[0] = uint64(desc)
	}
	o.queue.push(Event{table: evt, ctx: curCtx, base: *ev})
	return curCtx, true, nil
}

func (o *ordering) advanceAllocFree(ev *baseEvent, evt *evTable, m ThreadID, gen uint64, curCtx schedCtx) (schedCtx, bool, error) {
	// Handle simple instantaneous events that may or may not have a P.
	if err := validateCtx(curCtx, schedReqs{M: mustHave, P: mayHave, G: mayHave}); err != nil {
		return curCtx, false, err
	}
	o.queue.push(Event{table: evt, ctx: curCtx, base: *ev})
	return curCtx, true, nil
}

// Next returns the next event in the ordering.
func (o *ordering) Next() (Event, bool) {
	return o.queue.pop()
}

// schedCtx represents the scheduling resources associated with an event.
type schedCtx struct {
	G GoID
	P ProcID
	M ThreadID
}

// validateCtx ensures that ctx conforms to some reqs, returning an error if
// it doesn't.
func validateCtx(ctx schedCtx, reqs schedReqs) error {
	// Check thread requirements.
	if reqs.M == mustHave && ctx.M == NoThread {
		return fmt.Errorf("expected a thread but didn't have one")
	} else if reqs.M == mustNotHave && ctx.M != NoThread {
		return fmt.Errorf("expected no thread but had one")
	}

	// Check proc requirements.
	if reqs.P == mustHave && ctx.P == NoProc {
		return fmt.Errorf("expected a proc but didn't have one")
	} else if reqs.P == mustNotHave && ctx.P != NoProc {
		return fmt.Errorf("expected no proc but had one")
	}

	// Check goroutine requirements.
	if reqs.G == mustHave && ctx.G == NoGoroutine {
		return fmt.Errorf("expected a goroutine but didn't have one")
	} else if reqs.G == mustNotHave && ctx.G != NoGoroutine {
		return fmt.Errorf("expected no goroutine but had one")
	}
	return nil
}

// gcState is a trinary variable for the current state of the GC.
//
// The third state besides "enabled" and "disabled" is "undetermined."
type gcState uint8

const (
	gcUndetermined gcState = iota
	gcNotRunning
	gcRunning
)

// String returns a human-readable string for the GC state.
func (s gcState) String() string {
	switch s {
	case gcUndetermined:
		return "Undetermined"
	case gcNotRunning:
		return "NotRunning"
	case gcRunning:
		return "Running"
	}
	return "Bad"
}

// userRegion represents a unique user region when attached to some gState.
type userRegion struct {
	// name must be a resolved string because the string ID for the same
	// string may change across generations, but we care about checking
	// the value itself.
	taskID TaskID
	name   string
}

// rangeType is a way to classify special ranges of time.
//
// These typically correspond 1:1 with "Begin" events, but
// they may have an optional subtype that describes the range
// in more detail.
type rangeType struct {
	typ  tracev2.EventType // "Begin" event.
	desc stringID          // Optional subtype.
}

// makeRangeType constructs a new rangeType.
func makeRangeType(typ tracev2.EventType, desc stringID) rangeType {
	if styp := tracev2.Specs()[typ].StartEv; styp != tracev2.EvNone {
		typ = styp
	}
	return rangeType{typ, desc}
}

// gState is the state of a goroutine at a point in the trace.
type gState struct {
	id     GoID
	status tracev2.GoStatus
	seq    seqCounter

	// regions are the active user regions for this goroutine.
	regions []userRegion

	// rangeState is the state of special time ranges bound to this goroutine.
	rangeState
}

// beginRegion starts a user region on the goroutine.
func (s *gState) beginRegion(r userRegion) error {
	s.regions = append(s.regions, r)
	return nil
}

// endRegion ends a user region on the goroutine.
func (s *gState) endRegion(r userRegion) error {
	if len(s.regions) == 0 {
		// We do not know about regions that began before tracing started.
		return nil
	}
	if next := s.regions[len(s.regions)-1]; next != r {
		return fmt.Errorf("misuse of region in goroutine %v: region end %v when the inner-most active region start event is %v", s.id, r, next)
	}
	s.regions = s.regions[:len(s.regions)-1]
	return nil
}

// pState is the state of a proc at a point in the trace.
type pState struct {
	id     ProcID
	status tracev2.ProcStatus
	seq    seqCounter

	// rangeState is the state of special time ranges bound to this proc.
	rangeState
}

// mState is the state of a thread at a point in the trace.
type mState struct {
	g GoID   // Goroutine bound to this M. (The goroutine's state is Executing.)
	p ProcID // Proc bound to this M. (The proc's state is Executing.)
}

// rangeState represents the state of special time ranges.
type rangeState struct {
	// inFlight contains the rangeTypes of any ranges bound to a resource.
	inFlight []rangeType
}

// beginRange begins a special range in time on the goroutine.
//
// Returns an error if the range is already in progress.
func (s *rangeState) beginRange(typ rangeType) error {
	if s.hasRange(typ) {
		return fmt.Errorf("discovered event already in-flight for when starting event %v", tracev2.Specs()[typ.typ].Name)
	}
	s.inFlight = append(s.inFlight, typ)
	return nil
}

// activeRange marks special range in time on the goroutine as active in the
// initial generation, or confirms that it is indeed active in later generations.
func (s *rangeState) activeRange(typ rangeType, isInitialGen bool) error {
	if isInitialGen {
		if s.hasRange(typ) {
			return fmt.Errorf("found named active range already in first gen: %v", typ)
		}
		s.inFlight = append(s.inFlight, typ)
	} else if !s.hasRange(typ) {
		return fmt.Errorf("resource is missing active range: %v %v", tracev2.Specs()[typ.typ].Name, s.inFlight)
	}
	return nil
}

// hasRange returns true if a special time range on the goroutine as in progress.
func (s *rangeState) hasRange(typ rangeType) bool {
	return slices.Contains(s.inFlight, typ)
}

// endRange ends a special range in time on the goroutine.
//
// This must line up with the start event type  of the range the goroutine is currently in.
func (s *rangeState) endRange(typ tracev2.EventType) (stringID, error) {
	st := tracev2.Specs()[typ].StartEv
	idx := -1
	for i, r := range s.inFlight {
		if r.typ == st {
			idx = i
			break
		}
	}
	if idx < 0 {
		return 0, fmt.Errorf("tried to end event %v, but not in-flight", tracev2.Specs()[st].Name)
	}
	// Swap remove.
	desc := s.inFlight[idx].desc
	s.inFlight[idx], s.inFlight[len(s.inFlight)-1] = s.inFlight[len(s.inFlight)-1], s.inFlight[idx]
	s.inFlight = s.inFlight[:len(s.inFlight)-1]
	return desc, nil
}

// seqCounter represents a global sequence counter for a resource.
type seqCounter struct {
	gen uint64 // The generation for the local sequence counter seq.
	seq uint64 // The sequence number local to the generation.
}

// makeSeq creates a new seqCounter.
func makeSeq(gen, seq uint64) seqCounter {
	return seqCounter{gen: gen, seq: seq}
}

// succeeds returns true if a is the immediate successor of b.
func (a seqCounter) succeeds(b seqCounter) bool {
	return a.gen == b.gen && a.seq == b.seq+1
}

// String returns a debug string representation of the seqCounter.
func (c seqCounter) String() string {
	return fmt.Sprintf("%d (gen=%d)", c.seq, c.gen)
}

func dumpOrdering(order *ordering) string {
	var sb strings.Builder
	for id, state := range order.gStates {
		fmt.Fprintf(&sb, "G %d [status=%s seq=%s]\n", id, state.status, state.seq)
	}
	fmt.Fprintln(&sb)
	for id, state := range order.pStates {
		fmt.Fprintf(&sb, "P %d [status=%s seq=%s]\n", id, state.status, state.seq)
	}
	fmt.Fprintln(&sb)
	for id, state := range order.mStates {
		fmt.Fprintf(&sb, "M %d [g=%d p=%d]\n", id, state.g, state.p)
	}
	fmt.Fprintln(&sb)
	fmt.Fprintf(&sb, "GC %d %s\n", order.gcSeq, order.gcState)
	return sb.String()
}

// taskState represents an active task.
type taskState struct {
	// name is the type of the active task.
	name string

	// parentID is the parent ID of the active task.
	parentID TaskID
}

// queue implements a growable ring buffer with a queue API.
type queue[T any] struct {
	start, end int
	buf        []T
}

// push adds a new event to the back of the queue.
func (q *queue[T]) push(value T) {
	if q.end-q.start == len(q.buf) {
		q.grow()
	}
	q.buf[q.end%len(q.buf)] = value
	q.end++
}

// grow increases the size of the queue.
func (q *queue[T]) grow() {
	if len(q.buf) == 0 {
		q.buf = make([]T, 2)
		return
	}

	// Create new buf and copy data over.
	newBuf := make([]T, len(q.buf)*2)
	pivot := q.start % len(q.buf)
	first, last := q.buf[pivot:], q.buf[:pivot]
	copy(newBuf[:len(first)], first)
	copy(newBuf[len(first):], last)

	// Update the queue state.
	q.start = 0
	q.end = len(q.buf)
	q.buf = newBuf
}

// pop removes an event from the front of the queue. If the
// queue is empty, it returns an EventBad event.
func (q *queue[T]) pop() (T, bool) {
	if q.end-q.start == 0 {
		return *new(T), false
	}
	elem := &q.buf[q.start%len(q.buf)]
	value := *elem
	*elem = *new(T) // Clear the entry before returning, so we don't hold onto old tables.
	q.start++
	return value, true
}

// makeEvent creates an Event from the provided information.
//
// It's just a convenience function; it's always OK to construct
// an Event manually if this isn't quite the right way to express
// the contents of the event.
func makeEvent(table *evTable, ctx schedCtx, typ tracev2.EventType, time Time, args ...uint64) Event {
	ev := Event{
		table: table,
		ctx:   ctx,
		base: baseEvent{
			typ:  typ,
			time: time,
		},
	}
	copy(ev.base.args[:], args)
	return ev
}

// schedReqs is a set of constraints on what the scheduling
// context must look like.
type schedReqs struct {
	M constraint
	P constraint
	G constraint
}

// constraint represents a various presence requirements.
type constraint uint8

const (
	mustNotHave constraint = iota
	mayHave
	mustHave
)

// userGoReqs is a common requirement among events that are running
// or are close to running user code.
var userGoReqs = schedReqs{M: mustHave, P: mustHave, G: mustHave}
