github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/internal/task/task_stack_tinygoriscv.go (about) 1 //go:build scheduler.tasks && tinygo.riscv 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 scheduler_riscv.S that relies on the 11 // exact layout of this struct. 12 type calleeSavedRegs struct { 13 s0 uintptr // x8 (fp) 14 s1 uintptr // x9 15 s2 uintptr // x18 16 s3 uintptr // x19 17 s4 uintptr // x20 18 s5 uintptr // x21 19 s6 uintptr // x22 20 s7 uintptr // x23 21 s8 uintptr // x24 22 s9 uintptr // x25 23 s10 uintptr // x26 24 s11 uintptr // x27 25 26 pc uintptr 27 } 28 29 // archInit runs architecture-specific setup for the goroutine startup. 30 func (s *state) archInit(r *calleeSavedRegs, fn uintptr, args unsafe.Pointer) { 31 // Store the initial sp for the startTask function (implemented in assembly). 32 s.sp = uintptr(unsafe.Pointer(r)) 33 34 // Initialize the registers. 35 // These will be popped off of the stack on the first resume of the goroutine. 36 37 // Start the function at tinygo_startTask (defined in src/internal/task/task_stack_riscv.S). 38 // This assembly code calls a function (passed in s0) with a single argument 39 // (passed in s1). After the function returns, it calls Pause(). 40 r.pc = uintptr(unsafe.Pointer(&startTask)) 41 42 // Pass the function to call in s0. 43 // This function is a compiler-generated wrapper which loads arguments out 44 // of a struct pointer. See createGoroutineStartWrapper (defined in 45 // compiler/goroutine.go) for more information. 46 r.s0 = fn 47 48 // Pass the pointer to the arguments struct in s1. 49 r.s1 = uintptr(args) 50 } 51 52 func (s *state) resume() { 53 swapTask(s.sp, &systemStack) 54 } 55 56 func (s *state) pause() { 57 newStack := systemStack 58 systemStack = 0 59 swapTask(newStack, &s.sp) 60 } 61 62 // SystemStack returns the system stack pointer when called from a task stack. 63 // When called from the system stack, it returns 0. 64 func SystemStack() uintptr { 65 return systemStack 66 }