diff --git a/src/kernel/Entrypoint.hx b/src/kernel/Entrypoint.hx index 95ac353..9b31618 100644 --- a/src/kernel/Entrypoint.hx +++ b/src/kernel/Entrypoint.hx @@ -16,5 +16,7 @@ class Entrypoint { } catch (e) { Log.error('Error in startup: ${e.toString()}'); } + + KernelEvents.startEventLoop(); } } diff --git a/src/kernel/Init.hx b/src/kernel/Init.hx index c704775..93d16b5 100644 --- a/src/kernel/Init.hx +++ b/src/kernel/Init.hx @@ -1,25 +1,17 @@ package kernel; import kernel.service.ServiceManager; -import kernel.binstore.BinStore; -import kernel.gps.INS; import kernel.fs.FS; import kernel.gps.GPS; import kernel.log.Log; -import kernel.turtle.Turtle; -import haxe.MainLoop; import kernel.net.Routing; -import cc.OS; import lib.Debug; import kernel.ui.WindowManager; -import kernel.peripherals.Peripherals.Peripheral; import kernel.net.Net; import kernel.DCEHack; // Important for DCE hack class Init { @:allow(kernel.KernelEvents) - private static var mainEvent:MainEvent; - public static function initKernel() { // Init singeltons here because haxe is confused about the order to create them. Log.init(); @@ -44,10 +36,6 @@ class Init { FS.makeDir("/var/ns"); } - Init.mainEvent = MainLoop.add(() -> { - KernelEvents.startEventLoop(); - }); - ServiceManager.init(); } } diff --git a/src/kernel/KernelEvents.hx b/src/kernel/KernelEvents.hx index b3e30ed..70817a3 100644 --- a/src/kernel/KernelEvents.hx +++ b/src/kernel/KernelEvents.hx @@ -1,5 +1,7 @@ package kernel; +import kernel.turtle.TurtleMutex; +import kernel.turtle.Turtle; import kernel.peripherals.Peripherals.Peripheral; import kernel.log.Log; import lib.Pos; @@ -133,8 +135,49 @@ class KernelEvents { /** Start pulling events. Blocking. **/ - @:allow(kernel.Init) + @:allow(kernel.Entrypoint) private static function startEventLoop() { + if (Turtle.isTurtle()) { + turtleLoop(); + } else { + runMainLoop(); + } + } + + private static function turtleLoop() { + var turtleCoroutine = Coroutine.create(runTurtleLoop); + Coroutine.resume(turtleCoroutine); + + while (true) { + var eventData = pullEvents(); + + if (eventData[1] == "turtle_response" || eventData[1] == "tthread") { + Log.debug('Resuming turtle thread'); + var result = Coroutine.resume(turtleCoroutine, TableTools.unpack(eventData)); + + if (!result.success) { + Log.error('Error while running turtle thread: ${result.result}'); + } + + if (Coroutine.status(turtleCoroutine) == Dead) { + Log.error('Turtle thread died'); + } + } else { + fireSignal(eventData[1], eventData); + } + } + } + + private static function runTurtleLoop() { + while (!stopLoop) { + Coroutine.yield(); + if (stopLoop) + continue; + TurtleMutex.runThreadFunc(); + } + } + + private static function runMainLoop() { while (!stopLoop) { var event:Table = pullEvents(); @@ -156,7 +199,6 @@ class KernelEvents { Log.info('Shutting down event loop'); stopLoop = true; MainTerm.instance.reset(); - Init.mainEvent.stop(); } private static function pullEvents():Table { diff --git a/src/kernel/turtle/TurtleMutex.hx b/src/kernel/turtle/TurtleMutex.hx new file mode 100644 index 0000000..7ea78c8 --- /dev/null +++ b/src/kernel/turtle/TurtleMutex.hx @@ -0,0 +1,46 @@ +package kernel.turtle; + +import kernel.log.Log; +import cc.OS; +import kernel.ps.ProcessManager.PID; + +/** + Make sure only one process can access the turtle at a time. +**/ +class TurtleMutex { + private static var claimedPid:PID = -1; + public static var threadFunc:() -> Void; + + @:allow(kernel.ps.ProcessHandle) + private static function claim(pid:PID):Bool { + if (claimedPid == -1) { + claimedPid = pid; + return true; + } + return false; + } + + @:allow(kernel.ps.ProcessHandle) + private static function release(pid:PID) { + if (claimedPid == pid) { + claimedPid = -1; + } + } + + @:allow(kernel.KernelEvents) + private static function runThreadFunc() { + if (threadFunc != null) { + try { + threadFunc(); + } catch (e) { + Log.error("Error in tthread: " + e); + } + threadFunc = null; + } + } + + public static function runInTThread(func:() -> Void) { + threadFunc = func; + OS.queueEvent("tthread"); + } +}