ASELSANMicrokernel
S156 · SOURCE-BOUND GATE EVIDENCE

G8i: dormant per-CPU runtime model

Operations --test hedefi → simulation public mod g8i_runtime bağı → kaynak kesiti Bu sayfa yalnız S156 kapısına aittir; komşu kapıların kaynakları bu kabulün içine katılmaz.

S156Focused kod testiOperations id exactsource SHA exacttest target exact

operation: g8i-dormant-runtime-model-partial

uygulama/model · focused test · Operations · 3 exact excerpt

sequence-bound=true · implementation-bound=false
01 · Testin bağlı olduğu uygulama/model kodu

Kapının yürüttüğü gerçek kaynak

tam Rust öğesiL1–L200
simulation/src/g8i_runtime.rs::CpuState
//! G8i dormant runtime model.
//!
//! This state machine consumes the S155 ownership model without wiring the
//! production global scheduler or exception assembly.  It is the next
//! fail-closed source gate: local dequeue, current-task ownership, exception
//! entry/return and quiescent WFI are explicit per-CPU states.

use crate::g8i_runqueue::{
    ExceptionFrame, PerCpuRunQueueModel, RunQueueError, TaskToken, MAX_CPUS,
};

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum CpuState {
    Idle,
    Running,
    InException,
    Wfi,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum RuntimeError {
    Queue(RunQueueError),
    CurrentAlreadyOwned,
    NoCurrentTask,
    WrongCurrentTask,
    WfiWhileRunning,
    WfiWithRunnableTask,
    InvalidStateTransition,
    ExceptionWhileNotRunning,
    ReturnWhileNotInException,
}

impl From<RunQueueError> for RuntimeError {
    fn from(error: RunQueueError) -> Self {
        Self::Queue(error)
    }
}

pub struct DormantG8iRuntime {
    queues: PerCpuRunQueueModel,
    state: [CpuState; MAX_CPUS],
    current: [Option<TaskToken>; MAX_CPUS],
}

impl DormantG8iRuntime {
    pub const fn new() -> Self {
        Self {
            queues: PerCpuRunQueueModel::new(),
            state: [CpuState::Idle; MAX_CPUS],
            current: [None; MAX_CPUS],
        }
    }

    fn valid_cpu(cpu: usize) -> Result<(), RuntimeError> {
        if cpu < MAX_CPUS {
            Ok(())
        } else {
            Err(RuntimeError::Queue(RunQueueError::InvalidCpu))
        }
    }

    fn current_task_present(&self, task_id: u64) -> bool {
        self.current.iter().flatten().any(|task| task.id == task_id)
    }

    pub fn publish_local(&mut self, cpu: usize, task: TaskToken) -> Result<(), RuntimeError> {
        Self::valid_cpu(cpu)?;
        if self.current_task_present(task.id) {
            return Err(RuntimeError::Queue(RunQueueError::DuplicateTask));
        }
        self.queues.enqueue_local(cpu, task)?;
        if self.state[cpu] == CpuState::Wfi {
            self.state[cpu] = CpuState::Idle;
        }
        Ok(())
    }

    pub fn publish_remote(
        &mut self,
        source_cpu: usize,
        target_cpu: usize,
        task: TaskToken,
        generation: u64,
    ) -> Result<(), RuntimeError> {
        Self::valid_cpu(source_cpu)?;
        Self::valid_cpu(target_cpu)?;
        if self.current_task_present(task.id) {
            return Err(RuntimeError::Queue(RunQueueError::DuplicateTask));
        }
        self.queues
            .request_remote_enqueue(source_cpu, target_cpu, task, generation)?;
        if self.state[target_cpu] == CpuState::Wfi {
            self.state[target_cpu] = CpuState::Idle;
        }
        Ok(())
    }

    pub fn drain_mailbox(
        &mut self,
        caller_cpu: usize,
        target_cpu: usize,
    ) -> Result<(), RuntimeError> {
        Self::valid_cpu(caller_cpu)?;
        Self::valid_cpu(target_cpu)?;
        self.queues
            .drain_mailbox(caller_cpu, target_cpu)
            .map(|_| ())
            .map_err(Into::into)
    }

    pub fn run_next(&mut self, cpu: usize) -> Result<TaskToken, RuntimeError> {
        Self::valid_cpu(cpu)?;
        if self.current[cpu].is_some() {
            return Err(RuntimeError::CurrentAlreadyOwned);
        }
        if self.state[cpu] != CpuState::Idle {
            return Err(RuntimeError::InvalidStateTransition);
        }
        let task = self.queues.take_local(cpu).map_err(RuntimeError::from)?;
        self.current[cpu] = Some(task);
        self.state[cpu] = CpuState::Running;
        Ok(task)
    }

    pub fn enter_exception(
        &mut self,
        cpu: usize,
        generation: u64,
    ) -> Result<ExceptionFrame, RuntimeError> {
        Self::valid_cpu(cpu)?;
        if self.state[cpu] != CpuState::Running {
            return Err(RuntimeError::ExceptionWhileNotRunning);
        }
        let task = self.current[cpu].ok_or(RuntimeError::ExceptionWhileNotRunning)?;
        let frame = ExceptionFrame {
            task_id: task.id,
            owner_cpu: cpu,
            generation,
        };
        self.queues.enter_exception(cpu, frame)?;
        self.state[cpu] = CpuState::InException;
        Ok(frame)
    }

    pub fn leave_exception(&mut self, cpu: usize) -> Result<ExceptionFrame, RuntimeError> {
        Self::valid_cpu(cpu)?;
        if self.state[cpu] != CpuState::InException {
            return Err(RuntimeError::ReturnWhileNotInException);
        }
        let frame = self.queues.leave_exception(cpu)?;
        let task = self.current[cpu].ok_or(RuntimeError::NoCurrentTask)?;
        if frame.task_id != task.id || frame.owner_cpu != cpu {
            return Err(RuntimeError::WrongCurrentTask);
        }
        self.state[cpu] = CpuState::Running;
        Ok(frame)
    }

    pub fn return_current_to_idle(&mut self, cpu: usize) -> Result<TaskToken, RuntimeError> {
        Self::valid_cpu(cpu)?;
        if self.state[cpu] != CpuState::Running {
            return Err(RuntimeError::NoCurrentTask);
        }
        let task = self.current[cpu]
            .take()
            .ok_or(RuntimeError::NoCurrentTask)?;
        self.state[cpu] = CpuState::Idle;
        Ok(task)
    }

    pub fn enter_wfi(&mut self, cpu: usize) -> Result<(), RuntimeError> {
        Self::valid_cpu(cpu)?;
        if self.current[cpu].is_some() || self.state[cpu] == CpuState::Running {
            return Err(RuntimeError::WfiWhileRunning);
        }
        if self.state[cpu] != CpuState::Idle {
            return Err(RuntimeError::InvalidStateTransition);
        }
        if self.queues.queue_len(cpu)? != 0 {
            return Err(RuntimeError::WfiWithRunnableTask);
        }
        self.queues.enter_wfi(cpu)?;
        self.state[cpu] = CpuState::Wfi;
        Ok(())
    }

    pub fn state(&self, cpu: usize) -> Result<CpuState, RuntimeError> {
        Self::valid_cpu(cpu)?;
        Ok(self.state[cpu])
    }

    pub fn current(&self, cpu: usize) -> Result<Option<TaskToken>, RuntimeError> {
        Self::valid_cpu(cpu)?;
        Ok(self.current[cpu])
    }

    pub fn queue_len(&self, cpu: usize) -> Result<usize, RunQueueError> {
        self.queues.queue_len(cpu)
    }
}
snippet sha256: ed63df29b89ffile sha256: 4bb8d6cdea8b
02 · Doğrulayan test kodu

Operations komutuna bağlı focused test

tam Rust öğesiL128–L145
simulation/tests/g8i_dormant_runtime.rs::current_task_returns_to_idle_only_after_running_state

#[test]
fn current_task_returns_to_idle_only_after_running_state() {
    let mut runtime = DormantG8iRuntime::new();
    assert_eq!(
        runtime.return_current_to_idle(0),
        Err(RuntimeError::NoCurrentTask)
    );
    let task = TaskToken {
        id: 25,
        owner_cpu: 0,
    };
    runtime.publish_local(0, task).unwrap();
    runtime.run_next(0).unwrap();
    assert_eq!(runtime.return_current_to_idle(0).unwrap(), task);
    assert_eq!(runtime.state(0), Ok(CpuState::Idle));
    assert_eq!(runtime.current(0), Ok(None));
}
snippet sha256: 11dddb23cbd8file sha256: 0d6a95bebab7
03 · Kapı kimlik kaydı

Operations sıra, kimlik ve başlık bağı

tam Operations kaydıL23731–L23771
website/src/lib/operations.ts::g8i-dormant-runtime-model-partial
  {
    id: "g8i-dormant-runtime-model-partial",
    date: "2026-08-24",
    sequence: 156,
    status: "passed",
    umbrella_status: "partial",
    title: "G8i: dormant per-CPU runtime model",
    summary:
      "S156, S155 ownership modelini dormant runtime state machine ile tüketerek dört CPU için Idle/Running/InException/Wfi durumlarını, local dequeue, global tekil current-task sahipliğini, exact exception frame dönüşünü, quiescent WFI wake/admission'ı ve target mailbox drain öncesi remote task'in runnable olmamasını 8/8 kapattı. Bu kaynak/model kabulüdür; production scheduler wiring, QEMU ve fiziksel runtime açılmadı.",
    evidence: [
      "g8i_dormant_runtime: 8/8 PASS; dört CPU idle başlangıcı, owner-local dequeue, tekil current slot, exception entry/return, current→idle ve quiescent WFI doğrulandı.",
      "Remote task, target mailbox drain edilene kadar queue'da runnable değildir; running CPU WFI'ya giremez ve current olmadan exception entry reddedilir.",
      "Runnable queue ve tekrar WFI fail-closed reddediliyor; local/remote publish WFI hedefini Idle'a uyandırıyor, foreign drain reddediliyor ve geçersiz CPU public API'lerde panic yerine InvalidCpu döndürüyor.",
      "Current task kimliği bütün CPU'larda global tekildir; current durumundaki task başka queue/mailbox'a yeniden yayınlanamaz.",
      "Kalıcı kapsam: `docs/M8.1-RPi5-G8i-Dormant-Runtime-Model-Proof.md`.",
      "S156 fiziksel/device operasyonu yapmadı: physical/device operations=0 ve RUNBOOK_EXECUTED_IN_S156=NO.",
    ],
    commands: [
      "cargo test -p aselsan_microkernel_simulation --test g8i_dormant_runtime -- --test-threads=1",
    ],
    terminalSessions: [
      {
        id: "s156-g8i-dormant-runtime-model",
        title: "G8i dormant runtime host model kapısı",
        commandLines: [
          "cargo test -p aselsan_microkernel_simulation --test g8i_dormant_runtime -- --test-threads=1",
        ],
        outputLines: ["running 8 tests", "test result: ok. 8 passed; 0 failed"],
        exitCode: 0,
        outputMode: "selected",
      },
    ],
    terminalSessionsNote:
      "S156 yalnız bounded host/model state machine'dir; production scheduler, exception assembly, context switch, QEMU, fiziksel RPi ve generic SMP runtime sonucu değildir.",
    limitations: [
      "Production scheduler current-task ve per-CPU queue wiring'i henüz açılmadı; bu kapı model/source sınırındadır.",
      "Gerçek per-CPU IRQ stack, exception-frame trampoline, context switch ve migration sonraki G8i runtime kapılarında açılmalıdır.",
      "QEMU, fiziksel/device operations, CPU hotplug, TLB shootdown, long soak ve generic SMP arbitration kapsam dışıdır.",
      "Fiziksel/device operations=0; RUNBOOK_EXECUTED_IN_S156=NO.",
    ],
  },
snippet sha256: 261ec1e89b01file sha256: 9726dbf00f84
Focused test komutu
cargo test -p aselsan_microkernel_simulation --test g8i_dormant_runtime -- --test-threads=1
Registry schema v5 · generator website/scripts/generate-code-gates.mjs · Tam SHA-256: 91d38c7b6222f0b4c117be786454853543da55a160e543d9b951057cc20dcc06