ASELSANMicrokernel
S420 · SOURCE-BOUND GATE EVIDENCE

S420 · Terminal reconciliation ACK

tam S420 implementation modülü → Operations --test hedefi ile bağlı tam focused test → ayrı Operations kaydı Bu sayfa yalnız S420 kapısına aittir; komşu kapıların kaynakları bu kabulün içine katılmaz.

S420Focused kod testiOperations id exactsource SHA exacttest target exact

operation: g8l-s420-terminal-reconciliation-ack-partial

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

sequence-bound=true · implementation-bound=true
01 · Yürütme / doğrulama kodu

Kapının gerçek repository sözleşmesi

tam dosyaL1–L225
kernel/src/g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s420_terminal_reconciliation_ack.rs::S420 terminal reconciliation ack implementation
#![allow(unexpected_cfgs)]

//! S420 CPU0 reconciliation of S419 terminal records.
//!
//! CPU0 consumes a terminal record only after the provider lease is gone and
//! S418 reports no live partial state. A completed record additionally requires
//! the S243 S187 handoff to be pending. The resulting one-slot CPU1 ACK carries
//! no authority; S421 will decide whether a handoff may be taken.

use crate::g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s419_handshake_terminal_journal::{
    G8lS419HandshakeTerminalJournalError, G8lS419HandshakeTerminalJournalState,
    G8lS419HandshakeTerminalKind, G8lS419HandshakeTerminalRecord,
    S419_DIRECT_SCHEDULER_ACCESS_SITES, S419_PRODUCTION_GUARDED_DIRECT_ACCESS_SITES,
    S419_SOURCE_AUDIT_UNITS, S419_SOURCE_MODEL_COVERED_DIRECT_ACCESS_SITES,
    S419_UNROUTED_DIRECT_ACCESS_SITES,
};

pub const S420_SOURCE_AUDIT_UNITS: usize = S419_SOURCE_AUDIT_UNITS;
pub const S420_DIRECT_SCHEDULER_ACCESS_SITES: usize = S419_DIRECT_SCHEDULER_ACCESS_SITES;
pub const S420_SOURCE_MODEL_COVERED_DIRECT_ACCESS_SITES: usize =
    S419_SOURCE_MODEL_COVERED_DIRECT_ACCESS_SITES;
pub const S420_PRODUCTION_GUARDED_DIRECT_ACCESS_SITES: usize =
    S419_PRODUCTION_GUARDED_DIRECT_ACCESS_SITES;
pub const S420_UNROUTED_DIRECT_ACCESS_SITES: usize = S419_UNROUTED_DIRECT_ACCESS_SITES;
pub const S420_RECONCILIATION_ACK_CAPACITY: usize = 1;
pub const S420_PRODUCTION_CONSUMER_CALLSITES: usize = 1;
pub const S420_CPU0_TERMINAL_RECONCILIATION_COMPLETE: bool = true;
pub const S420_CPU1_S187_HANDOFF_CONSUMPTION_COMPLETE: bool = false;

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct G8lS420TerminalReconciliationAck {
    pub kind: G8lS419HandshakeTerminalKind,
    pub attempt_id: u64,
    pub provider_request_id: u64,
    pub exclusive_token: u64,
    pub s187_handoff_expected: bool,
    pub source_cpu: usize,
    pub target_cpu: usize,
    pub is_authority: bool,
}

#[derive(Debug)]
pub struct G8lS420TerminalReconciliationAckState {
    pending: Option<G8lS420TerminalReconciliationAck>,
}

impl G8lS420TerminalReconciliationAckState {
    pub const fn new() -> Self {
        Self { pending: None }
    }
    pub const fn pending(&self) -> bool {
        self.pending.is_some()
    }
    pub fn pending_ack(
        &self,
        caller_cpu: usize,
    ) -> Result<Option<G8lS420TerminalReconciliationAck>, G8lS420TerminalReconciliationError> {
        if caller_cpu != 1 {
            return Err(G8lS420TerminalReconciliationError::WrongConsumerCpu);
        }
        Ok(self.pending)
    }
    fn publish(
        &mut self,
        ack: G8lS420TerminalReconciliationAck,
    ) -> Result<(), G8lS420TerminalReconciliationError> {
        if self.pending.is_some() {
            return Err(G8lS420TerminalReconciliationError::AckSlotOccupied);
        }
        self.pending = Some(ack);
        Ok(())
    }
    pub fn take(
        &mut self,
        caller_cpu: usize,
    ) -> Result<Option<G8lS420TerminalReconciliationAck>, G8lS420TerminalReconciliationError> {
        if caller_cpu != 1 {
            return Err(G8lS420TerminalReconciliationError::WrongConsumerCpu);
        }
        Ok(self.pending.take())
    }
}

impl Default for G8lS420TerminalReconciliationAckState {
    fn default() -> Self {
        Self::new()
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum G8lS420TerminalReconciliationOutcome {
    Idle,
    HandshakeActive,
    AwaitingPartialCleanup,
    AckPublished(G8lS420TerminalReconciliationAck),
    AckPending(G8lS420TerminalReconciliationAck),
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum G8lS420TerminalReconciliationError {
    WrongCpu,
    WrongConsumerCpu,
    S419(G8lS419HandshakeTerminalJournalError),
    MissingCompletedHandoff,
    TerminalDisappeared,
    TerminalDrift,
    AckSlotOccupied,
    Upstream,
}

fn ack_from_record(record: G8lS419HandshakeTerminalRecord) -> G8lS420TerminalReconciliationAck {
    G8lS420TerminalReconciliationAck {
        kind: record.kind,
        attempt_id: record.attempt_id,
        provider_request_id: record.provider_request_id,
        exclusive_token: record.exclusive_token,
        s187_handoff_expected: record.kind == G8lS419HandshakeTerminalKind::Completed,
        source_cpu: 0,
        target_cpu: 1,
        is_authority: false,
    }
}

pub fn service_s420_model_terminal_reconciliation_ack(
    journal: &mut G8lS419HandshakeTerminalJournalState,
    acks: &mut G8lS420TerminalReconciliationAckState,
    caller_cpu: usize,
    active_exclusive_token: Option<u64>,
    partial_state_clean: bool,
    s187_handoff_pending: bool,
) -> Result<G8lS420TerminalReconciliationOutcome, G8lS420TerminalReconciliationError> {
    if caller_cpu != 0 {
        return Err(G8lS420TerminalReconciliationError::WrongCpu);
    }
    if let Some(existing) = acks.pending_ack(1)? {
        return Ok(G8lS420TerminalReconciliationOutcome::AckPending(existing));
    }
    let Some(record) = journal
        .pending_record(caller_cpu)
        .map_err(G8lS420TerminalReconciliationError::S419)?
    else {
        return Ok(G8lS420TerminalReconciliationOutcome::Idle);
    };
    if active_exclusive_token.is_some() {
        return Ok(G8lS420TerminalReconciliationOutcome::HandshakeActive);
    }
    if !partial_state_clean {
        return Ok(G8lS420TerminalReconciliationOutcome::AwaitingPartialCleanup);
    }
    if record.kind == G8lS419HandshakeTerminalKind::Completed && !s187_handoff_pending {
        return Err(G8lS420TerminalReconciliationError::MissingCompletedHandoff);
    }
    let taken = journal
        .take(caller_cpu)
        .map_err(G8lS420TerminalReconciliationError::S419)?
        .ok_or(G8lS420TerminalReconciliationError::TerminalDisappeared)?;
    if taken != record {
        return Err(G8lS420TerminalReconciliationError::TerminalDrift);
    }
    let ack = ack_from_record(taken);
    acks.publish(ack)?;
    Ok(G8lS420TerminalReconciliationOutcome::AckPublished(ack))
}

#[cfg(all(target_arch = "aarch64", target_os = "none", feature = "board-rpi5"))]
static S420_PRODUCTION_RECONCILIATION_ACKS: spin::Mutex<G8lS420TerminalReconciliationAckState> =
    spin::Mutex::new(G8lS420TerminalReconciliationAckState::new());

#[cfg(all(target_arch = "aarch64", target_os = "none", feature = "board-rpi5"))]
pub fn service_s420_terminal_reconciliation_ack_on_cpu0(
) -> Result<G8lS420TerminalReconciliationOutcome, G8lS420TerminalReconciliationError> {
    use crate::g8l_runtime_contract::CPU0;
    if crate::percpu::try_current_cpu_id() != Some(CPU0) {
        return Err(G8lS420TerminalReconciliationError::WrongCpu);
    }
    if let Some(existing) = S420_PRODUCTION_RECONCILIATION_ACKS.lock().pending_ack(1)? {
        return Ok(G8lS420TerminalReconciliationOutcome::AckPending(existing));
    }
    let cleanup = crate::g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s418_cpu0_partial_state_reconciliation::service_s418_cpu0_partial_state_reconciliation_on_cpu0()
        .map_err(|_| G8lS420TerminalReconciliationError::Upstream)?;
    let partial_state_clean = matches!(
        cleanup,
        crate::g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s418_cpu0_partial_state_reconciliation::G8lS418Cpu0PartialStateReconciliationOutcome::Clean
        | crate::g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s418_cpu0_partial_state_reconciliation::G8lS418Cpu0PartialStateReconciliationOutcome::Discarded(..)
    );
    let active_token = crate::g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s246_whole_scheduler_read_access_guard::S247_PRODUCTION_WHOLE_SCHEDULER_ACCESS_GATE
        .active_exclusive_token();
    let s187_handoff_pending = crate::g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s242_authority_return_s240_receipt_deferred_consumer::s243_deferred_s187_handoff_pending_on_cpu0()
        .map_err(|_| G8lS420TerminalReconciliationError::Upstream)?;
    let Some(record) = crate::g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s419_handshake_terminal_journal::inspect_s419_handshake_terminal_record_on_cpu0()
        .map_err(G8lS420TerminalReconciliationError::S419)? else {
        return Ok(G8lS420TerminalReconciliationOutcome::Idle);
    };
    if active_token.is_some() {
        return Ok(G8lS420TerminalReconciliationOutcome::HandshakeActive);
    }
    if !partial_state_clean {
        return Ok(G8lS420TerminalReconciliationOutcome::AwaitingPartialCleanup);
    }
    if record.kind == G8lS419HandshakeTerminalKind::Completed && !s187_handoff_pending {
        return Err(G8lS420TerminalReconciliationError::MissingCompletedHandoff);
    }
    let taken = crate::g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s419_handshake_terminal_journal::take_s419_handshake_terminal_record_on_cpu0()
        .map_err(G8lS420TerminalReconciliationError::S419)?
        .ok_or(G8lS420TerminalReconciliationError::TerminalDisappeared)?;
    if taken != record {
        return Err(G8lS420TerminalReconciliationError::TerminalDrift);
    }
    let ack = ack_from_record(taken);
    S420_PRODUCTION_RECONCILIATION_ACKS.lock().publish(ack)?;
    Ok(G8lS420TerminalReconciliationOutcome::AckPublished(ack))
}

#[cfg(all(target_arch = "aarch64", target_os = "none", feature = "board-rpi5"))]
pub fn inspect_s420_terminal_reconciliation_ack_on_cpu1(
) -> Result<Option<G8lS420TerminalReconciliationAck>, G8lS420TerminalReconciliationError> {
    S420_PRODUCTION_RECONCILIATION_ACKS.lock().pending_ack(1)
}

#[cfg(all(target_arch = "aarch64", target_os = "none", feature = "board-rpi5"))]
pub fn take_s420_terminal_reconciliation_ack_on_cpu1(
) -> Result<Option<G8lS420TerminalReconciliationAck>, G8lS420TerminalReconciliationError> {
    S420_PRODUCTION_RECONCILIATION_ACKS.lock().take(1)
}
snippet sha256: 1c02d378cd57file sha256: 1c02d378cd57
02 · Doğrulayan test kodu

Operations komutuna bağlı focused test

tam dosyaL1–L158
simulation/tests/g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s420_terminal_reconciliation_ack.rs::S420 terminal reconciliation ack focused tests
use aselsan_microkernel_simulation::g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s419_handshake_terminal_journal::{service_s419_model_handshake_terminal_journal, G8lS419HandshakeTerminalJournalState, G8lS419HandshakeTerminalKind};
use aselsan_microkernel_simulation::g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s420_terminal_reconciliation_ack::*;

fn journal(kind: G8lS419HandshakeTerminalKind) -> G8lS419HandshakeTerminalJournalState {
    let mut state = G8lS419HandshakeTerminalJournalState::new();
    service_s419_model_handshake_terminal_journal(&mut state, 1, kind, 7, 8, 9, 3).unwrap();
    state
}

#[test]
fn constants_define_single_reconciliation_ack() {
    assert_eq!(S420_RECONCILIATION_ACK_CAPACITY, 1);
    assert_eq!(S420_PRODUCTION_CONSUMER_CALLSITES, 1);
    assert!(S420_CPU0_TERMINAL_RECONCILIATION_COMPLETE);
    assert!(!S420_CPU1_S187_HANDOFF_CONSUMPTION_COMPLETE);
}

#[test]
fn completed_terminal_requires_and_records_pending_s187_handoff() {
    let mut journal = journal(G8lS419HandshakeTerminalKind::Completed);
    let mut acks = G8lS420TerminalReconciliationAckState::new();
    let outcome = service_s420_model_terminal_reconciliation_ack(
        &mut journal,
        &mut acks,
        0,
        None,
        true,
        true,
    )
    .unwrap();
    let G8lS420TerminalReconciliationOutcome::AckPublished(ack) = outcome else {
        panic!("ack")
    };
    assert!(ack.s187_handoff_expected);
    assert_eq!(
        (ack.attempt_id, ack.provider_request_id, ack.exclusive_token),
        (7, 8, 9)
    );
    assert!(!journal.pending());
    assert!(acks.pending());
}

#[test]
fn completed_without_handoff_fails_before_journal_take() {
    let mut journal = journal(G8lS419HandshakeTerminalKind::Completed);
    let mut acks = G8lS420TerminalReconciliationAckState::new();
    assert_eq!(
        service_s420_model_terminal_reconciliation_ack(
            &mut journal,
            &mut acks,
            0,
            None,
            true,
            false
        ),
        Err(G8lS420TerminalReconciliationError::MissingCompletedHandoff)
    );
    assert!(journal.pending() && !acks.pending());
}

#[test]
fn timeout_terminal_does_not_claim_handoff() {
    let mut journal = journal(G8lS419HandshakeTerminalKind::TimedOutReleased);
    let mut acks = G8lS420TerminalReconciliationAckState::new();
    service_s420_model_terminal_reconciliation_ack(&mut journal, &mut acks, 0, None, true, false)
        .unwrap();
    assert!(!acks.pending_ack(1).unwrap().unwrap().s187_handoff_expected);
}

#[test]
fn active_gate_or_partial_cleanup_preserves_journal() {
    for (active, clean, expected) in [
        (
            Some(9),
            true,
            G8lS420TerminalReconciliationOutcome::HandshakeActive,
        ),
        (
            None,
            false,
            G8lS420TerminalReconciliationOutcome::AwaitingPartialCleanup,
        ),
    ] {
        let mut journal = journal(G8lS419HandshakeTerminalKind::Completed);
        let mut acks = G8lS420TerminalReconciliationAckState::new();
        assert_eq!(
            service_s420_model_terminal_reconciliation_ack(
                &mut journal,
                &mut acks,
                0,
                active,
                clean,
                true
            )
            .unwrap(),
            expected
        );
        assert!(journal.pending());
    }
}

#[test]
fn occupied_ack_backpressures_before_terminal_take() {
    let mut first = journal(G8lS419HandshakeTerminalKind::TimedOutReleased);
    let mut acks = G8lS420TerminalReconciliationAckState::new();
    service_s420_model_terminal_reconciliation_ack(&mut first, &mut acks, 0, None, true, false)
        .unwrap();
    let pending = acks.pending_ack(1).unwrap().unwrap();
    let mut second = journal(G8lS419HandshakeTerminalKind::Completed);
    assert_eq!(
        service_s420_model_terminal_reconciliation_ack(&mut second, &mut acks, 0, None, true, true)
            .unwrap(),
        G8lS420TerminalReconciliationOutcome::AckPending(pending)
    );
    assert!(second.pending());
}

#[test]
fn production_orders_s418_gate_handoff_inspect_journal_take_ack_publish() {
    let source = include_str!("../../kernel/src/g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s420_terminal_reconciliation_ack.rs");
    let start = source
        .find("service_s420_terminal_reconciliation_ack_on_cpu0")
        .unwrap();
    let body = &source[start..];
    let cleanup = body
        .find("service_s418_cpu0_partial_state_reconciliation_on_cpu0")
        .unwrap();
    let gate = body.find("active_exclusive_token").unwrap();
    let handoff = body
        .find("s243_deferred_s187_handoff_pending_on_cpu0")
        .unwrap();
    let inspect = body
        .find("inspect_s419_handshake_terminal_record_on_cpu0")
        .unwrap();
    let take = body
        .find("take_s419_handshake_terminal_record_on_cpu0")
        .unwrap();
    assert!(cleanup < gate && gate < handoff && handoff < inspect && inspect < take);
}

#[test]
fn timer_chain_runs_s420_after_s418_before_s244() {
    let source = include_str!("../../kernel/src/arch/aarch64/exceptions.rs");
    let s418 = source
        .find("service_s418_cpu0_partial_state_reconciliation_on_cpu0")
        .unwrap();
    let s420 = source
        .find("service_s420_terminal_reconciliation_ack_on_cpu0")
        .unwrap();
    let s244 = source
        .find("service_s244_whole_scheduler_exclusion_admission_on_cpu0")
        .unwrap();
    assert!(s418 < s420 && s420 < s244);
    let name = "g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s420_terminal_reconciliation_ack";
    assert!(include_str!("../../kernel/src/main.rs").contains(&format!("mod {name};")));
    assert!(include_str!("../src/lib.rs").contains(&format!("pub mod {name};")));
}
snippet sha256: e298d6bd2614file sha256: e298d6bd2614
03 · Kapı kimlik kaydı

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

tam Operations kaydıL423–L439
website/src/lib/operations.ts::g8l-s420-terminal-reconciliation-ack-partial
  {
    id: "g8l-s420-terminal-reconciliation-ack-partial",
    sequence: 420,
    slug: "terminal_reconciliation_ack",
    title: "Terminal reconciliation ACK",
    focusedTests: 8,
    sourceBytes: 9992,
    sourceSha256:
      "1c02d378cd57b1ea00cea8da4ae3eabe197a4dd506e9f8a09aac2c8632794a65",
    testBytes: 5973,
    testSha256:
      "e298d6bd2614e7313daadbc0453f8cd9f340d8d7024ba4fc8a4b13c162c48786",
    acceptance:
      "CPU0 S419 terminal record'ını one-shot tüketir, partial-state sonucu ile karşılaştırır ve capacity-one terminal reconciliation ACK üretir.",
    retainedBoundary:
      "ACK CPU1'de S187 handoff consumption yetkisi değildir; delivery S421'e ayrılır.",
  },
snippet sha256: b16512a64176file sha256: 9726dbf00f84
Focused test komutu
CARGO_INCREMENTAL=0 cargo test -p aselsan_microkernel_simulation --test g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s420_terminal_reconciliation_ack -- --test-threads=1
proof: docs/M8.1-RPi5-G8l-S420-Terminal-Reconciliation-ACK-Proof.md
Registry schema v5 · generator website/scripts/generate-code-gates.mjs · Tam SHA-256: 3050638b71a684d8f8f947a8a6faa237a17fa8db5dc0db04fb207b668b462af9