// 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.

// Trace goroutine and P status management.

package runtime

import "internal/runtime/atomic"

// traceGoStatus is the status of a goroutine.
//
// They correspond directly to the various goroutine
// statuses.
type traceGoStatus uint8

const (
	traceGoBad traceGoStatus = iota
	traceGoRunnable
	traceGoRunning
	traceGoSyscall
	traceGoWaiting
)

// traceProcStatus is the status of a P.
//
// They mostly correspond to the various P statuses.
type traceProcStatus uint8

const (
	traceProcBad traceProcStatus = iota
	traceProcRunning
	traceProcIdle
	traceProcSyscall

	// traceProcSyscallAbandoned is a special case of
	// traceProcSyscall. It's used in the very specific case
	// where the first a P is mentioned in a generation is
	// part of a ProcSteal event. If that's the first time
	// it's mentioned, then there's no GoSyscallBegin to
	// connect the P stealing back to at that point. This
	// special state indicates this to the parser, so it
	// doesn't try to find a GoSyscallEndBlocked that
	// corresponds with the ProcSteal.
	traceProcSyscallAbandoned
)

// writeGoStatus emits a GoStatus event as well as any active ranges on the goroutine.
func (w traceWriter) writeGoStatus(goid uint64, mid int64, status traceGoStatus, markAssist bool, stackID uint64) traceWriter {
	// The status should never be bad. Some invariant must have been violated.
	if status == traceGoBad {
		print("runtime: goid=", goid, "\n")
		throw("attempted to trace a bad status for a goroutine")
	}

	// Trace the status.
	if stackID == 0 {
		w = w.event(traceEvGoStatus, traceArg(goid), traceArg(uint64(mid)), traceArg(status))
	} else {
		w = w.event(traceEvGoStatusStack, traceArg(goid), traceArg(uint64(mid)), traceArg(status), traceArg(stackID))
	}

	// Trace any special ranges that are in-progress.
	if markAssist {
		w = w.event(traceEvGCMarkAssistActive, traceArg(goid))
	}
	return w
}

// writeProcStatusForP emits a ProcStatus event for the provided p based on its status.
//
// The caller must fully own pp and it must be prevented from transitioning (e.g. this can be
// called by a forEachP callback or from a STW).
func (w traceWriter) writeProcStatusForP(pp *p, inSTW bool) traceWriter {
	if !pp.trace.acquireStatus(w.gen) {
		return w
	}
	var status traceProcStatus
	switch pp.status {
	case _Pidle, _Pgcstop:
		status = traceProcIdle
		if pp.status == _Pgcstop && inSTW {
			// N.B. a P that is running and currently has the world stopped will be
			// in _Pgcstop, but we model it as running in the tracer.
			status = traceProcRunning
		}
	case _Prunning:
		status = traceProcRunning
		// There's a short window wherein the goroutine may have entered _Gsyscall
		// but it still owns the P (it's not in _Psyscall yet). The goroutine entering
		// _Gsyscall is the tracer's signal that the P its bound to is also in a syscall,
		// so we need to emit a status that matches. See #64318.
		if w.mp.p.ptr() == pp && w.mp.curg != nil && readgstatus(w.mp.curg)&^_Gscan == _Gsyscall {
			status = traceProcSyscall
		}
	case _Psyscall:
		status = traceProcSyscall
	default:
		throw("attempt to trace invalid or unsupported P status")
	}
	w = w.writeProcStatus(uint64(pp.id), status, pp.trace.inSweep)
	return w
}

// writeProcStatus emits a ProcStatus event with all the provided information.
//
// The caller must have taken ownership of a P's status writing, and the P must be
// prevented from transitioning.
func (w traceWriter) writeProcStatus(pid uint64, status traceProcStatus, inSweep bool) traceWriter {
	// The status should never be bad. Some invariant must have been violated.
	if status == traceProcBad {
		print("runtime: pid=", pid, "\n")
		throw("attempted to trace a bad status for a proc")
	}

	// Trace the status.
	w = w.event(traceEvProcStatus, traceArg(pid), traceArg(status))

	// Trace any special ranges that are in-progress.
	if inSweep {
		w = w.event(traceEvGCSweepActive, traceArg(pid))
	}
	return w
}

// goStatusToTraceGoStatus translates the internal status to tracGoStatus.
//
// status must not be _Gdead or any status whose name has the suffix "_unused."
func goStatusToTraceGoStatus(status uint32, wr waitReason) traceGoStatus {
	// N.B. Ignore the _Gscan bit. We don't model it in the tracer.
	var tgs traceGoStatus
	switch status &^ _Gscan {
	case _Grunnable:
		tgs = traceGoRunnable
	case _Grunning, _Gcopystack:
		tgs = traceGoRunning
	case _Gsyscall:
		tgs = traceGoSyscall
	case _Gwaiting, _Gpreempted:
		// There are a number of cases where a G might end up in
		// _Gwaiting but it's actually running in a non-preemptive
		// state but needs to present itself as preempted to the
		// garbage collector. In these cases, we're not going to
		// emit an event, and we want these goroutines to appear in
		// the final trace as if they're running, not blocked.
		tgs = traceGoWaiting
		if status == _Gwaiting && wr.isWaitingForGC() {
			tgs = traceGoRunning
		}
	case _Gdead:
		throw("tried to trace dead goroutine")
	default:
		throw("tried to trace goroutine with invalid or unsupported status")
	}
	return tgs
}

// traceSchedResourceState is shared state for scheduling resources (i.e. fields common to
// both Gs and Ps).
type traceSchedResourceState struct {
	// statusTraced indicates whether a status event was traced for this resource
	// a particular generation.
	//
	// There are 3 of these because when transitioning across generations, traceAdvance
	// needs to be able to reliably observe whether a status was traced for the previous
	// generation, while we need to clear the value for the next generation.
	statusTraced [3]atomic.Uint32

	// seq is the sequence counter for this scheduling resource's events.
	// The purpose of the sequence counter is to establish a partial order between
	// events that don't obviously happen serially (same M) in the stream ofevents.
	//
	// There are two of these so that we can reset the counter on each generation.
	// This saves space in the resulting trace by keeping the counter small and allows
	// GoStatus and GoCreate events to omit a sequence number (implicitly 0).
	seq [2]uint64
}

// acquireStatus acquires the right to emit a Status event for the scheduling resource.
func (r *traceSchedResourceState) acquireStatus(gen uintptr) bool {
	if !r.statusTraced[gen%3].CompareAndSwap(0, 1) {
		return false
	}
	r.readyNextGen(gen)
	return true
}

// readyNextGen readies r for the generation following gen.
func (r *traceSchedResourceState) readyNextGen(gen uintptr) {
	nextGen := traceNextGen(gen)
	r.seq[nextGen%2] = 0
	r.statusTraced[nextGen%3].Store(0)
}

// statusWasTraced returns true if the sched resource's status was already acquired for tracing.
func (r *traceSchedResourceState) statusWasTraced(gen uintptr) bool {
	return r.statusTraced[gen%3].Load() != 0
}

// setStatusTraced indicates that the resource's status was already traced, for example
// when a goroutine is created.
func (r *traceSchedResourceState) setStatusTraced(gen uintptr) {
	r.statusTraced[gen%3].Store(1)
}

// nextSeq returns the next sequence number for the resource.
func (r *traceSchedResourceState) nextSeq(gen uintptr) traceArg {
	r.seq[gen%2]++
	return traceArg(r.seq[gen%2])
}
