runtime: make channels work in interrupts

This commit is contained in:
Jaden Weiss
2020-05-29 23:46:58 -04:00
committed by Ron Evans
parent aa3481e06a
commit a4f3457747
13 changed files with 232 additions and 33 deletions
+29 -1
View File
@@ -29,6 +29,8 @@ package runtime
// Moss.
import (
"internal/task"
"runtime/interrupt"
"unsafe"
)
@@ -292,10 +294,36 @@ func GC() {
}
// Mark phase: mark all reachable objects, recursively.
markGlobals()
markStack()
markGlobals()
// Channel operations in interrupts may move task pointers around while we are marking.
// Therefore we need to scan the runqueue seperately.
var markedTaskQueue task.Queue
runqueueScan:
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)))
// Push the task onto our temporary queue.
markedTaskQueue.Push(t)
}
finishMark()
// Restore the runqueue.
i := interrupt.Disable()
if !runqueue.Empty() {
// Something new came in while finishing the mark.
interrupt.Restore(i)
goto runqueueScan
}
runqueue = markedTaskQueue
interrupt.Restore(i)
// Sweep phase: free all non-marked objects and unmark marked objects for
// the next collection cycle.
sweep()