
This results in smaller and likely more efficient code. It does require some architecture specific code for each architecture, but I've kept the amount of code as small as possible.
61 строка
1,7 КиБ
Go
61 строка
1,7 КиБ
Go
// +build scheduler.tasks,arm,!cortexm,!avr,!xtensa
|
|
|
|
package task
|
|
|
|
import "unsafe"
|
|
|
|
var systemStack uintptr
|
|
|
|
// calleeSavedRegs is the list of registers that must be saved and restored when
|
|
// switching between tasks. Also see task_stack_arm.S that relies on the exact
|
|
// layout of this struct.
|
|
type calleeSavedRegs struct {
|
|
r4 uintptr
|
|
r5 uintptr
|
|
r6 uintptr
|
|
r7 uintptr
|
|
r8 uintptr
|
|
r9 uintptr
|
|
r10 uintptr
|
|
r11 uintptr
|
|
|
|
pc uintptr
|
|
}
|
|
|
|
// archInit runs architecture-specific setup for the goroutine startup.
|
|
func (s *state) archInit(r *calleeSavedRegs, fn uintptr, args unsafe.Pointer) {
|
|
// Store the initial sp for the startTask function (implemented in assembly).
|
|
s.sp = uintptr(unsafe.Pointer(r))
|
|
|
|
// Initialize the registers.
|
|
// These will be popped off of the stack on the first resume of the goroutine.
|
|
|
|
// Start the function at tinygo_startTask (defined in src/internal/task/task_stack_arm.S).
|
|
// This assembly code calls a function (passed in r4) with a single argument
|
|
// (passed in r5). After the function returns, it calls Pause().
|
|
r.pc = uintptr(unsafe.Pointer(&startTask))
|
|
|
|
// Pass the function to call in r4.
|
|
// This function is a compiler-generated wrapper which loads arguments out of a struct pointer.
|
|
// See createGoroutineStartWrapper (defined in compiler/goroutine.go) for more information.
|
|
r.r4 = fn
|
|
|
|
// Pass the pointer to the arguments struct in r5.
|
|
r.r5 = uintptr(args)
|
|
}
|
|
|
|
func (s *state) resume() {
|
|
swapTask(s.sp, &systemStack)
|
|
}
|
|
|
|
func (s *state) pause() {
|
|
newStack := systemStack
|
|
systemStack = 0
|
|
swapTask(newStack, &s.sp)
|
|
}
|
|
|
|
// SystemStack returns the system stack pointer when called from a task stack.
|
|
// When called from the system stack, it returns 0.
|
|
func SystemStack() uintptr {
|
|
return systemStack
|
|
}
|