ASELSANMicrokernel
S409 · SOURCE-BOUND GATE EVIDENCE

S409 · Live offer SGI delivery

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

S409Focused kod testiOperations id exactsource SHA exacttest target exact

operation: g8l-s409-live-offer-sgi-delivery-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–L343
kernel/src/g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s409_live_offer_sgi_delivery.rs::S409 live offer sgi delivery implementation
#![allow(unexpected_cfgs)]

//! S409 CPU0 SGI3 delivery, live-token validation, and exact raw EOI.
//!
//! S408 publishes a send receipt before issuing dedicated SGI3. S409 owns that
//! interrupt on CPU0, matches the send receipt to the pending S407 offer and
//! the active shared S247 exclusive token, writes the raw IAR value to EOI once,
//! and retains one linear delivery receipt. Admission remains a later gate.

use crate::g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s407_live_exclusion_offer_publication::G8lS407LiveExclusionOffer;
use crate::g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s408_live_offer_sgi_sender::{
    G8lS408LiveOfferSgiSendReceipt, S408_DIRECT_SCHEDULER_ACCESS_SITES,
    S408_EXPECTED_COMMAND, S408_EXPECTED_RAW_ACK, S408_PRODUCTION_GUARDED_DIRECT_ACCESS_SITES,
    S408_SGI_INTID, S408_SOURCE_AUDIT_UNITS, S408_SOURCE_CPU1,
    S408_SOURCE_MODEL_COVERED_DIRECT_ACCESS_SITES, S408_TARGET_CPU0,
    S408_UNROUTED_DIRECT_ACCESS_SITES,
};

pub const S409_SOURCE_AUDIT_UNITS: usize = S408_SOURCE_AUDIT_UNITS;
pub const S409_DIRECT_SCHEDULER_ACCESS_SITES: usize = S408_DIRECT_SCHEDULER_ACCESS_SITES;
pub const S409_SOURCE_MODEL_COVERED_DIRECT_ACCESS_SITES: usize =
    S408_SOURCE_MODEL_COVERED_DIRECT_ACCESS_SITES;
pub const S409_PRODUCTION_GUARDED_DIRECT_ACCESS_SITES: usize =
    S408_PRODUCTION_GUARDED_DIRECT_ACCESS_SITES;
pub const S409_UNROUTED_DIRECT_ACCESS_SITES: usize = S408_UNROUTED_DIRECT_ACCESS_SITES;
pub const S409_TARGET_CPU0: usize = S408_TARGET_CPU0;
pub const S409_PRODUCTION_IRQ_HANDLER_CALLSITES: usize = 1;
pub const S409_DELIVERY_RECEIPT_SLOT_CAPACITY: usize = 1;
pub const S409_IRQ_DELIVERY_COMPLETE: bool = true;
pub const S409_ADMISSION_CONSUMER_COMPLETE: bool = false;
pub const S409_END_TO_END_EXCLUSION_ADMISSION_COMPLETE: bool = false;

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum G8lS409LiveOfferSgiDeliveryError {
    InvalidPhase,
    WrongReceiverCpu,
    WrongInterruptId,
    WrongInterruptSource,
    SendReceiptDrift,
    OfferBindingDrift,
    GateTokenMismatch,
    RawEoiMismatch,
}

#[derive(Debug, PartialEq, Eq)]
pub struct G8lS409LiveOfferSgiAcknowledgement {
    raw_ack: u32,
    attempt_id: u64,
    provider_request_id: u64,
    exclusive_token: u64,
}

#[derive(Debug, PartialEq, Eq)]
pub struct G8lS409LiveOfferSgiDeliveryReceipt {
    raw_ack: u32,
    raw_eoi: u32,
    attempt_id: u64,
    provider_request_id: u64,
    exclusive_token: u64,
}

impl G8lS409LiveOfferSgiDeliveryReceipt {
    pub const fn raw_ack(&self) -> u32 {
        self.raw_ack
    }
    pub const fn raw_eoi(&self) -> u32 {
        self.raw_eoi
    }
    pub const fn attempt_id(&self) -> u64 {
        self.attempt_id
    }
    pub const fn provider_request_id(&self) -> u64 {
        self.provider_request_id
    }
    pub const fn exclusive_token(&self) -> u64 {
        self.exclusive_token
    }
    pub const fn gate_token_matched_while_live(&self) -> bool {
        true
    }

    pub const fn view(&self) -> G8lS409LiveOfferSgiDeliveryReceiptView {
        G8lS409LiveOfferSgiDeliveryReceiptView {
            raw_ack: self.raw_ack,
            raw_eoi: self.raw_eoi,
            attempt_id: self.attempt_id,
            provider_request_id: self.provider_request_id,
            exclusive_token: self.exclusive_token,
        }
    }
}

impl Drop for G8lS409LiveOfferSgiDeliveryReceipt {
    fn drop(&mut self) {}
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct G8lS409LiveOfferSgiDeliveryReceiptView {
    raw_ack: u32,
    raw_eoi: u32,
    attempt_id: u64,
    provider_request_id: u64,
    exclusive_token: u64,
}

impl G8lS409LiveOfferSgiDeliveryReceiptView {
    pub const fn raw_ack(&self) -> u32 {
        self.raw_ack
    }
    pub const fn raw_eoi(&self) -> u32 {
        self.raw_eoi
    }
    pub const fn attempt_id(&self) -> u64 {
        self.attempt_id
    }
    pub const fn provider_request_id(&self) -> u64 {
        self.provider_request_id
    }
    pub const fn exclusive_token(&self) -> u64 {
        self.exclusive_token
    }
    pub const fn gate_token_matched_while_live(&self) -> bool {
        true
    }
}

#[derive(Debug)]
pub struct G8lS409LiveOfferSgiDeliveryState {
    handling: bool,
    receipt: Option<G8lS409LiveOfferSgiDeliveryReceipt>,
}

impl G8lS409LiveOfferSgiDeliveryState {
    pub const fn new() -> Self {
        Self {
            handling: false,
            receipt: None,
        }
    }

    pub const fn receipt_pending(&self) -> bool {
        self.receipt.is_some()
    }

    pub fn pending_receipt_view(&self) -> Option<G8lS409LiveOfferSgiDeliveryReceiptView> {
        self.receipt
            .as_ref()
            .map(G8lS409LiveOfferSgiDeliveryReceipt::view)
    }

    pub fn begin_delivery(
        &mut self,
        receiver_cpu: usize,
        raw_ack: u32,
        send: G8lS408LiveOfferSgiSendReceipt,
        offer: G8lS407LiveExclusionOffer,
        active_exclusive_token: Option<u64>,
    ) -> Result<G8lS409LiveOfferSgiAcknowledgement, G8lS409LiveOfferSgiDeliveryError> {
        if self.handling || self.receipt.is_some() {
            return Err(G8lS409LiveOfferSgiDeliveryError::InvalidPhase);
        }
        if receiver_cpu != S409_TARGET_CPU0 {
            return Err(G8lS409LiveOfferSgiDeliveryError::WrongReceiverCpu);
        }
        if raw_ack & 0x3ff != S408_SGI_INTID {
            return Err(G8lS409LiveOfferSgiDeliveryError::WrongInterruptId);
        }
        if ((raw_ack >> 10) & 0x7) as usize != S408_SOURCE_CPU1 {
            return Err(G8lS409LiveOfferSgiDeliveryError::WrongInterruptSource);
        }
        if raw_ack != S408_EXPECTED_RAW_ACK || send.command() != S408_EXPECTED_COMMAND {
            return Err(G8lS409LiveOfferSgiDeliveryError::SendReceiptDrift);
        }
        if send.attempt_id() != offer.attempt_id
            || send.provider_request_id() != offer.provider_request_id
            || send.exclusive_token() != offer.exclusive_token
            || offer.source_cpu != S408_SOURCE_CPU1
            || offer.target_cpu != S409_TARGET_CPU0
            || !offer.requires_live_gate_match
            || offer.is_authority
            || offer.whole_scheduler_exclusion_proven
        {
            return Err(G8lS409LiveOfferSgiDeliveryError::OfferBindingDrift);
        }
        if active_exclusive_token != Some(offer.exclusive_token) {
            return Err(G8lS409LiveOfferSgiDeliveryError::GateTokenMismatch);
        }
        self.handling = true;
        Ok(G8lS409LiveOfferSgiAcknowledgement {
            raw_ack,
            attempt_id: offer.attempt_id,
            provider_request_id: offer.provider_request_id,
            exclusive_token: offer.exclusive_token,
        })
    }

    pub fn complete_eoi(
        &mut self,
        acknowledgement: G8lS409LiveOfferSgiAcknowledgement,
        raw_eoi: u32,
    ) -> Result<G8lS409LiveOfferSgiDeliveryReceiptView, G8lS409LiveOfferSgiDeliveryError> {
        if !self.handling || self.receipt.is_some() {
            return Err(G8lS409LiveOfferSgiDeliveryError::InvalidPhase);
        }
        if raw_eoi != acknowledgement.raw_ack {
            return Err(G8lS409LiveOfferSgiDeliveryError::RawEoiMismatch);
        }
        let receipt = G8lS409LiveOfferSgiDeliveryReceipt {
            raw_ack: acknowledgement.raw_ack,
            raw_eoi,
            attempt_id: acknowledgement.attempt_id,
            provider_request_id: acknowledgement.provider_request_id,
            exclusive_token: acknowledgement.exclusive_token,
        };
        let view = receipt.view();
        self.receipt = Some(receipt);
        self.handling = false;
        Ok(view)
    }

    pub fn take_receipt(
        &mut self,
        caller_cpu: usize,
    ) -> Result<Option<G8lS409LiveOfferSgiDeliveryReceipt>, G8lS409LiveOfferSgiDeliveryError> {
        if caller_cpu != S409_TARGET_CPU0 {
            return Err(G8lS409LiveOfferSgiDeliveryError::WrongReceiverCpu);
        }
        Ok(self.receipt.take())
    }
}

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

#[derive(Debug, PartialEq, Eq)]
pub enum G8lS409LiveOfferSgiDeliveryServiceError<E> {
    Delivery(G8lS409LiveOfferSgiDeliveryError),
    Eoi(E),
}

pub fn service_s409_model_live_offer_sgi_delivery<E, EndOfInterrupt>(
    delivery: &mut G8lS409LiveOfferSgiDeliveryState,
    receiver_cpu: usize,
    raw_ack: u32,
    send: G8lS408LiveOfferSgiSendReceipt,
    offer: G8lS407LiveExclusionOffer,
    active_exclusive_token: Option<u64>,
    mut end_of_interrupt: EndOfInterrupt,
) -> Result<G8lS409LiveOfferSgiDeliveryReceiptView, G8lS409LiveOfferSgiDeliveryServiceError<E>>
where
    EndOfInterrupt: FnMut(u32) -> Result<(), E>,
{
    let acknowledgement = delivery
        .begin_delivery(receiver_cpu, raw_ack, send, offer, active_exclusive_token)
        .map_err(G8lS409LiveOfferSgiDeliveryServiceError::Delivery)?;
    end_of_interrupt(raw_ack).map_err(G8lS409LiveOfferSgiDeliveryServiceError::Eoi)?;
    delivery
        .complete_eoi(acknowledgement, raw_ack)
        .map_err(G8lS409LiveOfferSgiDeliveryServiceError::Delivery)
}

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

/// Own SGI3. Every owned-path failure still writes exactly one fallback EOI.
#[cfg(all(target_arch = "aarch64", target_os = "none", feature = "board-rpi5"))]
pub fn try_handle_s409_live_offer_sgi_on_cpu0(ack: u32, int_id: u32) -> bool {
    use crate::g8l_runtime_contract::CPU0;
    if int_id != S408_SGI_INTID {
        return false;
    }
    let mut eoi_written = false;
    let result = (|| -> Result<(), ()> {
        let send = crate::g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s408_live_offer_sgi_sender::take_s408_live_offer_sgi_send_receipt_on_cpu0()
            .map_err(|_| ())?
            .ok_or(())?;
        let offer = crate::g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s407_live_exclusion_offer_publication::inspect_s407_live_exclusion_offer_on_cpu0()
            .map_err(|_| ())?
            .ok_or(())?;
        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();
        service_s409_model_live_offer_sgi_delivery(
            &mut S409_PRODUCTION_DELIVERY.lock(),
            crate::percpu::try_current_cpu_id().unwrap_or(usize::MAX),
            ack,
            send,
            offer,
            active_token,
            |_| {
                crate::arch::aarch64::gic::end_of_interrupt(ack);
                eoi_written = true;
                Ok::<(), ()>(())
            },
        )
        .map(|_| ())
        .map_err(|_| ())
    })();
    if result.is_ok() {
        let candidate = crate::g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s410_exclusion_admission_candidate_publication::service_s410_exclusion_admission_candidate_publication_on_cpu0();
        debug_assert!(candidate.is_ok());
        if candidate.is_ok() {
            let admission = crate::g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s411_ephemeral_exclusion_admission_constructor::service_s411_ephemeral_exclusion_admission_constructor_on_cpu0();
            debug_assert!(admission.is_ok());
            if admission.is_ok() {
                let join = unsafe {
                    crate::g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s413_exclusion_gated_s243_join::service_s413_exclusion_gated_s243_join_on_cpu0()
                };
                debug_assert!(join.is_ok());
                if let Ok(crate::g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s413_exclusion_gated_s243_join::G8lS413ExclusionGatedJoinOutcome::Published(receipt)) = join {
                    let ack = crate::g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s414_s243_join_ack_publication::service_s414_s243_join_ack_publication_on_cpu0(receipt);
                    debug_assert!(ack.is_ok());
                }
            }
        }
    }
    if !eoi_written {
        crate::arch::aarch64::gic::end_of_interrupt(ack);
    }
    debug_assert!(result.is_ok() && crate::percpu::try_current_cpu_id() == Some(CPU0));
    true
}

#[cfg(all(target_arch = "aarch64", target_os = "none", feature = "board-rpi5"))]
pub fn take_s409_live_offer_sgi_delivery_receipt_on_cpu0(
) -> Result<Option<G8lS409LiveOfferSgiDeliveryReceipt>, G8lS409LiveOfferSgiDeliveryError> {
    use crate::g8l_runtime_contract::CPU0;
    S409_PRODUCTION_DELIVERY.lock().take_receipt(CPU0)
}

#[cfg(all(target_arch = "aarch64", target_os = "none", feature = "board-rpi5"))]
pub fn inspect_s409_live_offer_sgi_delivery_receipt_on_cpu0(
) -> Result<Option<G8lS409LiveOfferSgiDeliveryReceiptView>, G8lS409LiveOfferSgiDeliveryError> {
    use crate::g8l_runtime_contract::CPU0;
    if crate::percpu::try_current_cpu_id() != Some(CPU0) {
        return Err(G8lS409LiveOfferSgiDeliveryError::WrongReceiverCpu);
    }
    Ok(S409_PRODUCTION_DELIVERY.lock().pending_receipt_view())
}
snippet sha256: 1f89b0022888file sha256: 1f89b0022888
02 · Doğrulayan test kodu

Operations komutuna bağlı focused test

tam dosyaL1–L377
simulation/tests/g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s409_live_offer_sgi_delivery.rs::S409 live offer sgi delivery focused tests
#![recursion_limit = "256"]

use aselsan_microkernel_simulation::g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s244_whole_scheduler_exclusion_admission_request::{
    service_s245_exclusion_admission_request, G8lS245WholeSchedulerExclusionAdmissionRequestState,
    S245_SOURCE_CPU0, S245_TARGET_CPU1,
};
use aselsan_microkernel_simulation::g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s246_whole_scheduler_read_access_guard::G8lS247WholeSchedulerAccessGate;
use aselsan_microkernel_simulation::g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s402_provider_invocation_observation_publication::{
    service_s402_model_provider_invocation_observation_publication,
    G8lS402ProviderInvocationObservationState,
};
use aselsan_microkernel_simulation::g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s404_scoped_authority_request_publication::{
    service_s404_model_scoped_authority_request_publication,
    G8lS404ScopedAuthorityRequestState,
};
use aselsan_microkernel_simulation::g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s407_live_exclusion_offer_publication::{
    try_publish_s407_model_live_exclusion_offer, G8lS407LiveExclusionOffer,
    G8lS407LiveExclusionOfferState,
};
use aselsan_microkernel_simulation::g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s408_live_offer_sgi_sender::{
    service_s408_model_live_offer_sgi_send, G8lS408LiveOfferSgiSendReceipt,
    G8lS408LiveOfferSgiSenderState, S408_DIRECT_SCHEDULER_ACCESS_SITES,
    S408_EXPECTED_ENABLE, S408_EXPECTED_RAW_ACK, S408_PRODUCTION_GUARDED_DIRECT_ACCESS_SITES,
    S408_SOURCE_AUDIT_UNITS, S408_SOURCE_MODEL_COVERED_DIRECT_ACCESS_SITES,
    S408_UNROUTED_DIRECT_ACCESS_SITES,
};
use aselsan_microkernel_simulation::g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s409_live_offer_sgi_delivery::*;

fn live_send() -> (
    G8lS247WholeSchedulerAccessGate,
    G8lS407LiveExclusionOffer,
    G8lS408LiveOfferSgiSendReceipt,
) {
    let gate = G8lS247WholeSchedulerAccessGate::new();
    let mut providers = G8lS245WholeSchedulerExclusionAdmissionRequestState::new();
    service_s245_exclusion_admission_request(&mut providers, S245_SOURCE_CPU0, true, true).unwrap();
    let mut observations = G8lS402ProviderInvocationObservationState::new();
    service_s402_model_provider_invocation_observation_publication(
        &mut observations,
        &gate,
        &mut providers,
        S245_TARGET_CPU1,
    )
    .unwrap();
    let mut scoped = G8lS404ScopedAuthorityRequestState::new();
    service_s404_model_scoped_authority_request_publication(
        &mut scoped,
        &mut observations,
        S245_SOURCE_CPU0,
    )
    .unwrap();
    service_s245_exclusion_admission_request(&mut providers, S245_SOURCE_CPU0, true, true).unwrap();
    let mut offers = G8lS407LiveExclusionOfferState::new();
    let offered = try_publish_s407_model_live_exclusion_offer(
        &mut offers,
        &gate,
        &mut providers,
        &mut scoped,
        S245_TARGET_CPU1,
    )
    .unwrap()
    .unwrap();
    let offer = offered.offer();
    let mut sender = G8lS408LiveOfferSgiSenderState::new();
    sender
        .prepare_receiver(0, 1, S408_EXPECTED_ENABLE, 1, 0)
        .unwrap();
    let send = service_s408_model_live_offer_sgi_send(&mut sender, 1, &offered).unwrap();
    core::mem::forget(offered);
    (gate, offer, send)
}

fn module_source() -> &'static str {
    include_str!("../../kernel/src/g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s409_live_offer_sgi_delivery.rs")
}

fn exception_source() -> &'static str {
    include_str!("../../kernel/src/arch/aarch64/exceptions.rs")
}

fn kernel_main_source() -> &'static str {
    include_str!("../../kernel/src/main.rs")
}

fn simulation_lib_source() -> &'static str {
    include_str!("../src/lib.rs")
}

#[test]
fn constants_promote_exact_sgi3_irq_delivery_only() {
    assert_eq!(S409_SOURCE_AUDIT_UNITS, 7);
    assert_eq!(S409_DIRECT_SCHEDULER_ACCESS_SITES, 113);
    assert_eq!(S409_SOURCE_MODEL_COVERED_DIRECT_ACCESS_SITES, 113);
    assert_eq!(S409_PRODUCTION_GUARDED_DIRECT_ACCESS_SITES, 113);
    assert_eq!(S409_UNROUTED_DIRECT_ACCESS_SITES, 0);
    assert_eq!(S409_PRODUCTION_IRQ_HANDLER_CALLSITES, 1);
    assert_eq!(S409_DELIVERY_RECEIPT_SLOT_CAPACITY, 1);
    assert!(S409_IRQ_DELIVERY_COMPLETE);
    assert!(!S409_ADMISSION_CONSUMER_COMPLETE);
    assert!(!S409_END_TO_END_EXCLUSION_ADMISSION_COMPLETE);
}

#[test]
fn s408_is_the_exact_sender_predecessor() {
    assert_eq!(S409_SOURCE_AUDIT_UNITS, S408_SOURCE_AUDIT_UNITS);
    assert_eq!(
        S409_DIRECT_SCHEDULER_ACCESS_SITES,
        S408_DIRECT_SCHEDULER_ACCESS_SITES
    );
    assert_eq!(
        S409_SOURCE_MODEL_COVERED_DIRECT_ACCESS_SITES,
        S408_SOURCE_MODEL_COVERED_DIRECT_ACCESS_SITES
    );
    assert_eq!(
        S409_PRODUCTION_GUARDED_DIRECT_ACCESS_SITES,
        S408_PRODUCTION_GUARDED_DIRECT_ACCESS_SITES
    );
    assert_eq!(
        S409_UNROUTED_DIRECT_ACCESS_SITES,
        S408_UNROUTED_DIRECT_ACCESS_SITES
    );
}

#[test]
fn exact_raw_ack_live_offer_and_gate_token_publish_post_eoi_receipt() {
    let (gate, offer, send) = live_send();
    let mut delivery = G8lS409LiveOfferSgiDeliveryState::new();
    let mut eoi_count = 0;
    let receipt = service_s409_model_live_offer_sgi_delivery(
        &mut delivery,
        S409_TARGET_CPU0,
        S408_EXPECTED_RAW_ACK,
        send,
        offer,
        gate.active_exclusive_token(),
        |raw| {
            assert_eq!(raw, S408_EXPECTED_RAW_ACK);
            eoi_count += 1;
            Ok::<(), ()>(())
        },
    )
    .unwrap();
    assert_eq!(eoi_count, 1);
    assert_eq!(receipt.raw_ack(), S408_EXPECTED_RAW_ACK);
    assert_eq!(receipt.raw_eoi(), S408_EXPECTED_RAW_ACK);
    assert_eq!(receipt.attempt_id(), 1);
    assert_eq!(receipt.provider_request_id(), 2);
    assert_eq!(receipt.exclusive_token(), 2);
    assert!(receipt.gate_token_matched_while_live());
    assert!(delivery.receipt_pending());
}

#[test]
fn wrong_receiver_raw_intid_source_or_gate_token_fails_before_eoi() {
    for (cpu, raw, token, expected) in [
        (
            1,
            S408_EXPECTED_RAW_ACK,
            Some(2),
            G8lS409LiveOfferSgiDeliveryError::WrongReceiverCpu,
        ),
        (
            0,
            4,
            Some(2),
            G8lS409LiveOfferSgiDeliveryError::WrongInterruptId,
        ),
        (
            0,
            3,
            Some(2),
            G8lS409LiveOfferSgiDeliveryError::WrongInterruptSource,
        ),
        (
            0,
            S408_EXPECTED_RAW_ACK,
            Some(9),
            G8lS409LiveOfferSgiDeliveryError::GateTokenMismatch,
        ),
    ] {
        let (_gate, offer, send) = live_send();
        let mut delivery = G8lS409LiveOfferSgiDeliveryState::new();
        let mut eoi_count = 0;
        assert_eq!(
            service_s409_model_live_offer_sgi_delivery(
                &mut delivery,
                cpu,
                raw,
                send,
                offer,
                token,
                |_| {
                    eoi_count += 1;
                    Ok::<(), ()>(())
                }
            ),
            Err(G8lS409LiveOfferSgiDeliveryServiceError::Delivery(expected))
        );
        assert_eq!(eoi_count, 0);
        assert!(!delivery.receipt_pending());
    }
}

#[test]
fn send_receipt_offer_identity_drift_fails_before_eoi() {
    let (_gate, mut offer, send) = live_send();
    offer.provider_request_id += 1;
    let mut delivery = G8lS409LiveOfferSgiDeliveryState::new();
    assert!(matches!(
        service_s409_model_live_offer_sgi_delivery(
            &mut delivery,
            0,
            S408_EXPECTED_RAW_ACK,
            send,
            offer,
            Some(2),
            |_| Ok::<(), ()>(())
        ),
        Err(G8lS409LiveOfferSgiDeliveryServiceError::Delivery(
            G8lS409LiveOfferSgiDeliveryError::OfferBindingDrift
        ))
    ));
}

#[test]
fn eoi_failure_does_not_publish_delivery_receipt() {
    let (gate, offer, send) = live_send();
    let mut delivery = G8lS409LiveOfferSgiDeliveryState::new();
    assert!(matches!(
        service_s409_model_live_offer_sgi_delivery(
            &mut delivery,
            0,
            S408_EXPECTED_RAW_ACK,
            send,
            offer,
            gate.active_exclusive_token(),
            |_| Err("eoi")
        ),
        Err(G8lS409LiveOfferSgiDeliveryServiceError::Eoi("eoi"))
    ));
    assert!(!delivery.receipt_pending());
}

#[test]
fn duplicate_delivery_is_rejected_without_second_eoi() {
    let (gate, offer, send) = live_send();
    let mut delivery = G8lS409LiveOfferSgiDeliveryState::new();
    service_s409_model_live_offer_sgi_delivery(
        &mut delivery,
        0,
        S408_EXPECTED_RAW_ACK,
        send,
        offer,
        gate.active_exclusive_token(),
        |_| Ok::<(), ()>(()),
    )
    .unwrap();
    let mut second_eoi = 0;
    assert!(matches!(
        service_s409_model_live_offer_sgi_delivery(
            &mut delivery,
            0,
            S408_EXPECTED_RAW_ACK,
            send,
            offer,
            gate.active_exclusive_token(),
            |_| {
                second_eoi += 1;
                Ok::<(), ()>(())
            }
        ),
        Err(G8lS409LiveOfferSgiDeliveryServiceError::Delivery(
            G8lS409LiveOfferSgiDeliveryError::InvalidPhase
        ))
    ));
    assert_eq!(second_eoi, 0);
}

#[test]
fn receipt_is_linear_and_cpu0_take_is_one_shot() {
    assert!(core::mem::needs_drop::<G8lS409LiveOfferSgiDeliveryReceipt>());
    let (gate, offer, send) = live_send();
    let mut delivery = G8lS409LiveOfferSgiDeliveryState::new();
    service_s409_model_live_offer_sgi_delivery(
        &mut delivery,
        0,
        S408_EXPECTED_RAW_ACK,
        send,
        offer,
        gate.active_exclusive_token(),
        |_| Ok::<(), ()>(()),
    )
    .unwrap();
    assert!(matches!(
        delivery.take_receipt(1),
        Err(G8lS409LiveOfferSgiDeliveryError::WrongReceiverCpu)
    ));
    assert!(delivery.take_receipt(0).unwrap().is_some());
    assert!(delivery.take_receipt(0).unwrap().is_none());
}

#[test]
fn model_orders_validation_before_eoi_before_receipt_publish() {
    let source = module_source();
    let start = source
        .find("pub fn service_s409_model_live_offer_sgi_delivery")
        .unwrap();
    let function: String = source[start..].split_whitespace().collect();
    let validate = function.find("delivery.begin_delivery(").unwrap();
    let eoi = function.find("end_of_interrupt(raw_ack)").unwrap();
    let publish = function.find("delivery.complete_eoi(").unwrap();
    assert!(validate < eoi && eoi < publish);
}

#[test]
fn irq_interceptor_owns_sgi3_before_s240_sgi2_and_returns_immediately() {
    let source = exception_source();
    let s409 = source
        .find("try_handle_s409_live_offer_sgi_on_cpu0")
        .unwrap();
    let s240 = source
        .find("try_handle_s179_notification_sgi_on_cpu0")
        .unwrap();
    assert!(s409 < s240);
    assert!(source[s409..s240].contains("return resume_ctx"));
}

#[test]
fn production_handler_matches_offer_and_shared_s247_token_before_raw_eoi() {
    let source = module_source();
    let start = source
        .find("pub fn try_handle_s409_live_offer_sgi_on_cpu0")
        .unwrap();
    let function = &source[start..];
    let offer = function
        .find("inspect_s407_live_exclusion_offer_on_cpu0")
        .unwrap();
    let gate = function
        .find("S247_PRODUCTION_WHOLE_SCHEDULER_ACCESS_GATE")
        .unwrap();
    let eoi = function.find("end_of_interrupt(ack)").unwrap();
    assert!(offer < eoi && gate < eoi);
}

#[test]
fn production_handler_writes_one_fallback_eoi_on_any_owned_sgi3_failure() {
    let source = module_source();
    assert!(source.contains("if !eoi_written"));
    assert_eq!(source.matches("end_of_interrupt(ack)").count(), 2);
}

#[test]
fn s409_does_not_publish_admission_or_enter_s243() {
    let source = module_source();
    for forbidden in [
        "publish_s244",
        "service_s243_deferred_authority_receipt_join",
        "addr_of!(",
        "addr_of_mut!(",
    ] {
        assert!(
            !source.contains(forbidden),
            "forbidden promotion: {forbidden}"
        );
    }
}

#[test]
fn s409_and_its_exact_s410_candidate_publisher_are_registered_separately() {
    let s409 = "g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s409_live_offer_sgi_delivery";
    let s410 = "g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s410_exclusion_admission_candidate_publication";
    assert!(kernel_main_source().contains(&format!("mod {s409};")));
    assert!(simulation_lib_source().contains(&format!("pub mod {s409};")));
    assert!(kernel_main_source().contains(&format!("mod {s410};")));
    assert!(simulation_lib_source().contains(&format!("pub mod {s410};")));
}
snippet sha256: 0ad35e21102bfile sha256: 0ad35e21102b
03 · Kapı kimlik kaydı

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

tam Operations kaydıL236–L252
website/src/lib/operations.ts::g8l-s409-live-offer-sgi-delivery-partial
  {
    id: "g8l-s409-live-offer-sgi-delivery-partial",
    sequence: 409,
    slug: "live_offer_sgi_delivery",
    title: "Live offer SGI delivery",
    focusedTests: 14,
    sourceBytes: 13539,
    sourceSha256:
      "1f89b002288893a8bf71e9ecbf78e10b967bcbb5706fb89c2d8677da7805073b",
    testBytes: 13270,
    testSha256:
      "0ad35e21102b3ba9ded8aee0c1154a7c5b70041949fd45ebcb13d0414db81696",
    acceptance:
      "CPU0 IRQ interceptor exact SGI3/raw ACK/source tuple'ını doğrular, typed delivery receipt'i capacity-one slot'a koyar ve raw EOI sırasını korur.",
    retainedBoundary:
      "IRQ delivery tamamdır; admission candidate consumer bu kapıda çalıştırılmaz.",
  },
snippet sha256: 93fd6181afbffile 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_s409_live_offer_sgi_delivery -- --test-threads=1
proof: docs/M8.1-RPi5-G8l-S409-Live-Offer-SGI-Delivery-Proof.md
Registry schema v5 · generator website/scripts/generate-code-gates.mjs · Tam SHA-256: 91d38c7b6222f0b4c117be786454853543da55a160e543d9b951057cc20dcc06