github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/internal/task/task_stack_cortexm.go (about) 1 //go:build scheduler.tasks && cortexm 2 3 package task 4 5 // Note that this is almost the same as task_stack_arm.go, but it uses the MSP 6 // register to store the system stack pointer instead of a global variable. The 7 // big advantage of this is that interrupts always execute with MSP (and not 8 // PSP, which is used for goroutines) so that goroutines do not need extra stack 9 // space for interrupts. 10 11 import "C" 12 import ( 13 "unsafe" 14 ) 15 16 // calleeSavedRegs is the list of registers that must be saved and restored when 17 // switching between tasks. Also see task_stack_cortexm.S that relies on the 18 // exact layout of this struct. 19 type calleeSavedRegs struct { 20 r4 uintptr 21 r5 uintptr 22 r6 uintptr 23 r7 uintptr 24 r8 uintptr 25 r9 uintptr 26 r10 uintptr 27 r11 uintptr 28 29 pc uintptr 30 } 31 32 // archInit runs architecture-specific setup for the goroutine startup. 33 func (s *state) archInit(r *calleeSavedRegs, fn uintptr, args unsafe.Pointer) { 34 // Store the initial sp for the startTask function (implemented in assembly). 35 s.sp = uintptr(unsafe.Pointer(r)) 36 37 // Initialize the registers. 38 // These will be popped off of the stack on the first resume of the goroutine. 39 40 // Start the function at tinygo_startTask (defined in src/internal/task/task_stack_cortexm.S). 41 // This assembly code calls a function (passed in r4) with a single argument (passed in r5). 42 // After the function returns, it calls Pause(). 43 r.pc = uintptr(unsafe.Pointer(&startTask)) 44 45 // Pass the function to call in r4. 46 // This function is a compiler-generated wrapper which loads arguments out of a struct pointer. 47 // See createGoroutineStartWrapper (defined in compiler/goroutine.go) for more information. 48 r.r4 = fn 49 50 // Pass the pointer to the arguments struct in r5. 51 r.r5 = uintptr(args) 52 } 53 54 func (s *state) resume() { 55 tinygo_switchToTask(s.sp) 56 } 57 58 //export tinygo_switchToTask 59 func tinygo_switchToTask(uintptr) 60 61 //export tinygo_switchToScheduler 62 func tinygo_switchToScheduler(*uintptr) 63 64 func (s *state) pause() { 65 tinygo_switchToScheduler(&s.sp) 66 } 67 68 // SystemStack returns the system stack pointer. On Cortex-M, it is always 69 // available. 70 // 71 //export SystemStack 72 func SystemStack() uintptr