171 lines
5.5 KiB
Nim
171 lines
5.5 KiB
Nim
# SPDX-License-Identifier: LSL-1.0
|
|
# Copyright (c) 2026 Markus Maiwald
|
|
# Stewardship: Self Sovereign Society Foundation
|
|
#
|
|
# This file is part of the Nexus Sovereign Core.
|
|
# See legal/LICENSE_SOVEREIGN.md for license terms.
|
|
|
|
## Rumpk Layer 1: The Reactive Dispatcher (The Tyrant)
|
|
##
|
|
## Implements the Silence Doctrine (SPEC-250).
|
|
## - No Tick.
|
|
## - No Policy.
|
|
## - Only Physics.
|
|
|
|
{.push stackTrace: off, lineTrace: off.}
|
|
|
|
import fiber
|
|
|
|
# We might need to access the Fiber globals from fiber.nim
|
|
# fiber.nim exports current_fiber, but we need to iterate them.
|
|
# Currently kernel.nim manages the specific fibers variables (fiber_ion, fiber_ui, etc.)
|
|
# We need a centralized registry or a way to iterate.
|
|
#
|
|
# For the first pass, we can replicate the logic in kernel.nim which explicitly checks
|
|
# the known fibers, but structured as the Spectrum loop.
|
|
# Or we can make kernel.nim pass the fibers to us.
|
|
#
|
|
# Let's keep it simple and stateless in sched.nim if possible, or have it manage the queue.
|
|
# Since kernel.nim holds the variables, sched.nim should probably define the *Strategy*
|
|
# and kernel.nim calls it, OR sched.nim should import kernel (circular!).
|
|
#
|
|
# Better: fiber.nim holds a linked list of fibers?
|
|
# Or sched.nim is just a helper module that kernel.nim uses.
|
|
|
|
# Let's define the Strategy here.
|
|
|
|
# To avoid circular imports, kernel.nim will likely INCLUDE sched.nim or sched.nim
|
|
# will act on a passed context.
|
|
# BUT, SPEC-250 implies sched.nim *is* the logic.
|
|
#
|
|
# Let's define the Harmonic logic.
|
|
# We need access to `current_fiber` (from fiber.nim) and `get_now_ns` (helper).
|
|
|
|
proc sched_get_now_ns*(): uint64 {.importc: "get_now_ns", cdecl.}
|
|
|
|
# Forward declaration for the tick function
|
|
# Returns TRUE if a fiber was switched to (work done/found).
|
|
# Returns FALSE if the system should sleep (WFI).
|
|
proc sched_tick_spectrum*(fibers: openArray[ptr FiberObject]): bool =
|
|
let now = sched_get_now_ns()
|
|
|
|
# =========================================================
|
|
# Phase 1: PHOTON (Hard Real-Time / Hardware Driven)
|
|
# =========================================================
|
|
# - V-Sync (Compositor)
|
|
# - Audio Mix
|
|
# - Network Polling (War Mode)
|
|
|
|
var run_photon = false
|
|
for f in fibers:
|
|
if f != nil and f.getSpectrum() == Spectrum.Photon:
|
|
if now >= f.sleep_until:
|
|
if f != current_fiber:
|
|
switch(f); return true
|
|
else:
|
|
run_photon = true
|
|
if run_photon: return true
|
|
|
|
# =========================================================
|
|
# Phase 2: MATTER (Interactive / Latency Sensitive)
|
|
# =========================================================
|
|
# - Shell
|
|
# - Editor
|
|
|
|
var run_matter = false
|
|
for f in fibers:
|
|
if f != nil and f.getSpectrum() == Spectrum.Matter:
|
|
if now >= f.sleep_until:
|
|
if f != current_fiber:
|
|
switch(f); return true
|
|
else:
|
|
run_matter = true
|
|
if run_matter: return true
|
|
|
|
# =========================================================
|
|
# Phase 3: GRAVITY (Throughput / Background)
|
|
# =========================================================
|
|
# - Compiler
|
|
# - Ledger Sync
|
|
|
|
var run_gravity = false
|
|
for f in fibers:
|
|
if f != nil and f.getSpectrum() == Spectrum.Gravity:
|
|
if now >= f.sleep_until:
|
|
if f != current_fiber:
|
|
switch(f); return true
|
|
else:
|
|
run_gravity = true
|
|
if run_gravity: return true
|
|
|
|
# =========================================================
|
|
# Phase 4: VOID (Scavenger)
|
|
# =========================================================
|
|
# - Untrusted Code
|
|
# - Speculative Execution
|
|
|
|
for f in fibers:
|
|
if f != nil and f.getSpectrum() == Spectrum.Void:
|
|
if now >= f.sleep_until:
|
|
if f != current_fiber:
|
|
switch(f)
|
|
return true
|
|
else:
|
|
return true
|
|
|
|
# =========================================================
|
|
# THE SILENCE
|
|
# =========================================================
|
|
# If we reached here, NO fiber is runnable.
|
|
return false
|
|
|
|
# =========================================================
|
|
# THE RATCHET (Post-Execution Analysis)
|
|
# =========================================================
|
|
|
|
proc console_write(p: pointer, len: csize_t) {.importc, cdecl.}
|
|
|
|
proc sched_log(msg: string) =
|
|
if msg.len > 0:
|
|
console_write(unsafeAddr msg[0], csize_t(msg.len))
|
|
|
|
proc sched_demote(f: ptr FiberObject) =
|
|
## Demote a fiber to a lower Spectrum tier
|
|
let current = f.getSpectrum()
|
|
case current:
|
|
of Spectrum.Photon:
|
|
f.setSpectrum(Spectrum.Matter)
|
|
console_write(cstring("[Ratchet] DEMOTED fiber to Matter\n"), 34)
|
|
of Spectrum.Matter:
|
|
f.setSpectrum(Spectrum.Gravity)
|
|
console_write(cstring("[Ratchet] DEMOTED fiber to Gravity\n"), 35)
|
|
of Spectrum.Gravity:
|
|
f.setSpectrum(Spectrum.Void)
|
|
console_write(cstring("[Ratchet] DEMOTED fiber to Void\n"), 32)
|
|
of Spectrum.Void:
|
|
discard # Already at the bottom
|
|
|
|
proc sched_analyze_burst*(f: ptr FiberObject, burst_ns: uint64) =
|
|
## Analyze the burst duration of a fiber after it yields/switches
|
|
## Implements the 3-strike rule for budget violations
|
|
if f == nil: return
|
|
|
|
f.last_burst_ns = burst_ns
|
|
|
|
# Update moving average (exponential: 75% old, 25% new)
|
|
if f.avg_burst == 0:
|
|
f.avg_burst = burst_ns
|
|
else:
|
|
f.avg_burst = (f.avg_burst * 3 + burst_ns) div 4
|
|
|
|
# Budget enforcement
|
|
if f.budget_ns > 0 and burst_ns > f.budget_ns:
|
|
f.violations += 1
|
|
console_write(cstring("[Ratchet] Violation: fiber exceeded budget\n"), 42)
|
|
|
|
if f.violations >= 3:
|
|
sched_demote(f)
|
|
f.violations = 0 # Reset after demotion
|
|
|
|
{.pop.}
|