rumpk/io/governor.nim

69 lines
1.7 KiB
Nim

# SPDX-License-Identifier: LUL-1.0
# Copyright (c) 2026 Markus Maiwald
# Stewardship: Self Sovereign Society Foundation
#
# This file is part of the Nexus SDK.
# See legal/LICENSE_UNBOUND.md for license terms.
# Rumpk Adaptive I/O Governor
# War Mode (polling) ↔ Peace Mode (interrupts)
import ring
const
POLL_BUDGET* = 2000 ## Cycles before switching to peace mode
PEACE_TIMEOUT_NS* = 1_000_000 ## 1ms before checking again
type
GovernorMode* = enum
War, ## High load: 100% CPU polling
Peace ## Low load: Interrupt-driven
IoGovernor*[T; N: static[int]] = object
mode*: GovernorMode
budget: int
ring*: RingBuffer[T, N]
# Callbacks (set by driver)
hw_has_data*: proc(): bool {.nimcall.}
hw_fetch*: proc(): T {.nimcall.}
hw_enable_irq*: proc() {.nimcall.}
hw_disable_irq*: proc() {.nimcall.}
lwkt_yield*: proc() {.nimcall.}
proc init*[T; N: static[int]](gov: var IoGovernor[T, N]) =
gov.mode = Peace
gov.budget = POLL_BUDGET
gov.ring.init()
proc tick*[T; N: static[int]](gov: var IoGovernor[T, N]) =
## Main driver loop iteration
if gov.hw_has_data():
# WAR MODE: Data available, stay aggressive
let data = gov.hw_fetch()
discard gov.ring.push(data)
gov.budget = POLL_BUDGET
gov.mode = War
else:
# Speculation window
if gov.budget > 0:
dec gov.budget
# cpu_relax() equivalent - let other fibers run briefly
else:
# PEACE MODE: Budget exhausted, sleep
gov.mode = Peace
gov.hw_enable_irq()
gov.lwkt_yield()
# Woke up from interrupt
gov.hw_disable_irq()
gov.budget = POLL_BUDGET
proc run*[T; N: static[int]](gov: var IoGovernor[T, N]) {.noreturn.} =
## Infinite driver loop
while true:
gov.tick()