stdgo

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 7, 2023 License: Apache-2.0 Imports: 6 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Block

func Block()

func CloseChan

func CloseChan(c *hchan)

func MakeChan

func MakeChan(chanType *abi.ChanType, sz int) *hchan

func Recover

func Recover(argp uintptr) any

func Recv

func Recv(c *hchan, ep unsafe.Pointer, block bool) (selected, received bool)

Recv receives on channel c and writes the received data to ep.

ep may be nil, in which case received data is ignored.

If block == false and no elements are available, returns (false, false). Otherwise, if c is closed, zeros *ep and returns (true, false). Otherwise, fills in *ep with an element and returns (true, true). A non-nil ep must point to the heap or the caller's stack.

func Sched

func Sched(guarded bool)

Gosched yields the processor, allowing other goroutines to run. It does not suspend the current goroutine, so execution resumes automatically.

If guarded is true, also checks for forbidden states and opts out of the yield in those cases.

func Select

func Select(cas0 *SelectCase, order0 *uint16, pc0 *uintptr, nsends, nrecvs int, block bool) (int, bool)

Select implements the select statement.

cas0 points to an array of type [ncases]scase, and order0 points to an array of type [2*ncases]uint16 where ncases must be <= 65536. Both reside on the goroutine's stack (regardless of any escaping in Select).

For race detector builds, pc0 points to an array of type [ncases]uintptr (also on the stack); for other builds, it's set to nil.

Select returns the index of the chosen scase, which matches the ordinal position of its respective select{recv,send,default} call. Also, if the chosen scase was a receive operation, it reports whether a value was received.

func Send

func Send(c *hchan, elem unsafe.Pointer, block bool, callerpc uintptr) bool

generic single channel send

If block is not nil, then the protocol will not sleep but return if it could not complete.

sleep can wake up with g.param == nil when a channel involved in the sleep has been closed. it is easiest to loop and re-run the operation; we'll see that it's now closed.

Types

type Chan

type Chan struct {
	Qcount    uint           // total data in the queue
	DataqSize uint           // size of the circular queue
	Buf       unsafe.Pointer // points to an array of dataqsiz elements
	ElemSize  uint16
	Closed    uint32
	ElemType  *abi.Type // element type
	Sendx     uint      // send index
	Recvx     uint      // receive index

	// Lock protects all fields in hchan, as well as several
	// fields in sudogs blocked on this channel.
	//
	// Do not change another G's status while holding this Lock
	// (in particular, do not ready a G), as this can deadlock
	// with stack shrinking.
	Lock Mutex
	// contains filtered or unexported fields
}

type Defer

type Defer struct {
	Started bool
	Heap    bool
	// OpenDefer indicates that this _defer is for a frame with open-coded
	// defers. We have only one defer record for the entire frame (which may
	// currently have 0, 1, or more defers active).
	OpenDefer bool
	SP        uintptr // sp at time of defer
	PC        uintptr // pc at time of defer
	Fn        func()  // can be nil for open-coded defers
	Panic     *Panic  // panic that is running defer
	Link      *Defer  // next defer on G; can point to either heap or stack!

	// If openDefer is true, the fields below record values about the stack
	// frame and associated function that has the open-coded defer(s). sp
	// above will be the sp for the frame, and pc will be address of the
	// deferreturn call in the function.
	FuncData unsafe.Pointer // funcdata for the function associated with the frame
	Varp     uintptr        // value of varp for the stack frame
	// FramePC is the current pc associated with the stack frame. Together,
	// with sp above (which is the sp associated with the stack frame),
	// FramePC/sp can be used as pc/sp pair to continue a stack trace via
	// gentraceback().
	FramePC uintptr
}

A Defer holds an entry on the list of deferred calls. If you add a field here, add code to clear it in deferProcStack. This struct must match the code in cmd/compile/internal/ssagen/ssa.go:deferstruct and cmd/compile/internal/ssagen/ssa.go:(*state).call. Some defers will be allocated on the stack and some on the heap. All defers are logically part of the stack, so write barriers to initialize them are not required. All defers must be manually scanned, and for heap defers, marked.

See $GOROOT/src/runtime/runtime2.go#type:_defer

type G

type G interface {
	ID() uint64
	Rand32() uint32
	Rand64() uint64

	// Status returns the status of this goroutine.
	Status() Status

	// DefaultAlloc returns the default allocator in this goroutine.
	DefaultAlloc() alloc.M

	// PersistantAlloc returns the persistant allocator in this goroutine.
	PersistantAlloc() alloc.P
}

G defines required methods for a goroutine implementation.

type GHead

type GHead struct {
	// Stack parameters.
	//
	// Stack describes the actual Stack memory: [Stack.lo, Stack.hi).
	// stackguard0 is the Stack pointer compared in the Go Stack growth prologue.
	// It is Stack.lo+StackGuard normally, but can be StackPreempt to trigger a preemption.
	// stackguard1 is the Stack pointer compared in the C Stack growth prologue.
	// It is Stack.lo+StackGuard on g0 and gsignal stacks.
	// It is ~0 on other goroutine stacks, to trigger a call to morestackc (and crash).
	Stack       Stack   // offset known to runtime/cgo
	Stackguard0 uintptr // offset known to liblink
	Stackguard1 uintptr // offset known to liblink

	Panic      *Panic         // innermost panic - offset known to liblink
	Defer      *Defer         // innermost defer
	M          unsafe.Pointer // current m; offset known to arm liblink
	Sched      Gobuf
	SyscallSP  uintptr // if status==Gsyscall, syscallsp = Sched.sp to use during gc
	SyscallPC  uintptr // if status==Gsyscall, syscallpc = Sched.pc to use during gc
	StacktopSP uintptr // expected sp at top of stack, to check in traceback

	ID_ uint64

	// Itab for the G interface value.
	Itab *abi.Itab
}

GHead contains required per-G data.

See ${GOROOT}/src/runtime/runtime2.go#type:g

NOTE:

  • unsafe.Offsetof(T.GHead.Stack) MUST be 0.
  • (dev) MUST be kept as non-generic struct type.

func (*GHead) G

func (gp *GHead) G() G

G returns the G implementation

func (*GHead) Guintptr

func (gp *GHead) Guintptr() Guintptr

func (*GHead) ID

func (gp *GHead) ID() uint64

type Gobuf

type Gobuf struct {
	// The offsets of SP, PC, and G are known to (hard-coded in) libmach.
	//
	// Ctxt is unusual with respect to GC: it may be a
	// heap-allocated funcval, so GC needs to track it, but it
	// needs to be set and cleared from assembly, where it's
	// difficult to have write barriers. However, ctxt is really a
	// saved, live register, and we only ever exchange it between
	// the real register and the gobuf. Hence, we treat it as a
	// root during stack scanning, which means assembly that saves
	// and restores it doesn't need write barriers. It's still
	// typed as a pointer so that any other writes from Go get
	// write barriers.
	SP   uintptr
	PC   uintptr
	G    Guintptr
	Ctxt unsafe.Pointer
	Ret  uintptr
	LR   uintptr
	BP   uintptr // for framepointer-enabled architectures
}

See ${GOROOT}/src/runtime/runtime2.go#type:gobuf

type Guintptr

type Guintptr uintptr

A Guintptr holds a goroutine pointer, but typed as a uintptr to bypass write barriers. It is used in the Gobuf goroutine state and in scheduling lists that are manipulated without a P.

The Gobuf.G goroutine pointer is almost always updated by assembly code. In one of the few places it is updated by Go code - func save - it must be treated as a uintptr to avoid a write barrier being emitted at a bad time. Instead of figuring out how to emit the write barriers missing in the assembly manipulation, we change the type of the field to uintptr, so that it does not require write barriers at all.

Goroutine structs are published in the allg list and never freed. That will keep the goroutine structs from being collected. There is never a time that Gobuf.g's contain the only references to a goroutine: the publishing of the goroutine in allg comes first. Goroutine pointers are also kept in non-GC-visible places like TLS, so I can't see them ever moving. If we did want to start moving data in the GC, we'd need to allocate the goroutine structs from an alternate arena. Using Guintptr doesn't make that problem any worse. Note that pollDesc.rg, pollDesc.wg also store g in uintptr form, so they would need to be updated too if g's start moving.

func (Guintptr) Ptr

func (gp Guintptr) Ptr() *GHead

func (*Guintptr) Set

func (gp *Guintptr) Set(g *GHead)

type Mutex

type Mutex struct {
	// contains filtered or unexported fields
}

Mutual exclusion locks. In the uncontended case, as fast as spin locks (just a few user-level instructions), but on the contention path they sleep in the kernel. A zeroed Mutex is unlocked (no need to initialize each lock). Initialization is helpful for static lock ranking, but not required.

type Panic

type Panic struct {
	Argp      unsafe.Pointer // pointer to arguments of deferred call run during panic; cannot move - known to liblink
	Arg       any            // argument to panic
	Link      *Panic         // link to earlier panic
	PC        uintptr        // where to return to in runtime if this panic is bypassed
	SP        unsafe.Pointer // where to return to in runtime if this panic is bypassed
	Recovered bool           // whether this panic is over
	Aborted   bool           // the panic was aborted
	Goexit    bool
}

A Panic holds information about an active panic.

A Panic value must only ever live on the stack.

The argp and link fields are stack pointers, but don't need special handling during stack growth: because they are pointer-typed and Panic values only live on the stack, regular stack pointer adjustment takes care of them.

see $GOROOT/src/runtime/runtime2.go#type:_panic

type SelectCase

type SelectCase struct {
	C    *hchan         // chan
	Elem unsafe.Pointer // data element
}

Select case descriptor. Known to compiler. Changes here must also be made in src/cmd/compile/internal/walk/select.go's scasetype.

type Stack

type Stack struct {
	Lo uintptr
	Hi uintptr
}

Stack describes a Go execution Stack. The bounds of the Stack are exactly [lo, hi), with no implicit data structures on either side.

func (Stack) PointerOnStack added in v0.2.0

func (stk Stack) PointerOnStack(ptr uintptr) bool

type Status

type Status = uint32

G status

Beyond indicating the general state of a G, the G status acts like a lock on the goroutine's stack (and hence its ability to execute user code).

If you add to this list, add to the list of "okay during garbage collection" status in mgcmark.go too.

TODO(austin): The StatusGscan bit could be much lighter-weight. For example, we could choose not to run StatusGscanrunnable goroutines found in the run queue, rather than CAS-looping until they become StatusGrunnable. And transitions like StatusGscanwaiting -> StatusGscanrunnable are actually okay because they don't affect stack ownership.

const (
	// StatusGidle means this goroutine was just allocated and has not
	// yet been initialized.
	StatusGidle Status = iota // 0

	// StatusGrunnable means this goroutine is on a run queue. It is
	// not currently executing user code. The stack is not owned.
	StatusGrunnable // 1

	// StatusGrunning means this goroutine may execute user code. The
	// stack is owned by this goroutine. It is not on a run queue.
	// It is assigned an M and a P (g.m and g.m.p are valid).
	StatusGrunning // 2

	// StatusGsyscall means this goroutine is executing a system call.
	// It is not executing user code. The stack is owned by this
	// goroutine. It is not on a run queue. It is assigned an M.
	StatusGsyscall // 3

	// StatusGwaiting means this goroutine is blocked in the runtime.
	// It is not executing user code. It is not on a run queue,
	// but should be recorded somewhere (e.g., a channel wait
	// queue) so it can be ready()d when necessary. The stack is
	// not owned *except* that a channel operation may read or
	// write parts of the stack under the appropriate channel
	// lock. Otherwise, it is not safe to access the stack after a
	// goroutine enters StatusGwaiting (e.g., it may get moved).
	StatusGwaiting // 4

	// StatusGmoribund_unused is currently unused, but hardcoded in gdb
	// scripts.
	StatusGmoribund_unused // 5

	// StatusGdead means this goroutine is currently unused. It may be
	// just exited, on a free list, or just being initialized. It
	// is not executing user code. It may or may not have a stack
	// allocated. The G and its stack (if any) are owned by the M
	// that is exiting the G or that obtained the G from the free
	// list.
	StatusGdead // 6

	// StatusGenqueue_unused is currently unused.
	StatusGenqueue_unused // 7

	// StatusGcopystack means this goroutine's stack is being moved. It
	// is not executing user code and is not on a run queue. The
	// stack is owned by the goroutine that put it in StatusGcopystack.
	StatusGcopystack // 8

	// StatusGpreempted means this goroutine stopped itself for a
	// suspendG preemption. It is like StatusGwaiting, but nothing is
	// yet responsible for ready()ing it. Some suspendG must CAS
	// the status to StatusGwaiting to take responsibility for
	// ready()ing this G.
	StatusGpreempted // 9

	// StatusGscan combined with one of the above states other than
	// StatusGrunning indicates that GC is scanning the stack. The
	// goroutine is not executing user code and the stack is owned
	// by the goroutine that set the StatusGscan bit.
	//
	// StatusGscanrunning is different: it is used to briefly block
	// state transitions while GC signals the G to scan its own
	// stack. This is otherwise like StatusGrunning.
	//
	// atomicstatus&~Gscan gives the state the goroutine will
	// return to when the scan completes.
	StatusGscan          Status = 0x1000
	StatusGscanrunnable  Status = StatusGscan + StatusGrunnable  // 0x1001
	StatusGscanrunning   Status = StatusGscan + StatusGrunning   // 0x1002
	StatusGscansyscall   Status = StatusGscan + StatusGsyscall   // 0x1003
	StatusGscanwaiting   Status = StatusGscan + StatusGwaiting   // 0x1004
	StatusGscanpreempted Status = StatusGscan + StatusGpreempted // 0x1009
)

type Sudog

type Sudog struct {
	// contains filtered or unexported fields
}

Sudog represents a g in a wait list, such as for sending/receiving on a channel.

Sudog is necessary because the g ↔ synchronization object relation is many-to-many. A g can be on many wait lists, so there may be many sudogs for one g; and many gs may be waiting on the same synchronization object, so there may be many sudogs for one object.

sudogs are allocated from a special pool. Use acquireSudog and releaseSudog to allocate and free them.

See ${GOROOT}/src/runtime/runtime2.go#type:sudog

type WaitReason

type WaitReason uint8

A WaitReason explains why a goroutine has been stopped. See gopark. Do not re-use waitReasons, add new ones.

const (
	WaitReasonZero                  WaitReason = iota // ""
	WaitReasonGCAssistMarking                         // "GC assist marking"
	WaitReasonIOWait                                  // "IO wait"
	WaitReasonChanReceiveNilChan                      // "chan receive (nil chan)"
	WaitReasonChanSendNilChan                         // "chan send (nil chan)"
	WaitReasonDumpingHeap                             // "dumping heap"
	WaitReasonGarbageCollection                       // "garbage collection"
	WaitReasonGarbageCollectionScan                   // "garbage collection scan"
	WaitReasonPanicWait                               // "panicwait"
	WaitReasonSelect                                  // "select"
	WaitReasonSelectNoCases                           // "select (no cases)"
	WaitReasonGCAssistWait                            // "GC assist wait"
	WaitReasonGCSweepWait                             // "GC sweep wait"
	WaitReasonGCScavengeWait                          // "GC scavenge wait"
	WaitReasonChanReceive                             // "chan receive"
	WaitReasonChanSend                                // "chan send"
	WaitReasonFinalizerWait                           // "finalizer wait"
	WaitReasonForceGCIdle                             // "force gc (idle)"
	WaitReasonSemacquire                              // "semacquire"
	WaitReasonSleep                                   // "sleep"
	WaitReasonSyncCondWait                            // "sync.Cond.Wait"
	WaitReasonSyncMutexLock                           // "sync.Mutex.Lock"
	WaitReasonSyncRWMutexRLock                        // "sync.RWMutex.RLock"
	WaitReasonSyncRWMutexLock                         // "sync.RWMutex.Lock"
	WaitReasonTraceReaderBlocked                      // "trace reader (blocked)"
	WaitReasonWaitForGCCycle                          // "wait for GC cycle"
	WaitReasonGCWorkerIdle                            // "GC worker (idle)"
	WaitReasonGCWorkerActive                          // "GC worker (active)"
	WaitReasonPreempted                               // "preempted"
	WaitReasonDebugCall                               // "debug call"
	WaitReasonGCMarkTermination                       // "GC mark termination"
	WaitReasonStoppingTheWorld                        // "stopping the world"
)

func (WaitReason) IsMutexWait

func (w WaitReason) IsMutexWait() bool

type Waitq

type Waitq struct {
	// contains filtered or unexported fields
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL