runtime: move scheduler code around

This moves all scheduler code into a separate file that is only compiled
when there's a scheduler in use (the tasks or asyncify scheduler, which
are both cooperative). The main goal of this change is to make it easier
to add a new "scheduler" based on OS threads.

It also fixes a few subtle issues with `-gc=none`:

  - Gosched() panicked. This is now fixed to just return immediately
    (the only logical thing to do when there's only one goroutine).
  - Timers aren't supported without a scheduler, but the relevant code
    was still present and would happily add a timer to the queue. It
    just never ran. So now it exits with a runtime error, similar to any
    blocking operation.
This commit is contained in:
Ayke van Laethem
2024-10-25 11:14:57 +02:00
committed by Ron Evans
parent 6593cf22fa
commit d1fe02df23
12 changed files with 315 additions and 277 deletions
+3 -2
View File
@@ -464,12 +464,13 @@ func runGC() (freeBytes uintptr) {
// Therefore we need to scan the runqueue separately.
var markedTaskQueue task.Queue
runqueueScan:
runqueue := schedulerRunQueue()
for !runqueue.Empty() {
// Pop the next task off of the runqueue.
t := runqueue.Pop()
// Mark the task if it has not already been marked.
markRoot(uintptr(unsafe.Pointer(&runqueue)), uintptr(unsafe.Pointer(t)))
markRoot(uintptr(unsafe.Pointer(runqueue)), uintptr(unsafe.Pointer(t)))
// Push the task onto our temporary queue.
markedTaskQueue.Push(t)
@@ -484,7 +485,7 @@ func runGC() (freeBytes uintptr) {
interrupt.Restore(i)
goto runqueueScan
}
runqueue = markedTaskQueue
*runqueue = markedTaskQueue
interrupt.Restore(i)
} else {
finishMark()