Source File
resources.go
Belonging Package
internal/trace
// 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
// ThreadID is the runtime-internal M structure's ID. This is unique
// for each OS thread.
type ThreadID int64
// NoThread indicates that the relevant events don't correspond to any
// thread in particular.
const NoThread = ThreadID(-1)
// ProcID is the runtime-internal G structure's id field. This is unique
// for each P.
type ProcID int64
// NoProc indicates that the relevant events don't correspond to any
// P in particular.
const NoProc = ProcID(-1)
// GoID is the runtime-internal G structure's goid field. This is unique
// for each goroutine.
type GoID int64
// NoGoroutine indicates that the relevant events don't correspond to any
// goroutine in particular.
const NoGoroutine = GoID(-1)
// GoState represents the state of a goroutine.
//
// New GoStates may be added in the future. Users of this type must be robust
// to that possibility.
type GoState uint8
const (
GoUndetermined GoState = iota // No information is known about the goroutine.
GoNotExist // Goroutine does not exist.
GoRunnable // Goroutine is runnable but not running.
GoRunning // Goroutine is running.
GoWaiting // Goroutine is waiting on something to happen.
GoSyscall // Goroutine is in a system call.
)
// Executing returns true if the state indicates that the goroutine is executing
// and bound to its thread.
func ( GoState) () bool {
return == GoRunning || == GoSyscall
}
// String returns a human-readable representation of a GoState.
//
// The format of the returned string is for debugging purposes and is subject to change.
func ( GoState) () string {
switch {
case GoUndetermined:
return "Undetermined"
case GoNotExist:
return "NotExist"
case GoRunnable:
return "Runnable"
case GoRunning:
return "Running"
case GoWaiting:
return "Waiting"
case GoSyscall:
return "Syscall"
}
return "Bad"
}
// ProcState represents the state of a proc.
//
// New ProcStates may be added in the future. Users of this type must be robust
// to that possibility.
type ProcState uint8
const (
ProcUndetermined ProcState = iota // No information is known about the proc.
ProcNotExist // Proc does not exist.
ProcRunning // Proc is running.
ProcIdle // Proc is idle.
)
// Executing returns true if the state indicates that the proc is executing
// and bound to its thread.
func ( ProcState) () bool {
return == ProcRunning
}
// String returns a human-readable representation of a ProcState.
//
// The format of the returned string is for debugging purposes and is subject to change.
func ( ProcState) () string {
switch {
case ProcUndetermined:
return "Undetermined"
case ProcNotExist:
return "NotExist"
case ProcRunning:
return "Running"
case ProcIdle:
return "Idle"
}
return "Bad"
}
// ResourceKind indicates a kind of resource that has a state machine.
//
// New ResourceKinds may be added in the future. Users of this type must be robust
// to that possibility.
type ResourceKind uint8
const (
ResourceNone ResourceKind = iota // No resource.
ResourceGoroutine // Goroutine.
ResourceProc // Proc.
ResourceThread // Thread.
)
// String returns a human-readable representation of a ResourceKind.
//
// The format of the returned string is for debugging purposes and is subject to change.
func ( ResourceKind) () string {
switch {
case ResourceNone:
return "None"
case ResourceGoroutine:
return "Goroutine"
case ResourceProc:
return "Proc"
case ResourceThread:
return "Thread"
}
return "Bad"
}
// ResourceID represents a generic resource ID.
type ResourceID struct {
// Kind is the kind of resource this ID is for.
Kind ResourceKind
id int64
}
// MakeResourceID creates a general resource ID from a specific resource's ID.
func [ interface{ GoID | ProcID | ThreadID }]( ) ResourceID {
var ResourceID
var any =
switch .(type) {
case GoID:
.Kind = ResourceGoroutine
case ProcID:
.Kind = ResourceProc
case ThreadID:
.Kind = ResourceThread
}
.id = int64()
return
}
// Goroutine obtains a GoID from the resource ID.
//
// r.Kind must be ResourceGoroutine or this function will panic.
func ( ResourceID) () GoID {
if .Kind != ResourceGoroutine {
panic(fmt.Sprintf("attempted to get GoID from %s resource ID", .Kind))
}
return GoID(.id)
}
// Proc obtains a ProcID from the resource ID.
//
// r.Kind must be ResourceProc or this function will panic.
func ( ResourceID) () ProcID {
if .Kind != ResourceProc {
panic(fmt.Sprintf("attempted to get ProcID from %s resource ID", .Kind))
}
return ProcID(.id)
}
// Thread obtains a ThreadID from the resource ID.
//
// r.Kind must be ResourceThread or this function will panic.
func ( ResourceID) () ThreadID {
if .Kind != ResourceThread {
panic(fmt.Sprintf("attempted to get ThreadID from %s resource ID", .Kind))
}
return ThreadID(.id)
}
// String returns a human-readable string representation of the ResourceID.
//
// This representation is subject to change and is intended primarily for debugging.
func ( ResourceID) () string {
if .Kind == ResourceNone {
return .Kind.String()
}
return fmt.Sprintf("%s(%d)", .Kind, .id)
}
// StateTransition provides details about a StateTransition event.
type StateTransition struct {
// Resource is the resource this state transition is for.
Resource ResourceID
// Reason is a human-readable reason for the state transition.
Reason string
// Stack is the stack trace of the resource making the state transition.
//
// This is distinct from the result (Event).Stack because it pertains to
// the transitioning resource, not any of the ones executing the event
// this StateTransition came from.
//
// An example of this difference is the NotExist -> Runnable transition for
// goroutines, which indicates goroutine creation. In this particular case,
// a Stack here would refer to the starting stack of the new goroutine, and
// an (Event).Stack would refer to the stack trace of whoever created the
// goroutine.
Stack Stack
// The actual transition data. Stored in a neutral form so that
// we don't need fields for every kind of resource.
id int64
oldState uint8
newState uint8
}
func goStateTransition( GoID, , GoState) StateTransition {
return StateTransition{
Resource: ResourceID{Kind: ResourceGoroutine, id: int64()},
oldState: uint8(),
newState: uint8(),
}
}
func procStateTransition( ProcID, , ProcState) StateTransition {
return StateTransition{
Resource: ResourceID{Kind: ResourceProc, id: int64()},
oldState: uint8(),
newState: uint8(),
}
}
// Goroutine returns the state transition for a goroutine.
//
// Transitions to and from states that are Executing are special in that
// they change the future execution context. In other words, future events
// on the same thread will feature the same goroutine until it stops running.
//
// Panics if d.Resource.Kind is not ResourceGoroutine.
func ( StateTransition) () (, GoState) {
if .Resource.Kind != ResourceGoroutine {
panic("Goroutine called on non-Goroutine state transition")
}
return GoState(.oldState), GoState(.newState)
}
// Proc returns the state transition for a proc.
//
// Transitions to and from states that are Executing are special in that
// they change the future execution context. In other words, future events
// on the same thread will feature the same goroutine until it stops running.
//
// Panics if d.Resource.Kind is not ResourceProc.
func ( StateTransition) () (, ProcState) {
if .Resource.Kind != ResourceProc {
panic("Proc called on non-Proc state transition")
}
return ProcState(.oldState), ProcState(.newState)
}
The pages are generated with Golds v0.7.0-preview. (GOOS=linux GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds. |