task_stack_amd64.mx raw

   1  //go:build scheduler.tasks && amd64 && !windows
   2  
   3  package task
   4  
   5  import "unsafe"
   6  
   7  var systemStack uintptr
   8  
   9  // calleeSavedRegs is the list of registers that must be saved and restored when
  10  // switching between tasks. Also see task_stack_amd64.S that relies on the exact
  11  // layout of this struct.
  12  type calleeSavedRegs struct {
  13  	rbx uintptr
  14  	rbp uintptr
  15  	r12 uintptr
  16  	r13 uintptr
  17  	r14 uintptr
  18  	r15 uintptr
  19  
  20  	pc uintptr
  21  }
  22  
  23  // archInit runs architecture-specific setup for the goroutine startup.
  24  func (s *state) archInit(r *calleeSavedRegs, fn uintptr, args unsafe.Pointer) {
  25  	// Store the initial sp for the startTask function (implemented in assembly).
  26  	s.sp = uintptr(unsafe.Pointer(r))
  27  
  28  	// Initialize the registers.
  29  	// These will be popped off of the stack on the first resume of the goroutine.
  30  
  31  	// Start the function at moxie_startTask (defined in
  32  	// src/internal/task/task_stack_amd64.S). This assembly code calls a
  33  	// function (passed in r12) with a single argument (passed in r13). After
  34  	// the function returns, it calls Pause().
  35  	r.pc = uintptr(unsafe.Pointer(&startTask))
  36  
  37  	// Pass the function to call in r12.
  38  	// This function is a compiler-generated wrapper which loads arguments out
  39  	// of a struct pointer. See createGoroutineStartWrapper (defined in
  40  	// compiler/goroutine.go) for more information.
  41  	r.r12 = fn
  42  
  43  	// Pass the pointer to the arguments struct in r13.
  44  	r.r13 = uintptr(args)
  45  }
  46  
  47  func (s *state) resume() {
  48  	swapTask(s.sp, &systemStack)
  49  }
  50  
  51  func (s *state) pause() {
  52  	newStack := systemStack
  53  	systemStack = 0
  54  	swapTask(newStack, &s.sp)
  55  }
  56  
  57  // SystemStack returns the system stack pointer when called from a task stack.
  58  // When called from the system stack, it returns 0.
  59  func SystemStack() uintptr {
  60  	return systemStack
  61  }
  62