riscv: switch to tasks-based scheduler

This is only supported for RV32 at the moment. RV64 can be added at a
later time.
Этот коммит содержится в:
Ayke van Laethem 2020-03-17 20:45:30 +01:00 коммит произвёл Ron Evans
родитель 5d8f25a622
коммит 878b62bbe8
5 изменённых файлов: 139 добавлений и 1 удалений

Просмотреть файл

@ -1,4 +1,4 @@
// +build scheduler.tasks,arm,!cortexm,!avr,!xtensa
// +build scheduler.tasks,arm,!cortexm,!avr,!xtensa,!tinygo.riscv
package task

69
src/internal/task/task_stack_tinygoriscv.S Обычный файл
Просмотреть файл

@ -0,0 +1,69 @@
.section .text.tinygo_startTask
.global tinygo_startTask
.type tinygo_startTask, %function
tinygo_startTask:
// Small assembly stub for starting a goroutine. This is already run on the
// new stack, with the callee-saved registers already loaded.
// Most importantly, s0 contains the pc of the to-be-started function and s1
// contains the only argument it is given. Multiple arguments are packed
// into one by storing them in a new allocation.
// Set the first argument of the goroutine start wrapper, which contains all
// the arguments.
mv a0, s1
// Branch to the "goroutine start" function. Use jalr to write the return
// address to ra so we'll return here after the goroutine exits.
jalr s0
// After return, exit this goroutine. This is a tail call.
tail tinygo_pause
.section .text.tinygo_swapTask
.global tinygo_swapTask
.type tinygo_swapTask, %function
tinygo_swapTask:
// This function gets the following parameters:
// a0 = newStack uintptr
// a1 = oldStack *uintptr
// Push all callee-saved registers.
addi sp, sp, -52
sw ra, 48(sp)
sw s11, 44(sp)
sw s10, 40(sp)
sw s9, 36(sp)
sw s8, 32(sp)
sw s7, 28(sp)
sw s6, 24(sp)
sw s5, 20(sp)
sw s4, 16(sp)
sw s3, 12(sp)
sw s2, 8(sp)
sw s1, 4(sp)
sw s0, (sp)
// Save the current stack pointer in oldStack.
sw sp, 0(a1)
// Switch to the new stack pointer.
mv sp, a0
// Pop all saved registers from this new stack.
lw ra, 48(sp)
lw s11, 44(sp)
lw s10, 40(sp)
lw s9, 36(sp)
lw s8, 32(sp)
lw s7, 28(sp)
lw s6, 24(sp)
lw s5, 20(sp)
lw s4, 16(sp)
lw s3, 12(sp)
lw s2, 8(sp)
lw s1, 4(sp)
lw s0, (sp)
addi sp, sp, 52
// Return into the task.
ret

66
src/internal/task/task_stack_tinygoriscv.go Обычный файл
Просмотреть файл

@ -0,0 +1,66 @@
// +build scheduler.tasks,tinygo.riscv
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 scheduler_riscv.S that relies on the
// exact layout of this struct.
type calleeSavedRegs struct {
s0 uintptr // x8 (fp)
s1 uintptr // x9
s2 uintptr // x18
s3 uintptr // x19
s4 uintptr // x20
s5 uintptr // x21
s6 uintptr // x22
s7 uintptr // x23
s8 uintptr // x24
s9 uintptr // x25
s10 uintptr // x26
s11 uintptr // x27
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_riscv.S).
// This assembly code calls a function (passed in s0) with a single argument
// (passed in s1). After the function returns, it calls Pause().
r.pc = uintptr(unsafe.Pointer(&startTask))
// Pass the function to call in s0.
// 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.s0 = fn
// Pass the pointer to the arguments struct in s1.
r.s1 = 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
}

Просмотреть файл

@ -16,6 +16,7 @@
],
"extra-files": [
"src/device/riscv/start.S",
"src/internal/task/task_stack_tinygoriscv.S",
"src/runtime/gc_riscv.S",
"src/device/riscv/handleinterrupt.S"
],

Просмотреть файл

@ -2,6 +2,8 @@
"inherits": ["riscv"],
"llvm-target": "riscv32--none",
"build-tags": ["tinygo.riscv32"],
"scheduler": "tasks",
"default-stack-size": 2048,
"cflags": [
"-march=rv32imac",
"-mabi=ilp32"