diff --git a/compiler/compiler.go b/compiler/compiler.go index 2a5b80a3..ef2fd416 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 34a1c879..30abb23d 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 2d833c5e..8f118921 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) }