From 1c9d63f485126106f53c08e297b70dcf1eb0e62f Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Fri, 16 Aug 2019 15:22:12 +0200 Subject: [PATCH] compiler,runtime: fix new task-based scheduler A bug was introduced in the previous commit that led to miscompilations in the time.Sleep function when the scheduler was disabled, because time.Sleep (implemented in the runtime) tried to switch to the scheduler stack. This commit restores the binary size of most examples to what it was before, but still reduces static RAM consumption (.bss) slightly. This gives me some confidence that it does indeed fix the introduced bug. --- compiler/compiler.go | 1 + compiler/goroutine-lowering.go | 4 ++++ src/runtime/scheduler_tasks.go | 6 ++++++ 3 files changed, 11 insertions(+) diff --git a/compiler/compiler.go b/compiler/compiler.go index 2a5b80a332..ef2fd4164b 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -37,6 +37,7 @@ var functionsUsedInTransforms = []string{ "runtime.alloc", "runtime.free", "runtime.sleepTask", + "runtime.sleepCurrentTask", "runtime.setTaskStatePtr", "runtime.getTaskStatePtr", "runtime.activateTask", diff --git a/compiler/goroutine-lowering.go b/compiler/goroutine-lowering.go index 34a1c879aa..30abb23d38 100644 --- a/compiler/goroutine-lowering.go +++ b/compiler/goroutine-lowering.go @@ -150,6 +150,10 @@ func (c *Compiler) lowerTasks() error { zero := llvm.ConstInt(c.uintptrType, 0, false) c.createRuntimeCall("startGoroutine", []llvm.Value{realMainWrapper, zero}, "") c.createRuntimeCall("scheduler", nil, "") + sleep := c.mod.NamedFunction("time.Sleep") + if !sleep.IsNil() { + sleep.ReplaceAllUsesWith(c.mod.NamedFunction("runtime.sleepCurrentTask")) + } } else { // Program doesn't need a scheduler. Call main.main directly. c.builder.SetInsertPointBefore(mainCall) diff --git a/src/runtime/scheduler_tasks.go b/src/runtime/scheduler_tasks.go index 2d833c5e5b..8f1189211f 100644 --- a/src/runtime/scheduler_tasks.go +++ b/src/runtime/scheduler_tasks.go @@ -98,6 +98,12 @@ func startGoroutine(fn, args uintptr) { //go:linkname sleep time.Sleep func sleep(d int64) { + sleepTicks(timeUnit(d / tickMicros)) +} + +// sleepCurrentTask suspends the current goroutine. This is a compiler +// intrinsic. It replaces calls to time.Sleep when a scheduler is in use. +func sleepCurrentTask(d int64) { sleepTask(currentTask, d) swapTask(currentTask, &schedulerState) }