task.mx raw

   1  package task
   2  
   3  import (
   4  	"unsafe"
   5  )
   6  
   7  // Task is a state of goroutine for scheduling purposes.
   8  type Task struct {
   9  	// Next is a field which can be used to make a linked list of tasks.
  10  	Next *Task
  11  
  12  	// Ptr is a field which can be used for storing a pointer.
  13  	Ptr unsafe.Pointer
  14  
  15  	// Data is a field which can be used for storing state information.
  16  	Data uint64
  17  
  18  	// gcData holds data for the GC.
  19  	gcData gcData
  20  
  21  	// state is the underlying running state of the task.
  22  	state state
  23  
  24  	// This is needed for some crypto packages.
  25  	FipsIndicator uint8
  26  
  27  	// State of the goroutine: running, paused, or must-resume-next-pause.
  28  	// This extra field doesn't increase memory usage on 32-bit CPUs and above,
  29  	// since it falls into the padding of the FipsIndicator bit above.
  30  	RunState uint8
  31  
  32  	// DeferFrame stores a pointer to the (stack allocated) defer frame of the
  33  	// goroutine that is used for the recover builtin.
  34  	DeferFrame unsafe.Pointer
  35  }
  36  
  37  const (
  38  	// Initial state: the goroutine state is saved on the stack.
  39  	RunStatePaused = iota
  40  
  41  	// The goroutine is running right now.
  42  	RunStateRunning
  43  
  44  	// The goroutine is running, but already marked as "can resume".
  45  	// The next call to Pause() won't actually pause the goroutine.
  46  	RunStateResuming
  47  )
  48  
  49  // DataUint32 returns the Data field as a uint32. The value is only valid after
  50  // setting it through SetDataUint32 or by storing to it using DataAtomicUint32.
  51  func (t *Task) DataUint32() uint32 {
  52  	return *(*uint32)(unsafe.Pointer(&t.Data))
  53  }
  54  
  55  // SetDataUint32 updates the uint32 portion of the Data field (which could be
  56  // the first 4 or last 4 bytes depending on the architecture endianness).
  57  func (t *Task) SetDataUint32(val uint32) {
  58  	*(*uint32)(unsafe.Pointer(&t.Data)) = val
  59  }
  60  
  61  // DataAtomicUint32 returns the Data field as an atomic-if-needed Uint32 value.
  62  func (t *Task) DataAtomicUint32() *Uint32 {
  63  	return (*Uint32)(unsafe.Pointer(&t.Data))
  64  }
  65  
  66  // getGoroutineStackSize is a compiler intrinsic that returns the stack size for
  67  // the given function and falls back to the default stack size. It is replaced
  68  // with a load from a special section just before codegen.
  69  func getGoroutineStackSize(fn uintptr) uintptr
  70  
  71  //go:linkname runtime_alloc runtime.alloc
  72  func runtime_alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer
  73  
  74  //go:linkname scheduleTask runtime.scheduleTask
  75  func scheduleTask(*Task)
  76