Skip to main content

xlog_cuda/provider/
resident_schedule.rs

1use std::sync::Arc;
2
3use cudarc::driver::{sys, CudaStream, DeviceRepr, LaunchConfig};
4use xlog_core::{Result, ScalarType, XlogError};
5
6use super::resident_filter_project::ResidentFilterScratch;
7use super::resident_relational::{
8    ResidentConvergenceControl, ResidentDeviceTrace, ResidentJoinWorkspace, ResidentPackedReceipt,
9    ResidentSchemaWinners, ResidentSetWorkspace, ResidentTerminalStatus,
10};
11use super::CudaKernelProvider;
12use crate::cuda_compat::{AsKernelParam, DeviceSlice, LaunchAsync};
13use crate::cuda_graph::{
14    CapturedCudaGraph, ConditionalCudaGraphBody, ConditionalCudaGraphSequenceBuilder, CudaGraphNode,
15};
16use crate::device_runtime::{StreamId, XlogDeviceRuntime};
17use crate::launch::{EnqueuedLaunch, LaunchEnqueueError, LaunchRecorder};
18use crate::memory::{
19    CudaBuffer, GpuMemoryReservation, RuntimeAllocationIdentity, TrackedCudaSlice,
20};
21
22const RESIDENT_SCHEDULE_MAX_ARITY: usize = 17;
23const RESIDENT_SCHEDULE_BLOCK_SIZE: u32 = 256;
24pub const RESIDENT_SCHEDULE_ABI_VERSION: u32 = 3;
25const RESIDENT_SCHEDULE_MAX_ROWS: u64 = 65_536;
26const MODULE: &str = "xlog_resident_schedule";
27const KERNEL: &str = "resident_schedule_execute";
28pub const RESIDENT_SCHEDULE_SLOT_SOURCE: u32 = 1;
29pub const RESIDENT_SCHEDULE_SLOT_PERMANENT: u32 = 2;
30pub const RESIDENT_SCHEDULE_SLOT_DEFINED: u32 = 4;
31const SOURCE_SLOT: u32 = RESIDENT_SCHEDULE_SLOT_SOURCE;
32
33#[expect(
34    clippy::too_many_arguments,
35    reason = "allocation validation compares the complete recorded allocation identity against its expected runtime, stream, and device fields"
36)]
37fn validate_runtime_allocation_fields(
38    manager_id: usize,
39    allocation_ptr: u64,
40    allocation_bytes: usize,
41    block_id: crate::device_runtime::BlockId,
42    block_bytes: usize,
43    block_state: crate::device_runtime::BlockState,
44    expected_manager_id: usize,
45    expected_device_ordinal: u32,
46) -> Result<(u64, u64)> {
47    if manager_id != expected_manager_id {
48        return Err(XlogError::Kernel(
49            "resident schedule allocation belongs to a foreign memory manager".into(),
50        ));
51    }
52    if block_state != crate::device_runtime::BlockState::Live {
53        return Err(XlogError::Kernel(
54            "resident schedule allocation runtime block is not live".into(),
55        ));
56    }
57    if block_id.device_ordinal != expected_device_ordinal {
58        return Err(XlogError::Kernel(
59            "resident schedule allocation belongs to a foreign CUDA device".into(),
60        ));
61    }
62    let allocation_bytes = u64::try_from(allocation_bytes)
63        .map_err(|_| XlogError::Kernel("resident schedule allocation size overflow".into()))?;
64    let block_bytes = u64::try_from(block_bytes)
65        .map_err(|_| XlogError::Kernel("resident schedule runtime block size overflow".into()))?;
66    let allocation_end = allocation_ptr
67        .checked_add(allocation_bytes)
68        .ok_or_else(|| XlogError::Kernel("resident schedule allocation range overflow".into()))?;
69    let block_end = block_id.ptr.checked_add(block_bytes).ok_or_else(|| {
70        XlogError::Kernel("resident schedule runtime block range overflow".into())
71    })?;
72    if allocation_ptr < block_id.ptr || allocation_end > block_end {
73        return Err(XlogError::Kernel(
74            "resident schedule allocation range is outside its runtime block".into(),
75        ));
76    }
77    Ok((allocation_ptr, allocation_end))
78}
79
80fn validate_runtime_allocation_identity(
81    identity: &RuntimeAllocationIdentity,
82    domain: &ResidentExecutionDomain,
83) -> Result<(u64, u64)> {
84    let range = validate_runtime_allocation_fields(
85        identity.manager_id,
86        identity.allocation_ptr,
87        identity.allocation_bytes,
88        identity.block_id,
89        identity.block_bytes,
90        identity.block_state,
91        domain.memory_manager_identity,
92        domain.runtime.device_ordinal(),
93    )?;
94    if !Arc::ptr_eq(&identity.context, &domain.context)
95        || identity.context.cu_ctx() != domain.context.cu_ctx()
96    {
97        return Err(XlogError::Kernel(
98            "resident schedule allocation belongs to a foreign CUDA context".into(),
99        ));
100    }
101    Ok(range)
102}
103
104fn validate_schedule_allocation(
105    identity: Option<RuntimeAllocationIdentity>,
106    domain: &ResidentExecutionDomain,
107    ranges: &mut Vec<(u64, u64)>,
108) -> Result<RuntimeAllocationIdentity> {
109    let identity = identity.ok_or_else(|| {
110        XlogError::Kernel(
111            "resident schedule requires every allocation to be runtime tracked".into(),
112        )
113    })?;
114    let range = validate_runtime_allocation_identity(&identity, domain)?;
115    insert_nonoverlapping_allocation_range(ranges, range)?;
116    Ok(identity)
117}
118
119fn insert_nonoverlapping_allocation_range(
120    ranges: &mut Vec<(u64, u64)>,
121    range: (u64, u64),
122) -> Result<()> {
123    if range.0 >= range.1 {
124        return Err(XlogError::Kernel(
125            "resident schedule allocation range is empty or reversed".into(),
126        ));
127    }
128    if ranges
129        .iter()
130        .any(|previous| range.0 < previous.1 && previous.0 < range.1)
131    {
132        return Err(XlogError::Kernel(
133            "resident schedule allocations have overlapping byte ranges".into(),
134        ));
135    }
136    ranges.push(range);
137    Ok(())
138}
139
140fn validate_receipt_slot_mapping(
141    receipt_slots: &[u32],
142    slot_flags: &[u32],
143    head_count: u32,
144) -> Result<Vec<usize>> {
145    let head_count = usize::try_from(head_count)
146        .map_err(|_| XlogError::Kernel("resident schedule head count overflow".into()))?;
147    if receipt_slots.len() != head_count {
148        return Err(XlogError::Kernel(
149            "resident schedule receipt slot count does not match its head count".into(),
150        ));
151    }
152    let mut validated = Vec::with_capacity(receipt_slots.len());
153    for &slot in receipt_slots {
154        let slot = usize::try_from(slot)
155            .map_err(|_| XlogError::Kernel("resident schedule receipt slot overflow".into()))?;
156        let flags = *slot_flags.get(slot).ok_or_else(|| {
157            XlogError::Kernel("resident schedule receipt slot is out of range".into())
158        })?;
159        if flags & RESIDENT_SCHEDULE_SLOT_SOURCE != 0
160            || flags & RESIDENT_SCHEDULE_SLOT_PERMANENT == 0
161        {
162            return Err(XlogError::Kernel(
163                "resident schedule receipt slot is not a permanent output".into(),
164            ));
165        }
166        if validated.contains(&slot) {
167            return Err(XlogError::Kernel(
168                "resident schedule receipt slots contain a duplicate".into(),
169            ));
170        }
171        validated.push(slot);
172    }
173    Ok(validated)
174}
175
176pub(crate) fn validate_execution_domain(
177    provider: &CudaKernelProvider,
178    domain: &ResidentExecutionDomain,
179) -> Result<()> {
180    let manager_id = Arc::as_ptr(provider.memory()) as usize;
181    let manager_runtime = provider.memory().runtime().ok_or_else(|| {
182        XlogError::Kernel(
183            "resident execution domain requires a runtime-backed memory manager".into(),
184        )
185    })?;
186    if domain.provider_identity != provider.provider_identity()
187        || domain.memory_manager_identity != manager_id
188        || !Arc::ptr_eq(manager_runtime, &domain.runtime)
189        || !Arc::ptr_eq(provider.device(), provider.memory().device())
190        || !Arc::ptr_eq(provider.device(), domain.runtime.device())
191    {
192        return Err(XlogError::Kernel(
193            "resident execution domain provider, manager, and runtime identities differ".into(),
194        ));
195    }
196    let device_ordinal = u32::try_from(provider.device().ordinal()).map_err(|_| {
197        XlogError::Kernel("resident execution domain device ordinal overflow".into())
198    })?;
199    if domain.runtime.device_ordinal() != device_ordinal
200        || !domain.runtime.supports_block_use_tracking()
201    {
202        return Err(XlogError::Kernel(
203            "resident execution domain runtime is incompatible with the provider".into(),
204        ));
205    }
206    let resolved_stream = domain
207        .runtime
208        .stream_pool()
209        .resolve(domain.stream_id)
210        .ok_or_else(|| {
211            XlogError::Kernel(
212                "resident execution domain stream id is not owned by the runtime".into(),
213            )
214        })?;
215    if !Arc::ptr_eq(&resolved_stream, &domain.stream) {
216        return Err(XlogError::Kernel(
217            "resident execution domain stream does not match its runtime stream id".into(),
218        ));
219    }
220    let provider_context = provider.device().inner().stream().context();
221    if !Arc::ptr_eq(&domain.context, provider_context)
222        || !Arc::ptr_eq(domain.stream.context(), &domain.context)
223        || domain.context.cu_ctx() != provider_context.cu_ctx()
224        || domain.stream.context().cu_ctx() != domain.context.cu_ctx()
225    {
226        return Err(XlogError::Kernel(
227            "resident execution domain belongs to a foreign CUDA context".into(),
228        ));
229    }
230    Ok(())
231}
232
233/// Typed operation tag with the same four-byte representation consumed by CUDA.
234#[repr(u32)]
235#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord)]
236pub enum ResidentScheduleOpKind {
237    #[default]
238    Unit = 0,
239    Scan = 1,
240    Filter = 2,
241    Project = 3,
242    JoinInner = 4,
243    JoinSemi = 5,
244    Union = 6,
245    Diff = 7,
246    TestStatus = 8,
247    TraceDelta = 9,
248}
249
250const OP_UNIT: ResidentScheduleOpKind = ResidentScheduleOpKind::Unit;
251const OP_SCAN: ResidentScheduleOpKind = ResidentScheduleOpKind::Scan;
252const OP_FILTER: ResidentScheduleOpKind = ResidentScheduleOpKind::Filter;
253const OP_PROJECT: ResidentScheduleOpKind = ResidentScheduleOpKind::Project;
254const OP_JOIN_INNER: ResidentScheduleOpKind = ResidentScheduleOpKind::JoinInner;
255const OP_JOIN_SEMI: ResidentScheduleOpKind = ResidentScheduleOpKind::JoinSemi;
256const OP_UNION: ResidentScheduleOpKind = ResidentScheduleOpKind::Union;
257const OP_DIFF: ResidentScheduleOpKind = ResidentScheduleOpKind::Diff;
258const OP_TEST_STATUS: ResidentScheduleOpKind = ResidentScheduleOpKind::TestStatus;
259const OP_TRACE_DELTA: ResidentScheduleOpKind = ResidentScheduleOpKind::TraceDelta;
260
261pub const RESIDENT_SCHEDULE_OP_MARK_NOVELTY: u32 = 1;
262pub const RESIDENT_SCHEDULE_OP_MARK_SCHEMA_WINNER: u32 = 2;
263pub const RESIDENT_SCHEDULE_TRACE_SEMANTIC_GUARD: u32 = 1;
264pub const RESIDENT_SCHEDULE_REGION_INITIALIZE: u32 = 1;
265pub const RESIDENT_SCHEDULE_REGION_SCC_BEGIN: u32 = 2;
266pub const RESIDENT_SCHEDULE_REGION_RECURSIVE: u32 = 4;
267pub const RESIDENT_SCHEDULE_REGION_FINALIZE: u32 = 8;
268
269/// Device relation view shared by every compact resident operation.
270#[repr(C, align(8))]
271#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
272pub struct ResidentRelationView {
273    pub columns: [u64; RESIDENT_SCHEDULE_MAX_ARITY],
274    pub widths: [u32; RESIDENT_SCHEDULE_MAX_ARITY],
275    pub arity: u32,
276    pub capacity: u32,
277    pub reserved: u32,
278    pub num_rows: u64,
279}
280
281// SAFETY: stable C layout, no references, and every field accepts all bit patterns.
282unsafe impl DeviceRepr for ResidentRelationView {}
283
284/// Fixed-address relation table entry with replay-generation metadata.
285#[repr(C, align(16))]
286#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
287pub struct ResidentRelationSlot {
288    pub relation: ResidentRelationView,
289    pub generation: u32,
290    pub flags: u32,
291    pub initial_count: u32,
292    pub schema_tag: u32,
293}
294
295// SAFETY: stable C layout, no references, and every field accepts all bit patterns.
296unsafe impl DeviceRepr for ResidentRelationSlot {}
297
298/// One operation in stable schedule order.
299#[repr(C)]
300#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
301pub struct ResidentOpDescriptor {
302    pub kind: ResidentScheduleOpKind,
303    pub flags: u32,
304    pub op_id: u32,
305    pub out: u32,
306    pub in0: u32,
307    pub in1: u32,
308    pub in0_generation: u32,
309    pub in1_generation: u32,
310    pub out_generation: u32,
311    pub aux_offset: u32,
312    pub aux_count: u32,
313    pub left_key: u32,
314    pub right_key: u32,
315    pub scan_delta: u32,
316    pub filter_delta: u32,
317    pub schema_winner_head: u32,
318    pub schema_winner_id: u32,
319    pub reserved: u32,
320}
321
322// SAFETY: stable C layout, no references, and `kind` is created through its
323// public typed variants before this host-owned descriptor is uploaded.
324unsafe impl DeviceRepr for ResidentOpDescriptor {}
325
326impl ResidentOpDescriptor {
327    /// Construct a nullary Unit leaf that writes one logical empty tuple.
328    pub fn unit(op_id: u32, out: u32, out_generation: u32) -> Self {
329        Self {
330            kind: ResidentScheduleOpKind::Unit,
331            op_id,
332            out,
333            out_generation,
334            ..Self::default()
335        }
336    }
337
338    /// Construct a Scan leaf that binds an existing immutable source slot.
339    pub fn scan(op_id: u32, source: u32, source_generation: u32) -> Self {
340        Self {
341            kind: ResidentScheduleOpKind::Scan,
342            op_id,
343            out: source,
344            in0: source,
345            in0_generation: source_generation,
346            out_generation: source_generation,
347            ..Self::default()
348        }
349    }
350
351    pub fn with_schema_winner(mut self, head: u32, schema_id: u32) -> Self {
352        self.flags |= RESIDENT_SCHEDULE_OP_MARK_SCHEMA_WINNER;
353        self.schema_winner_head = head;
354        self.schema_winner_id = schema_id;
355        self
356    }
357
358    pub fn test_status(status: ResidentTerminalStatus) -> Result<Self> {
359        if status.reserved != 0 {
360            return Err(XlogError::Kernel(
361                "resident schedule test status reserved field is nonzero".into(),
362            ));
363        }
364        Ok(Self {
365            kind: OP_TEST_STATUS,
366            op_id: status.op_id,
367            out: status.code,
368            in0: status.resource_code,
369            in1: status.iterations,
370            in0_generation: status.limit,
371            in1_generation: status.reserved,
372            out_generation: status.required as u32,
373            aux_offset: (status.required >> 32) as u32,
374            aux_count: status.capacity as u32,
375            left_key: (status.capacity >> 32) as u32,
376            ..Default::default()
377        })
378    }
379
380    pub fn trace_delta(
381        scan_delta: u32,
382        filter_delta: u32,
383        semantic_guard: Option<(u32, u32)>,
384    ) -> Self {
385        let (flags, in0, in0_generation) = match semantic_guard {
386            Some((slot, generation)) => (RESIDENT_SCHEDULE_TRACE_SEMANTIC_GUARD, slot, generation),
387            None => (0, 0, 0),
388        };
389        Self {
390            kind: OP_TRACE_DELTA,
391            flags,
392            in0,
393            in0_generation,
394            scan_delta,
395            filter_delta,
396            ..Default::default()
397        }
398    }
399}
400
401fn decode_test_status(op: &ResidentOpDescriptor) -> Result<ResidentTerminalStatus> {
402    if op.kind != OP_TEST_STATUS
403        || op.flags != 0
404        || op.in1_generation != 0
405        || op.right_key != 0
406        || op.scan_delta != 0
407        || op.filter_delta != 0
408        || op.schema_winner_head != 0
409        || op.schema_winner_id != 0
410        || op.reserved != 0
411    {
412        return Err(XlogError::Kernel(
413            "resident schedule test status descriptor is invalid".into(),
414        ));
415    }
416    Ok(ResidentTerminalStatus {
417        code: op.out,
418        op_id: op.op_id,
419        resource_code: op.in0,
420        iterations: op.in1,
421        limit: op.in0_generation,
422        reserved: op.in1_generation,
423        required: u64::from(op.out_generation) | (u64::from(op.aux_offset) << 32),
424        capacity: u64::from(op.aux_count) | (u64::from(op.left_key) << 32),
425    })
426}
427
428type ResidentTraceDelta = (u32, u32, Option<(u32, u32)>);
429
430fn decode_trace_delta(op: &ResidentOpDescriptor) -> Result<ResidentTraceDelta> {
431    let has_semantic_guard = op.flags & RESIDENT_SCHEDULE_TRACE_SEMANTIC_GUARD != 0;
432    if op.kind != OP_TRACE_DELTA
433        || op.flags & !RESIDENT_SCHEDULE_TRACE_SEMANTIC_GUARD != 0
434        || op.op_id != 0
435        || op.out != 0
436        || op.in1 != 0
437        || op.in1_generation != 0
438        || op.out_generation != 0
439        || op.aux_offset != 0
440        || op.aux_count != 0
441        || op.left_key != 0
442        || op.right_key != 0
443        || op.schema_winner_head != 0
444        || op.schema_winner_id != 0
445        || op.reserved != 0
446        || (!has_semantic_guard && (op.in0 != 0 || op.in0_generation != 0))
447    {
448        return Err(XlogError::Kernel(
449            "resident schedule trace delta descriptor is invalid".into(),
450        ));
451    }
452    Ok((
453        op.scan_delta,
454        op.filter_delta,
455        has_semantic_guard.then_some((op.in0, op.in0_generation)),
456    ))
457}
458
459/// Contiguous operation range with an explicit barrier boundary.
460#[repr(C)]
461#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
462pub struct ResidentWaveDescriptor {
463    pub first_op: u32,
464    pub op_count: u32,
465    pub flags: u32,
466    pub reserved: u32,
467}
468
469// SAFETY: stable C layout, no references, and every field accepts all bit patterns.
470unsafe impl DeviceRepr for ResidentWaveDescriptor {}
471
472/// Contiguous wave range executed by one cooperative launch.
473#[repr(C)]
474#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
475pub struct ResidentRegionDescriptor {
476    pub first_wave: u32,
477    pub wave_count: u32,
478    pub iteration_limit: u32,
479    pub op_id: u32,
480    pub flags: u32,
481    pub first_slot: u32,
482    pub slot_count: u32,
483    pub generation_offset: u32,
484}
485
486// SAFETY: stable C layout, no references, and every field accepts all bit patterns.
487unsafe impl DeviceRepr for ResidentRegionDescriptor {}
488
489/// Device pointers and exact bounds for one compact resident schedule.
490#[repr(C, align(16))]
491#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
492pub struct ResidentScheduleHeader {
493    pub slots: u64,
494    pub ops: u64,
495    pub waves: u64,
496    pub regions: u64,
497    pub generation_metadata: u64,
498    pub filter_comparisons: u64,
499    pub project_expressions: u64,
500    pub filter_mask: u64,
501    pub filter_prefix: u64,
502    pub filter_block_sums: u64,
503    pub filter_block_offsets: u64,
504    pub set_slots: u64,
505    pub set_required: u64,
506    pub join_buckets: u64,
507    pub join_next: u64,
508    pub join_required: u64,
509    pub status: u64,
510    pub changed: u64,
511    pub iterations: u64,
512    pub scan_trace: u64,
513    pub filter_trace: u64,
514    pub semantic_scan_trace: u64,
515    pub semantic_filter_trace: u64,
516    pub schema_seen_nonempty: u64,
517    pub schema_winner_ids: u64,
518    pub receipt_table: u64,
519    pub receipt_bytes: u64,
520    pub slot_count: u32,
521    pub op_count: u32,
522    pub wave_count: u32,
523    pub region_count: u32,
524    pub filter_comparison_count: u32,
525    pub project_expression_count: u32,
526    pub filter_capacity: u32,
527    pub filter_block_count: u32,
528    pub set_slot_mask: u32,
529    pub set_candidate_capacity: u32,
530    pub join_bucket_mask: u32,
531    pub join_right_capacity: u32,
532    pub schema_winner_count: u32,
533    pub receipt_count: u32,
534    pub receipt_byte_count: u32,
535    pub generation_metadata_count: u32,
536    pub abi_version: u32,
537    pub reserved: u32,
538}
539
540// SAFETY: stable C layout, no references, and every field accepts all bit patterns.
541unsafe impl DeviceRepr for ResidentScheduleHeader {}
542
543/// One flattened filter comparison consumed by the compact schedule.
544#[repr(C, align(8))]
545#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
546pub struct ResidentFilterComparisonDescriptor {
547    pub left_kind: u32,
548    pub left_column: u32,
549    pub right_kind: u32,
550    pub right_column: u32,
551    pub op: u32,
552    pub width: u32,
553    pub reserved_zero: u32,
554    pub reserved_one: u32,
555    pub left_constant: u64,
556    pub right_constant: u64,
557}
558
559// SAFETY: stable C layout, no references, and every field accepts all bit patterns.
560unsafe impl DeviceRepr for ResidentFilterComparisonDescriptor {}
561
562impl ResidentFilterComparisonDescriptor {
563    pub fn column_constant(column: u32, op: u32, width: u32, constant: u64) -> Self {
564        Self {
565            left_kind: 0,
566            left_column: column,
567            right_kind: 1,
568            right_column: 0,
569            op,
570            width,
571            reserved_zero: 0,
572            reserved_one: 0,
573            left_constant: 0,
574            right_constant: constant,
575        }
576    }
577}
578
579/// One fixed-width projection expression consumed by the compact schedule.
580#[repr(C, align(8))]
581#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
582pub struct ResidentProjectExpressionDescriptor {
583    pub kind: u32,
584    pub column: u32,
585    pub width: u32,
586    pub reserved: u32,
587    pub constant: u64,
588}
589
590// SAFETY: stable C layout, no references, and every field accepts all bit patterns.
591unsafe impl DeviceRepr for ResidentProjectExpressionDescriptor {}
592
593impl ResidentProjectExpressionDescriptor {
594    pub fn column(column: u32, width: u32) -> Self {
595        Self {
596            kind: 0,
597            column,
598            width,
599            reserved: 0,
600            constant: 0,
601        }
602    }
603
604    pub fn constant(width: u32, constant: u64) -> Self {
605        Self {
606            kind: 1,
607            column: 0,
608            width,
609            reserved: 0,
610            constant,
611        }
612    }
613}
614
615/// Exclusive graph-lifetime binding for one stable relation slot.
616pub enum ResidentScheduleRelation<'a> {
617    Source {
618        buffer: &'a CudaBuffer,
619        generation: u32,
620        initial_count: u32,
621    },
622    Output {
623        buffer: &'a mut CudaBuffer,
624        generation: u32,
625    },
626}
627
628/// Transient slot ownership used while materializing graph-free schedule metadata.
629pub enum ResidentScheduleSlotBinding<'a> {
630    Source {
631        buffer: &'a CudaBuffer,
632        generation: u32,
633        initial_count: u32,
634    },
635    Resident {
636        buffer: &'a CudaBuffer,
637        generation: u32,
638        permanent: bool,
639    },
640}
641
642impl<'a> ResidentScheduleSlotBinding<'a> {
643    pub fn source(buffer: &'a CudaBuffer, generation: u32) -> Result<Self> {
644        let initial_count = buffer.cached_row_count().ok_or_else(|| {
645            XlogError::Kernel(
646                "resident schedule source requires a cold-path cached logical row count".into(),
647            )
648        })?;
649        if u64::from(initial_count) > buffer.num_rows() {
650            return Err(XlogError::Kernel(
651                "resident schedule source count exceeds capacity".into(),
652            ));
653        }
654        Ok(Self::Source {
655            buffer,
656            generation,
657            initial_count,
658        })
659    }
660
661    pub fn scratch(buffer: &'a CudaBuffer, generation: u32) -> Self {
662        Self::Resident {
663            buffer,
664            generation,
665            permanent: false,
666        }
667    }
668
669    pub fn permanent(buffer: &'a CudaBuffer, generation: u32) -> Self {
670        Self::Resident {
671            buffer,
672            generation,
673            permanent: true,
674        }
675    }
676
677    fn buffer(&self) -> &CudaBuffer {
678        match self {
679            Self::Source { buffer, .. } | Self::Resident { buffer, .. } => buffer,
680        }
681    }
682
683    fn generation(&self) -> u32 {
684        match self {
685            Self::Source { generation, .. } | Self::Resident { generation, .. } => *generation,
686        }
687    }
688
689    fn flags(&self) -> u32 {
690        match self {
691            Self::Source { .. } => RESIDENT_SCHEDULE_SLOT_SOURCE | RESIDENT_SCHEDULE_SLOT_DEFINED,
692            Self::Resident {
693                permanent: true, ..
694            } => RESIDENT_SCHEDULE_SLOT_PERMANENT | RESIDENT_SCHEDULE_SLOT_DEFINED,
695            Self::Resident {
696                permanent: false, ..
697            } => 0,
698        }
699    }
700
701    fn initial_count(&self) -> u32 {
702        match self {
703            Self::Source { initial_count, .. } => *initial_count,
704            Self::Resident { .. } => 0,
705        }
706    }
707
708    /// Record the externally owned relation with its exact scheduler access.
709    pub fn record_uses(&self, recorder: &mut LaunchRecorder) {
710        match self {
711            Self::Source { buffer, .. } => {
712                for column in buffer.columns() {
713                    recorder.read_column(column);
714                }
715                recorder.read(buffer.num_rows_device());
716            }
717            Self::Resident { buffer, .. } => {
718                for column in buffer.columns() {
719                    recorder.read_column(column);
720                    recorder.write_column(column);
721                }
722                recorder.read_write(buffer.num_rows_device());
723            }
724        }
725    }
726}
727
728/// Runtime-owned control/workspace bindings copied into a graph-free header.
729pub struct ResidentScheduleExternalBindings<'a> {
730    filter_scratch: Option<&'a ResidentFilterScratch>,
731    set_workspace: &'a ResidentSetWorkspace,
732    join_workspace: &'a ResidentJoinWorkspace,
733    control: &'a ResidentConvergenceControl,
734    trace: &'a ResidentDeviceTrace,
735    schema_winners: &'a ResidentSchemaWinners,
736    receipt: &'a ResidentPackedReceipt,
737}
738
739impl<'a> ResidentScheduleExternalBindings<'a> {
740    pub fn new(
741        filter_scratch: Option<&'a ResidentFilterScratch>,
742        set_workspace: &'a ResidentSetWorkspace,
743        join_workspace: &'a ResidentJoinWorkspace,
744        control: &'a ResidentConvergenceControl,
745        trace: &'a ResidentDeviceTrace,
746        schema_winners: &'a ResidentSchemaWinners,
747        receipt: &'a ResidentPackedReceipt,
748    ) -> Self {
749        Self {
750            filter_scratch,
751            set_workspace,
752            join_workspace,
753            control,
754            trace,
755            schema_winners,
756            receipt,
757        }
758    }
759
760    /// Record every runtime-owned mutable workspace and final receipt binding.
761    pub fn record_uses(&self, recorder: &mut LaunchRecorder) {
762        if let Some(filter_scratch) = self.filter_scratch {
763            filter_scratch.record_uses(recorder);
764        }
765        self.set_workspace.record_uses(recorder);
766        self.join_workspace.record_uses(recorder);
767        self.control.record_uses(recorder);
768        self.trace.record_uses(recorder);
769        self.schema_winners.record_uses(recorder);
770        self.receipt.record_uses(recorder);
771    }
772}
773
774impl<'a> ResidentScheduleRelation<'a> {
775    pub fn source(buffer: &'a CudaBuffer, generation: u32) -> Result<Self> {
776        let initial_count = buffer.cached_row_count().ok_or_else(|| {
777            XlogError::Kernel(
778                "resident schedule source requires a cold-path cached logical row count".into(),
779            )
780        })?;
781        if u64::from(initial_count) > buffer.num_rows() {
782            return Err(XlogError::Kernel(format!(
783                "resident schedule source count {initial_count} exceeds capacity {}",
784                buffer.num_rows()
785            )));
786        }
787        Ok(Self::Source {
788            buffer,
789            generation,
790            initial_count,
791        })
792    }
793
794    pub fn output(buffer: &'a mut CudaBuffer, generation: u32) -> Self {
795        Self::Output { buffer, generation }
796    }
797
798    fn buffer(&self) -> &CudaBuffer {
799        match self {
800            Self::Source { buffer, .. } => buffer,
801            Self::Output { buffer, .. } => buffer,
802        }
803    }
804
805    fn generation(&self) -> u32 {
806        match self {
807            Self::Source { generation, .. } | Self::Output { generation, .. } => *generation,
808        }
809    }
810
811    fn flags(&self) -> u32 {
812        match self {
813            Self::Source { .. } => SOURCE_SLOT,
814            Self::Output { .. } => 0,
815        }
816    }
817
818    fn initial_count(&self) -> u32 {
819        match self {
820            Self::Source { initial_count, .. } => *initial_count,
821            Self::Output { .. } => 0,
822        }
823    }
824
825    fn invalidate_output_metadata(&mut self) {
826        if let Self::Output { buffer, .. } = self {
827            let _ = buffer.num_rows_device_mut();
828        }
829    }
830
831    fn is_output(&self) -> bool {
832        matches!(self, Self::Output { .. })
833    }
834}
835
836/// One post-synchronization observation of terminal status and row counts.
837#[derive(Debug, Clone, PartialEq, Eq)]
838pub struct ResidentScheduleReceipt {
839    pub status: ResidentTerminalStatus,
840    pub changed: u32,
841    pub counts: Vec<u32>,
842}
843
844struct ResidentSchedulePinnedReceipt {
845    buffer: crate::device::PinnedHostBuffer,
846}
847
848impl ResidentSchedulePinnedReceipt {
849    fn allocate(stream: &CudaStream, len: usize) -> Result<Self> {
850        Ok(Self {
851            buffer: crate::device::PinnedHostBuffer::new(stream, len).map_err(|error| {
852                XlogError::Kernel(format!(
853                    "resident schedule pinned receipt allocation failed: {error}"
854                ))
855            })?,
856        })
857    }
858
859    fn copy_from_device(
860        &mut self,
861        source: &TrackedCudaSlice<u8>,
862        stream: &Arc<CudaStream>,
863    ) -> Result<Vec<u8>> {
864        self.buffer
865            .copy_from_device(&source.view(), stream)
866            .map_err(|error| {
867                XlogError::Kernel(format!(
868                    "resident schedule final receipt copy failed: {error}"
869                ))
870            })
871    }
872}
873
874/// All allocations whose addresses are captured by one compact schedule graph.
875pub struct ResidentSchedule<'a> {
876    origin_provider_identity: u64,
877    origin_memory_manager: usize,
878    header: TrackedCudaSlice<ResidentScheduleHeader>,
879    _slots: TrackedCudaSlice<ResidentRelationSlot>,
880    _ops: TrackedCudaSlice<ResidentOpDescriptor>,
881    _waves: TrackedCudaSlice<ResidentWaveDescriptor>,
882    _regions: TrackedCudaSlice<ResidentRegionDescriptor>,
883    _generation_metadata: TrackedCudaSlice<u32>,
884    _filter_comparisons: TrackedCudaSlice<ResidentFilterComparisonDescriptor>,
885    _project_expressions: TrackedCudaSlice<ResidentProjectExpressionDescriptor>,
886    _filter_mask: TrackedCudaSlice<u32>,
887    _filter_prefix: TrackedCudaSlice<u32>,
888    _filter_block_sums: TrackedCudaSlice<u32>,
889    _filter_block_offsets: TrackedCudaSlice<u32>,
890    _set_slots: TrackedCudaSlice<u64>,
891    _set_required: TrackedCudaSlice<u64>,
892    _join_buckets: TrackedCudaSlice<u32>,
893    _join_next: TrackedCudaSlice<u32>,
894    _join_required: TrackedCudaSlice<u64>,
895    _status: TrackedCudaSlice<ResidentTerminalStatus>,
896    _changed: TrackedCudaSlice<u32>,
897    _iterations: TrackedCudaSlice<u32>,
898    _scan_trace: TrackedCudaSlice<u32>,
899    _filter_trace: TrackedCudaSlice<u32>,
900    _semantic_scan_trace: TrackedCudaSlice<u32>,
901    _semantic_filter_trace: TrackedCudaSlice<u32>,
902    _receipt_table: TrackedCudaSlice<u64>,
903    receipt_bytes: TrackedCudaSlice<u8>,
904    pinned_receipt: ResidentSchedulePinnedReceipt,
905    launch_config: LaunchConfig,
906    region_count: u32,
907    region_descriptors: Vec<ResidentRegionDescriptor>,
908    requested_receipt_count: usize,
909    receipt_slots: Vec<u32>,
910    relations: Vec<ResidentScheduleRelation<'a>>,
911}
912
913impl ResidentSchedule<'_> {
914    fn memory_accesses(
915        &self,
916    ) -> crate::device_runtime::ResourceResult<Vec<crate::memory::DeviceMemoryAccess>> {
917        use crate::device_runtime::Access;
918        use crate::memory::DeviceRead;
919        let mut accesses = vec![
920            self.header.view().access(Access::Read)?,
921            self._ops.view().access(Access::Read)?,
922            self._waves.view().access(Access::Read)?,
923            self._regions.view().access(Access::Read)?,
924            self._generation_metadata.view().access(Access::Read)?,
925            self._filter_comparisons.view().access(Access::Read)?,
926            self._project_expressions.view().access(Access::Read)?,
927            self._receipt_table.view().access(Access::Read)?,
928            self._slots.view().access(Access::ReadWrite)?,
929            self._filter_mask.view().access(Access::ReadWrite)?,
930            self._filter_prefix.view().access(Access::ReadWrite)?,
931            self._filter_block_sums.view().access(Access::ReadWrite)?,
932            self._filter_block_offsets
933                .view()
934                .access(Access::ReadWrite)?,
935            self._set_slots.view().access(Access::ReadWrite)?,
936            self._set_required.view().access(Access::ReadWrite)?,
937            self._join_buckets.view().access(Access::ReadWrite)?,
938            self._join_next.view().access(Access::ReadWrite)?,
939            self._join_required.view().access(Access::ReadWrite)?,
940            self._status.view().access(Access::ReadWrite)?,
941            self._changed.view().access(Access::ReadWrite)?,
942            self._iterations.view().access(Access::ReadWrite)?,
943            self._scan_trace.view().access(Access::ReadWrite)?,
944            self._filter_trace.view().access(Access::ReadWrite)?,
945            self._semantic_scan_trace.view().access(Access::ReadWrite)?,
946            self._semantic_filter_trace
947                .view()
948                .access(Access::ReadWrite)?,
949            self.receipt_bytes.view().access(Access::Write)?,
950        ];
951        for relation in &self.relations {
952            let (buffer, access) = match relation {
953                ResidentScheduleRelation::Source { buffer, .. } => (*buffer, Access::Read),
954                ResidentScheduleRelation::Output { buffer, .. } => (&**buffer, Access::ReadWrite),
955            };
956            for column in buffer.columns() {
957                accesses.push(column.device_view().access(access)?);
958            }
959            accesses.push(buffer.num_rows_device().view().access(access)?);
960        }
961        Ok(accesses)
962    }
963}
964
965/// Graph-free compact scheduler metadata owned by the enclosing runtime capsule.
966#[derive(Clone)]
967pub struct ResidentExecutionDomain {
968    provider_identity: u64,
969    memory_manager_identity: usize,
970    runtime: Arc<XlogDeviceRuntime>,
971    stream_id: StreamId,
972    stream: Arc<CudaStream>,
973    context: Arc<cudarc::driver::CudaContext>,
974    marker: Arc<()>,
975}
976
977/// Enqueued resident operation that must be completed or cancelled exactly once.
978/// Dropping it automatically aborts through the underlying launch transaction.
979#[must_use = "an enqueued resident launch must be committed or aborted"]
980pub struct ResidentEnqueuedLaunch {
981    enqueued: EnqueuedLaunch,
982    marker: Arc<()>,
983}
984
985impl ResidentEnqueuedLaunch {
986    /// Publish the recorded resident allocation uses.
987    pub fn commit(self) -> Result<()> {
988        self.enqueued
989            .commit_bound(&self.marker)
990            .map_err(|error| XlogError::Kernel(format!("resident launch commit: {error}")))
991    }
992
993    /// Synchronize possible work and cancel the prepared resident reservations.
994    pub fn abort(self) -> Result<()> {
995        self.enqueued
996            .abort()
997            .map_err(|error| XlogError::Kernel(format!("resident launch abort: {error}")))
998    }
999}
1000
1001impl ResidentExecutionDomain {
1002    pub fn new_strict_recorder(&self) -> LaunchRecorder {
1003        LaunchRecorder::new_strict_bound(
1004            self.stream_id,
1005            Arc::clone(&self.runtime),
1006            Arc::clone(&self.marker),
1007        )
1008    }
1009
1010    /// Prepare the recorded resident uses and synchronously invoke one enqueue operation.
1011    ///
1012    /// # Safety
1013    ///
1014    /// `operation` must enqueue all work synchronously before it returns and use
1015    /// only the supplied stream. Every XLOG-owned allocation it touches must be
1016    /// registered on `recorder` with its exact access mode. Nested work must
1017    /// reuse the supplied enqueue capability instead of preparing another
1018    /// recorder or submitting independently on the raw stream.
1019    pub unsafe fn enqueue<E, F>(
1020        &self,
1021        recorder: LaunchRecorder,
1022        operation: F,
1023    ) -> std::result::Result<ResidentEnqueuedLaunch, LaunchEnqueueError<E>>
1024    where
1025        F: FnOnce(&crate::launch::CudaEnqueue<'_>) -> std::result::Result<(), E>,
1026    {
1027        // SAFETY: the execution domain supplies the runtime, marker, stream id,
1028        // and stream object that were bound together when the recorder was minted.
1029        let enqueued = unsafe {
1030            recorder.enqueue_bound(
1031                &self.runtime,
1032                &self.marker,
1033                self.stream_id,
1034                self.stream.as_ref(),
1035                operation,
1036            )?
1037        };
1038        Ok(ResidentEnqueuedLaunch {
1039            enqueued,
1040            marker: Arc::clone(&self.marker),
1041        })
1042    }
1043
1044    pub fn stream_id(&self) -> StreamId {
1045        self.stream_id
1046    }
1047}
1048
1049/// Graph-free compact scheduler metadata owned by the enclosing runtime capsule.
1050pub struct ResidentScheduleDeviceProgram {
1051    origin_provider_identity: u64,
1052    domain: ResidentExecutionDomain,
1053    header: TrackedCudaSlice<ResidentScheduleHeader>,
1054    _slots: TrackedCudaSlice<ResidentRelationSlot>,
1055    _ops: TrackedCudaSlice<ResidentOpDescriptor>,
1056    _waves: TrackedCudaSlice<ResidentWaveDescriptor>,
1057    _regions: TrackedCudaSlice<ResidentRegionDescriptor>,
1058    _generation_metadata: TrackedCudaSlice<u32>,
1059    _filter_comparisons: TrackedCudaSlice<ResidentFilterComparisonDescriptor>,
1060    _project_expressions: TrackedCudaSlice<ResidentProjectExpressionDescriptor>,
1061    launch_config: LaunchConfig,
1062    region_descriptors: Vec<ResidentRegionDescriptor>,
1063}
1064
1065impl ResidentScheduleDeviceProgram {
1066    /// Record immutable program tables and the replay-mutated slot table.
1067    pub fn record_uses(&self, recorder: &mut LaunchRecorder) {
1068        recorder.require_bound_domain(
1069            &self.domain.runtime,
1070            &self.domain.marker,
1071            self.domain.stream_id,
1072        );
1073        recorder.read(&self.header);
1074        recorder.read_write(&self._slots);
1075        recorder.read(&self._ops);
1076        recorder.read(&self._waves);
1077        recorder.read(&self._regions);
1078        recorder.read(&self._generation_metadata);
1079        recorder.read(&self._filter_comparisons);
1080        recorder.read(&self._project_expressions);
1081    }
1082}
1083
1084/// One captured schedule plus every allocation and exclusive relation lease.
1085pub struct ResidentScheduleGraph<'a> {
1086    graph: CapturedCudaGraph,
1087    schedule: ResidentSchedule<'a>,
1088    provider: &'a CudaKernelProvider,
1089    stream: Arc<CudaStream>,
1090    in_flight: bool,
1091}
1092
1093impl ResidentScheduleGraph<'_> {
1094    pub fn node_count(&self) -> Result<usize> {
1095        self.graph.node_count()
1096    }
1097
1098    pub fn nodes(&self) -> Result<Vec<CudaGraphNode>> {
1099        self.graph.nodes()
1100    }
1101
1102    pub fn launch(&mut self) -> Result<()> {
1103        if self.in_flight {
1104            return Err(XlogError::Kernel(
1105                "resident schedule launch is already in flight".into(),
1106            ));
1107        }
1108        self.graph.launch(&self.stream)?;
1109        self.in_flight = true;
1110        Ok(())
1111    }
1112
1113    pub fn synchronize_and_observe(&mut self) -> Result<ResidentScheduleReceipt> {
1114        if !self.in_flight {
1115            return Err(XlogError::Kernel(
1116                "resident schedule has no in-flight launch to observe".into(),
1117            ));
1118        }
1119        self.stream
1120            .synchronize()
1121            .map_err(|error| XlogError::Kernel(format!("resident schedule sync: {error}")))?;
1122        let receipt = self
1123            .provider
1124            .observe_resident_schedule(&mut self.schedule, &self.stream)?;
1125        self.in_flight = false;
1126        Ok(receipt)
1127    }
1128
1129    pub fn relation(&self, slot: usize) -> Result<&CudaBuffer> {
1130        if self.in_flight {
1131            return Err(XlogError::Kernel(
1132                "resident schedule relation is unavailable while launch is in flight".into(),
1133            ));
1134        }
1135        self.schedule
1136            .relations
1137            .get(slot)
1138            .map(ResidentScheduleRelation::buffer)
1139            .ok_or_else(|| XlogError::Kernel(format!("resident schedule slot {slot} is invalid")))
1140    }
1141}
1142
1143impl Drop for ResidentScheduleGraph<'_> {
1144    fn drop(&mut self) {
1145        if self.in_flight {
1146            let _ = self.stream.synchronize();
1147        }
1148    }
1149}
1150
1151const _: () = {
1152    use std::mem::{align_of, offset_of, size_of};
1153
1154    assert!(size_of::<ResidentRelationView>() == 224);
1155    assert!(align_of::<ResidentRelationView>() == 8);
1156    assert!(offset_of!(ResidentRelationView, columns) == 0);
1157    assert!(offset_of!(ResidentRelationView, widths) == 136);
1158    assert!(offset_of!(ResidentRelationView, arity) == 204);
1159    assert!(offset_of!(ResidentRelationView, capacity) == 208);
1160    assert!(offset_of!(ResidentRelationView, reserved) == 212);
1161    assert!(offset_of!(ResidentRelationView, num_rows) == 216);
1162
1163    assert!(size_of::<ResidentRelationSlot>() == 240);
1164    assert!(align_of::<ResidentRelationSlot>() == 16);
1165    assert!(offset_of!(ResidentRelationSlot, relation) == 0);
1166    assert!(offset_of!(ResidentRelationSlot, generation) == 224);
1167    assert!(offset_of!(ResidentRelationSlot, flags) == 228);
1168    assert!(offset_of!(ResidentRelationSlot, initial_count) == 232);
1169    assert!(offset_of!(ResidentRelationSlot, schema_tag) == 236);
1170
1171    assert!(size_of::<ResidentOpDescriptor>() == 72);
1172    assert!(align_of::<ResidentOpDescriptor>() == 4);
1173    assert!(offset_of!(ResidentOpDescriptor, kind) == 0);
1174    assert!(offset_of!(ResidentOpDescriptor, flags) == 4);
1175    assert!(offset_of!(ResidentOpDescriptor, op_id) == 8);
1176    assert!(offset_of!(ResidentOpDescriptor, out) == 12);
1177    assert!(offset_of!(ResidentOpDescriptor, in0) == 16);
1178    assert!(offset_of!(ResidentOpDescriptor, in1) == 20);
1179    assert!(offset_of!(ResidentOpDescriptor, in0_generation) == 24);
1180    assert!(offset_of!(ResidentOpDescriptor, in1_generation) == 28);
1181    assert!(offset_of!(ResidentOpDescriptor, out_generation) == 32);
1182    assert!(offset_of!(ResidentOpDescriptor, aux_offset) == 36);
1183    assert!(offset_of!(ResidentOpDescriptor, aux_count) == 40);
1184    assert!(offset_of!(ResidentOpDescriptor, left_key) == 44);
1185    assert!(offset_of!(ResidentOpDescriptor, right_key) == 48);
1186    assert!(offset_of!(ResidentOpDescriptor, scan_delta) == 52);
1187    assert!(offset_of!(ResidentOpDescriptor, filter_delta) == 56);
1188    assert!(offset_of!(ResidentOpDescriptor, schema_winner_head) == 60);
1189    assert!(offset_of!(ResidentOpDescriptor, schema_winner_id) == 64);
1190    assert!(offset_of!(ResidentOpDescriptor, reserved) == 68);
1191
1192    assert!(size_of::<ResidentWaveDescriptor>() == 16);
1193    assert!(align_of::<ResidentWaveDescriptor>() == 4);
1194    assert!(offset_of!(ResidentWaveDescriptor, first_op) == 0);
1195    assert!(offset_of!(ResidentWaveDescriptor, op_count) == 4);
1196    assert!(offset_of!(ResidentWaveDescriptor, flags) == 8);
1197    assert!(offset_of!(ResidentWaveDescriptor, reserved) == 12);
1198
1199    assert!(size_of::<ResidentRegionDescriptor>() == 32);
1200    assert!(align_of::<ResidentRegionDescriptor>() == 4);
1201    assert!(offset_of!(ResidentRegionDescriptor, first_wave) == 0);
1202    assert!(offset_of!(ResidentRegionDescriptor, wave_count) == 4);
1203    assert!(offset_of!(ResidentRegionDescriptor, iteration_limit) == 8);
1204    assert!(offset_of!(ResidentRegionDescriptor, op_id) == 12);
1205    assert!(offset_of!(ResidentRegionDescriptor, flags) == 16);
1206    assert!(offset_of!(ResidentRegionDescriptor, first_slot) == 20);
1207    assert!(offset_of!(ResidentRegionDescriptor, slot_count) == 24);
1208    assert!(offset_of!(ResidentRegionDescriptor, generation_offset) == 28);
1209
1210    assert!(size_of::<ResidentScheduleHeader>() == 288);
1211    assert!(align_of::<ResidentScheduleHeader>() == 16);
1212    assert!(offset_of!(ResidentScheduleHeader, slots) == 0);
1213    assert!(offset_of!(ResidentScheduleHeader, ops) == 8);
1214    assert!(offset_of!(ResidentScheduleHeader, waves) == 16);
1215    assert!(offset_of!(ResidentScheduleHeader, regions) == 24);
1216    assert!(offset_of!(ResidentScheduleHeader, generation_metadata) == 32);
1217    assert!(offset_of!(ResidentScheduleHeader, filter_comparisons) == 40);
1218    assert!(offset_of!(ResidentScheduleHeader, project_expressions) == 48);
1219    assert!(offset_of!(ResidentScheduleHeader, filter_mask) == 56);
1220    assert!(offset_of!(ResidentScheduleHeader, filter_prefix) == 64);
1221    assert!(offset_of!(ResidentScheduleHeader, filter_block_sums) == 72);
1222    assert!(offset_of!(ResidentScheduleHeader, filter_block_offsets) == 80);
1223    assert!(offset_of!(ResidentScheduleHeader, set_slots) == 88);
1224    assert!(offset_of!(ResidentScheduleHeader, set_required) == 96);
1225    assert!(offset_of!(ResidentScheduleHeader, join_buckets) == 104);
1226    assert!(offset_of!(ResidentScheduleHeader, join_next) == 112);
1227    assert!(offset_of!(ResidentScheduleHeader, join_required) == 120);
1228    assert!(offset_of!(ResidentScheduleHeader, status) == 128);
1229    assert!(offset_of!(ResidentScheduleHeader, changed) == 136);
1230    assert!(offset_of!(ResidentScheduleHeader, iterations) == 144);
1231    assert!(offset_of!(ResidentScheduleHeader, scan_trace) == 152);
1232    assert!(offset_of!(ResidentScheduleHeader, filter_trace) == 160);
1233    assert!(offset_of!(ResidentScheduleHeader, semantic_scan_trace) == 168);
1234    assert!(offset_of!(ResidentScheduleHeader, semantic_filter_trace) == 176);
1235    assert!(offset_of!(ResidentScheduleHeader, schema_seen_nonempty) == 184);
1236    assert!(offset_of!(ResidentScheduleHeader, schema_winner_ids) == 192);
1237    assert!(offset_of!(ResidentScheduleHeader, receipt_table) == 200);
1238    assert!(offset_of!(ResidentScheduleHeader, receipt_bytes) == 208);
1239    assert!(offset_of!(ResidentScheduleHeader, slot_count) == 216);
1240    assert!(offset_of!(ResidentScheduleHeader, schema_winner_count) == 264);
1241    assert!(offset_of!(ResidentScheduleHeader, generation_metadata_count) == 276);
1242    assert!(offset_of!(ResidentScheduleHeader, abi_version) == 280);
1243    assert!(offset_of!(ResidentScheduleHeader, reserved) == 284);
1244
1245    assert!(size_of::<ResidentFilterComparisonDescriptor>() == 48);
1246    assert!(align_of::<ResidentFilterComparisonDescriptor>() == 8);
1247    assert!(offset_of!(ResidentFilterComparisonDescriptor, left_constant) == 32);
1248    assert!(offset_of!(ResidentFilterComparisonDescriptor, right_constant) == 40);
1249
1250    assert!(size_of::<ResidentProjectExpressionDescriptor>() == 24);
1251    assert!(align_of::<ResidentProjectExpressionDescriptor>() == 8);
1252    assert!(offset_of!(ResidentProjectExpressionDescriptor, constant) == 16);
1253};
1254
1255pub fn resident_schedule_metadata_device_bytes(
1256    slot_count: usize,
1257    op_count: usize,
1258    wave_count: usize,
1259    region_count: usize,
1260    generation_metadata_count: usize,
1261    filter_comparison_count: usize,
1262    project_expression_count: usize,
1263) -> Result<u64> {
1264    let tables = [
1265        (slot_count.max(1), size_of::<ResidentRelationSlot>()),
1266        (op_count.max(1), size_of::<ResidentOpDescriptor>()),
1267        (wave_count.max(1), size_of::<ResidentWaveDescriptor>()),
1268        (region_count.max(1), size_of::<ResidentRegionDescriptor>()),
1269        (generation_metadata_count.max(1), size_of::<u32>()),
1270        (
1271            filter_comparison_count.max(1),
1272            size_of::<ResidentFilterComparisonDescriptor>(),
1273        ),
1274        (
1275            project_expression_count.max(1),
1276            size_of::<ResidentProjectExpressionDescriptor>(),
1277        ),
1278    ];
1279    let total = tables.iter().try_fold(
1280        size_of::<ResidentScheduleHeader>() as u128,
1281        |sum, &(count, width)| sum.checked_add((count as u128) * (width as u128)),
1282    );
1283    total
1284        .and_then(|bytes| u64::try_from(bytes).ok())
1285        .ok_or_else(|| XlogError::Kernel("resident schedule metadata bytes overflow".into()))
1286}
1287
1288fn checked_u32(value: usize, context: &str) -> Result<u32> {
1289    u32::try_from(value)
1290        .map_err(|_| XlogError::Kernel(format!("resident schedule {context} exceeds u32")))
1291}
1292
1293fn checked_capacity(value: u64, context: &str) -> Result<u32> {
1294    if value > RESIDENT_SCHEDULE_MAX_ROWS {
1295        return Err(XlogError::Kernel(format!(
1296            "resident schedule {context} capacity {value} exceeds {RESIDENT_SCHEDULE_MAX_ROWS}"
1297        )));
1298    }
1299    u32::try_from(value)
1300        .map_err(|_| XlogError::Kernel(format!("resident schedule {context} exceeds u32")))
1301}
1302
1303fn checked_workspace_slots(candidate_capacity: u64, context: &str) -> Result<u32> {
1304    let doubled = candidate_capacity
1305        .max(1)
1306        .checked_mul(2)
1307        .ok_or_else(|| XlogError::Kernel(format!("resident schedule {context} overflow")))?;
1308    let slots = doubled
1309        .checked_next_power_of_two()
1310        .ok_or_else(|| XlogError::Kernel(format!("resident schedule {context} overflow")))?;
1311    u32::try_from(slots)
1312        .map_err(|_| XlogError::Kernel(format!("resident schedule {context} exceeds u32")))
1313}
1314
1315fn reset_slot_flags(flags: u32) -> u32 {
1316    if flags & (RESIDENT_SCHEDULE_SLOT_SOURCE | RESIDENT_SCHEDULE_SLOT_PERMANENT) != 0 {
1317        flags | RESIDENT_SCHEDULE_SLOT_DEFINED
1318    } else {
1319        flags & !RESIDENT_SCHEDULE_SLOT_DEFINED
1320    }
1321}
1322
1323#[cfg(test)]
1324fn reset_slot_state_for_region(
1325    flags: u32,
1326    generation: u32,
1327    count: u32,
1328    initializes: bool,
1329) -> (u32, u32, u32) {
1330    let source = flags & RESIDENT_SCHEDULE_SLOT_SOURCE != 0;
1331    let permanent = flags & RESIDENT_SCHEDULE_SLOT_PERMANENT != 0;
1332    (
1333        reset_slot_flags(flags),
1334        generation,
1335        if source || (permanent && !initializes) {
1336            count
1337        } else {
1338            0
1339        },
1340    )
1341}
1342
1343fn slot_input_is_ready(flags: u32, generation: u32, expected_generation: u32) -> bool {
1344    flags & RESIDENT_SCHEDULE_SLOT_DEFINED != 0 && generation == expected_generation
1345}
1346
1347fn slot_output_generation_is_valid(flags: u32, generation: u32, output_generation: u32) -> bool {
1348    flags & RESIDENT_SCHEDULE_SLOT_SOURCE == 0
1349        && (output_generation == generation || generation.checked_add(1) == Some(output_generation))
1350}
1351
1352fn finish_slot_write(flags: u32, success: bool) -> u32 {
1353    if success {
1354        flags | RESIDENT_SCHEDULE_SLOT_DEFINED
1355    } else {
1356        flags
1357    }
1358}
1359
1360fn checked_schedule_head_count(receipt_count: u32, receipt_byte_count: u32) -> Result<u32> {
1361    let remainder = receipt_count.checked_sub(4).filter(|value| value % 2 == 0);
1362    let expected_bytes = receipt_count
1363        .checked_add(1)
1364        .and_then(|count| count.checked_mul(size_of::<u32>() as u32))
1365        .and_then(|count_bytes| {
1366            (size_of::<ResidentTerminalStatus>() as u32).checked_add(count_bytes)
1367        });
1368    if remainder.is_none() || expected_bytes != Some(receipt_byte_count) {
1369        return Err(XlogError::Kernel(
1370            "resident schedule packed receipt shape is invalid".into(),
1371        ));
1372    }
1373    Ok(remainder.expect("validated receipt remainder") / 2)
1374}
1375
1376fn checked_schedule_winner_count(
1377    receipt_count: u32,
1378    receipt_byte_count: u32,
1379    schema_winner_count: u32,
1380) -> Result<u32> {
1381    let head_count = checked_schedule_head_count(receipt_count, receipt_byte_count)?;
1382    if schema_winner_count != head_count {
1383        return Err(XlogError::Kernel(
1384            "resident schedule schema winner count does not match its receipt".into(),
1385        ));
1386    }
1387    Ok(head_count)
1388}
1389
1390fn validate_schema_winner_encoding(op: &ResidentOpDescriptor, head_count: u32) -> Result<()> {
1391    let marks_winner = op.flags & RESIDENT_SCHEDULE_OP_MARK_SCHEMA_WINNER != 0;
1392    if (marks_winner && op.schema_winner_head >= head_count)
1393        || (!marks_winner && (op.schema_winner_head != 0 || op.schema_winner_id != 0))
1394    {
1395        return Err(XlogError::Kernel(format!(
1396            "resident schedule operation {} has an invalid schema winner encoding",
1397            op.op_id
1398        )));
1399    }
1400    Ok(())
1401}
1402
1403fn same_relation_layout(left: &ResidentRelationView, right: &ResidentRelationView) -> bool {
1404    left.arity == right.arity
1405        && left.widths[..left.arity as usize] == right.widths[..right.arity as usize]
1406}
1407
1408fn column_width_matches(relation: &ResidentRelationView, column: u32, width: u32) -> bool {
1409    let column = column as usize;
1410    column < relation.arity as usize && relation.widths[column] == width
1411}
1412
1413fn validate_flattened_filter_project_descriptors(
1414    slots: &[ResidentRelationSlot],
1415    slot_types: &[Vec<ScalarType>],
1416    ops: &[ResidentOpDescriptor],
1417    filter_comparisons: &[ResidentFilterComparisonDescriptor],
1418    project_expressions: &[ResidentProjectExpressionDescriptor],
1419) -> Result<()> {
1420    if slots.len() != slot_types.len() {
1421        return Err(XlogError::Kernel(
1422            "resident schedule slot type table length is invalid".into(),
1423        ));
1424    }
1425    for (slot, types) in slots.iter().zip(slot_types) {
1426        if types.len() != slot.relation.arity as usize {
1427            return Err(XlogError::Kernel(
1428                "resident schedule slot type table arity is invalid".into(),
1429            ));
1430        }
1431        for (column, scalar) in types.iter().copied().enumerate() {
1432            if resident_schedule_scalar_width(scalar)? != slot.relation.widths[column] {
1433                return Err(XlogError::Kernel(
1434                    "resident schedule slot type width is invalid".into(),
1435                ));
1436            }
1437        }
1438    }
1439
1440    let operand_type = |relation: &ResidentRelationView,
1441                        types: &[ScalarType],
1442                        kind: u32,
1443                        column: u32,
1444                        width: u32,
1445                        constant: u64|
1446     -> Result<Option<ScalarType>> {
1447        if !matches!(width, 4 | 8) {
1448            return Err(XlogError::Kernel(
1449                "resident schedule descriptor scalar width is invalid".into(),
1450            ));
1451        }
1452        match kind {
1453            0 => {
1454                if constant != 0 || !column_width_matches(relation, column, width) {
1455                    return Err(XlogError::Kernel(
1456                        "resident schedule descriptor column is invalid".into(),
1457                    ));
1458                }
1459                Ok(types.get(column as usize).copied())
1460            }
1461            1 if column == 0 => Ok(None),
1462            _ => Err(XlogError::Kernel(
1463                "resident schedule descriptor operand kind is invalid".into(),
1464            )),
1465        }
1466    };
1467
1468    let mut filter_cursor = 0_u32;
1469    let mut project_cursor = 0_u32;
1470    let filter_total = checked_u32(filter_comparisons.len(), "filter comparison count")?;
1471    let project_total = checked_u32(project_expressions.len(), "project expression count")?;
1472    for op in ops {
1473        if op.kind == OP_FILTER {
1474            if op.in0 as usize >= slots.len()
1475                || op.out as usize >= slots.len()
1476                || op.aux_offset != filter_cursor
1477                || op.aux_offset > filter_total
1478                || op.aux_count > filter_total - op.aux_offset
1479            {
1480                return Err(XlogError::Kernel(format!(
1481                    "resident schedule filter {} descriptor range is invalid",
1482                    op.op_id
1483                )));
1484            }
1485            let input = &slots[op.in0 as usize].relation;
1486            let output = &slots[op.out as usize].relation;
1487            if slots[op.in0 as usize].schema_tag != slots[op.out as usize].schema_tag
1488                || !same_relation_layout(input, output)
1489            {
1490                return Err(XlogError::Kernel(format!(
1491                    "resident schedule filter {} input and output schemas differ",
1492                    op.op_id
1493                )));
1494            }
1495            let types = &slot_types[op.in0 as usize];
1496            for comparison in
1497                &filter_comparisons[op.aux_offset as usize..(op.aux_offset + op.aux_count) as usize]
1498            {
1499                if comparison.op > 5
1500                    || comparison.reserved_zero != 0
1501                    || comparison.reserved_one != 0
1502                {
1503                    return Err(XlogError::Kernel(format!(
1504                        "resident schedule filter {} descriptor payload is invalid",
1505                        op.op_id
1506                    )));
1507                }
1508                let left = operand_type(
1509                    input,
1510                    types,
1511                    comparison.left_kind,
1512                    comparison.left_column,
1513                    comparison.width,
1514                    comparison.left_constant,
1515                )?;
1516                let right = operand_type(
1517                    input,
1518                    types,
1519                    comparison.right_kind,
1520                    comparison.right_column,
1521                    comparison.width,
1522                    comparison.right_constant,
1523                )?;
1524                if left.is_some() && right.is_some() && left != right {
1525                    return Err(XlogError::Kernel(format!(
1526                        "resident schedule filter {} operand types differ",
1527                        op.op_id
1528                    )));
1529                }
1530            }
1531            filter_cursor = op.aux_offset + op.aux_count;
1532        } else if op.kind == OP_PROJECT {
1533            if op.in0 as usize >= slots.len()
1534                || op.out as usize >= slots.len()
1535                || op.aux_offset != project_cursor
1536                || op.aux_offset > project_total
1537                || op.aux_count > project_total - op.aux_offset
1538            {
1539                return Err(XlogError::Kernel(format!(
1540                    "resident schedule project {} descriptor range is invalid",
1541                    op.op_id
1542                )));
1543            }
1544            let input = &slots[op.in0 as usize].relation;
1545            let output = &slots[op.out as usize].relation;
1546            if op.aux_count != output.arity {
1547                return Err(XlogError::Kernel(format!(
1548                    "resident schedule project {} expression count is invalid",
1549                    op.op_id
1550                )));
1551            }
1552            let input_types = &slot_types[op.in0 as usize];
1553            let output_types = &slot_types[op.out as usize];
1554            for (column, expression) in project_expressions
1555                [op.aux_offset as usize..(op.aux_offset + op.aux_count) as usize]
1556                .iter()
1557                .enumerate()
1558            {
1559                if expression.reserved != 0
1560                    || expression.width != output.widths[column]
1561                    || !matches!(expression.width, 4 | 8)
1562                {
1563                    return Err(XlogError::Kernel(format!(
1564                        "resident schedule project {} descriptor payload is invalid",
1565                        op.op_id
1566                    )));
1567                }
1568                match expression.kind {
1569                    0 => {
1570                        if expression.constant != 0
1571                            || !column_width_matches(input, expression.column, expression.width)
1572                            || input_types.get(expression.column as usize)
1573                                != output_types.get(column)
1574                        {
1575                            return Err(XlogError::Kernel(format!(
1576                                "resident schedule project {} column type is invalid",
1577                                op.op_id
1578                            )));
1579                        }
1580                    }
1581                    1 if expression.column == 0 => {}
1582                    _ => {
1583                        return Err(XlogError::Kernel(format!(
1584                            "resident schedule project {} expression kind is invalid",
1585                            op.op_id
1586                        )));
1587                    }
1588                }
1589            }
1590            project_cursor = op.aux_offset + op.aux_count;
1591        }
1592    }
1593    if filter_cursor != filter_total || project_cursor != project_total {
1594        return Err(XlogError::Kernel(
1595            "resident schedule flattened descriptor tables are not exactly covered".into(),
1596        ));
1597    }
1598    Ok(())
1599}
1600
1601fn resident_schedule_scalar_width(scalar: ScalarType) -> Result<u32> {
1602    match scalar {
1603        ScalarType::Symbol | ScalarType::U32 => Ok(4),
1604        ScalarType::U64 => Ok(8),
1605        unsupported => Err(XlogError::Kernel(format!(
1606            "resident schedule scalar type {unsupported:?} is unsupported"
1607        ))),
1608    }
1609}
1610
1611fn resident_schedule_scalar_tag(scalar: ScalarType) -> u32 {
1612    match scalar {
1613        ScalarType::Symbol => 1,
1614        ScalarType::U32 => 2,
1615        ScalarType::U64 => 3,
1616        _ => 0,
1617    }
1618}
1619
1620fn validate_initialization_scope(
1621    initial_region: &ResidentRegionDescriptor,
1622    slot_count: u32,
1623) -> Result<()> {
1624    if initial_region.first_slot != 0 || initial_region.slot_count != slot_count {
1625        return Err(XlogError::Kernel(
1626            "resident schedule initialization must cover every relation slot".into(),
1627        ));
1628    }
1629    Ok(())
1630}
1631
1632fn validate_wave_partition(waves: &[ResidentWaveDescriptor], op_count: u32) -> Result<()> {
1633    let mut next_op = 0_u32;
1634    for wave in waves {
1635        if wave.first_op != next_op
1636            || wave.first_op > op_count
1637            || wave.op_count > op_count - wave.first_op
1638            || wave.flags != 0
1639            || wave.reserved != 0
1640        {
1641            return Err(XlogError::Kernel(
1642                "resident schedule waves must exactly partition operations".into(),
1643            ));
1644        }
1645        next_op = wave.first_op + wave.op_count;
1646    }
1647    if next_op != op_count {
1648        return Err(XlogError::Kernel(
1649            "resident schedule waves must exactly partition operations".into(),
1650        ));
1651    }
1652    Ok(())
1653}
1654
1655fn validate_region_control_and_ranges(
1656    regions: &[ResidentRegionDescriptor],
1657    wave_count: u32,
1658    slot_count: u32,
1659) -> Result<()> {
1660    if regions.is_empty() {
1661        return Err(XlogError::Kernel(
1662            "resident schedule requires at least one region".into(),
1663        ));
1664    }
1665    validate_initialization_scope(&regions[0], slot_count)?;
1666    let allowed_flags = RESIDENT_SCHEDULE_REGION_INITIALIZE
1667        | RESIDENT_SCHEDULE_REGION_SCC_BEGIN
1668        | RESIDENT_SCHEDULE_REGION_RECURSIVE
1669        | RESIDENT_SCHEDULE_REGION_FINALIZE;
1670    let mut next_wave = 0_u32;
1671    for (index, region) in regions.iter().enumerate() {
1672        if region.first_wave > wave_count
1673            || region.wave_count > wave_count - region.first_wave
1674            || region.first_slot > slot_count
1675            || region.slot_count > slot_count - region.first_slot
1676            || region.first_wave != next_wave
1677            || region.flags & !allowed_flags != 0
1678        {
1679            return Err(XlogError::Kernel(
1680                "resident schedule region range or reserved field is invalid".into(),
1681            ));
1682        }
1683        let initializes = region.flags & RESIDENT_SCHEDULE_REGION_INITIALIZE != 0;
1684        let begins_scc = region.flags & RESIDENT_SCHEDULE_REGION_SCC_BEGIN != 0;
1685        let recursive = region.flags & RESIDENT_SCHEDULE_REGION_RECURSIVE != 0;
1686        let finalizes = region.flags & RESIDENT_SCHEDULE_REGION_FINALIZE != 0;
1687        if initializes != (index == 0)
1688            || finalizes != (index + 1 == regions.len())
1689            || (recursive && region.flags != RESIDENT_SCHEDULE_REGION_RECURSIVE)
1690            || (begins_scc && (recursive || finalizes))
1691            || (!begins_scc && !recursive && region.iteration_limit != 1)
1692        {
1693            return Err(XlogError::Kernel(
1694                "resident schedule region control flags are invalid".into(),
1695            ));
1696        }
1697        if begins_scc {
1698            let body = regions.get(index + 1).ok_or_else(|| {
1699                XlogError::Kernel("resident schedule SCC begin has no recursive body".into())
1700            })?;
1701            if body.flags != RESIDENT_SCHEDULE_REGION_RECURSIVE
1702                || body.iteration_limit != region.iteration_limit
1703                || body.op_id != region.op_id
1704            {
1705                return Err(XlogError::Kernel(
1706                    "resident schedule SCC begin does not match its recursive body".into(),
1707                ));
1708            }
1709        } else if recursive {
1710            let seed = index
1711                .checked_sub(1)
1712                .and_then(|seed_index| regions.get(seed_index))
1713                .ok_or_else(|| {
1714                    XlogError::Kernel("resident schedule recursive body has no SCC begin".into())
1715                })?;
1716            if seed.flags & RESIDENT_SCHEDULE_REGION_SCC_BEGIN == 0 {
1717                return Err(XlogError::Kernel(
1718                    "resident schedule recursive body has no SCC begin".into(),
1719                ));
1720            }
1721        }
1722        next_wave = region.first_wave + region.wave_count;
1723    }
1724    if next_wave != wave_count {
1725        return Err(XlogError::Kernel(
1726            "resident schedule regions do not cover every wave".into(),
1727        ));
1728    }
1729    Ok(())
1730}
1731
1732fn validate_generation_baseline_ranges(
1733    regions: &[ResidentRegionDescriptor],
1734    generation_base_count: u32,
1735) -> Result<()> {
1736    let mut cursor = 0_u32;
1737    for region in regions {
1738        if region.generation_offset != cursor {
1739            return Err(XlogError::Kernel(
1740                "resident schedule generation baselines are not contiguous".into(),
1741            ));
1742        }
1743        cursor = cursor.checked_add(region.slot_count).ok_or_else(|| {
1744            XlogError::Kernel("resident schedule generation baseline range overflow".into())
1745        })?;
1746        if cursor > generation_base_count {
1747            return Err(XlogError::Kernel(
1748                "resident schedule generation baseline range is invalid".into(),
1749            ));
1750        }
1751    }
1752    if cursor != generation_base_count {
1753        return Err(XlogError::Kernel(
1754            "resident schedule generation baseline table has trailing entries".into(),
1755        ));
1756    }
1757    Ok(())
1758}
1759
1760fn build_generation_baselines(
1761    regions: &mut [ResidentRegionDescriptor],
1762    slot_generations: &[u32],
1763) -> Result<Vec<u32>> {
1764    let mut baselines = Vec::new();
1765    for region in regions {
1766        if region.generation_offset != 0 {
1767            return Err(XlogError::Kernel(
1768                "resident schedule generation baselines are not contiguous".into(),
1769            ));
1770        }
1771        region.generation_offset = checked_u32(baselines.len(), "generation baseline count")?;
1772        let first = usize::try_from(region.first_slot).unwrap_or(usize::MAX);
1773        let count = usize::try_from(region.slot_count).unwrap_or(usize::MAX);
1774        let end = first
1775            .checked_add(count)
1776            .filter(|&end| end <= slot_generations.len())
1777            .ok_or_else(|| {
1778                XlogError::Kernel(
1779                    "resident schedule generation baseline slot scope is invalid".into(),
1780                )
1781            })?;
1782        baselines.extend_from_slice(&slot_generations[first..end]);
1783    }
1784    checked_u32(baselines.len(), "generation baseline count")?;
1785    Ok(baselines)
1786}
1787
1788fn build_generation_metadata(
1789    generation_bases: &[u32],
1790    schema_defaults: &[u32],
1791) -> Result<Vec<u32>> {
1792    let metadata_count = generation_bases
1793        .len()
1794        .checked_add(schema_defaults.len())
1795        .ok_or_else(|| {
1796            XlogError::Kernel("resident schedule generation metadata overflow".into())
1797        })?;
1798    let mut metadata = Vec::with_capacity(metadata_count);
1799    metadata.extend_from_slice(generation_bases);
1800    metadata.extend_from_slice(schema_defaults);
1801    Ok(metadata)
1802}
1803
1804#[cfg(test)]
1805fn generation_baseline_count_from_metadata(
1806    generation_metadata_count: u32,
1807    schema_winner_count: u32,
1808) -> Result<u32> {
1809    generation_metadata_count
1810        .checked_sub(schema_winner_count)
1811        .ok_or_else(|| {
1812            XlogError::Kernel(
1813                "resident schedule generation metadata is shorter than its schema-default tail"
1814                    .into(),
1815            )
1816        })
1817}
1818
1819#[cfg(test)]
1820fn reset_schema_winner_state(
1821    defaults: &[u32],
1822    seen_nonempty: &mut [u32],
1823    winner_ids: &mut [u32],
1824) -> Result<()> {
1825    if defaults.len() != seen_nonempty.len() || defaults.len() != winner_ids.len() {
1826        return Err(XlogError::Kernel(
1827            "resident schedule schema-winner replay state has the wrong shape".into(),
1828        ));
1829    }
1830    seen_nonempty.fill(0);
1831    winner_ids.copy_from_slice(defaults);
1832    Ok(())
1833}
1834
1835#[cfg(test)]
1836fn mark_schema_winner_model(
1837    contribution_count: u32,
1838    candidate_id: u32,
1839    seen_nonempty: &mut u32,
1840    winner_id: &mut u32,
1841) {
1842    if contribution_count != 0 && *seen_nonempty == 0 {
1843        *seen_nonempty = 1;
1844        *winner_id = candidate_id;
1845    }
1846}
1847
1848#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
1849struct ResidentScheduleRequirements {
1850    filter_capacity: u32,
1851    set_candidate_capacity: u64,
1852    join_right_capacity: u32,
1853}
1854
1855#[expect(
1856    clippy::too_many_arguments,
1857    reason = "schedule validation receives every descriptor table and capacity needed to certify fixed graph bindings"
1858)]
1859fn validate_schedule_program(
1860    slots: &[ResidentRelationSlot],
1861    slot_types: &[Vec<ScalarType>],
1862    ops: &[ResidentOpDescriptor],
1863    waves: &[ResidentWaveDescriptor],
1864    regions: &[ResidentRegionDescriptor],
1865    generation_bases: &[u32],
1866    filter_comparisons: &[ResidentFilterComparisonDescriptor],
1867    project_expressions: &[ResidentProjectExpressionDescriptor],
1868    schema_defaults: &[u32],
1869) -> Result<ResidentScheduleRequirements> {
1870    validate_flattened_filter_project_descriptors(
1871        slots,
1872        slot_types,
1873        ops,
1874        filter_comparisons,
1875        project_expressions,
1876    )?;
1877    let op_count = checked_u32(ops.len(), "operation count")?;
1878    let wave_count = checked_u32(waves.len(), "wave count")?;
1879    let slot_count = checked_u32(slots.len(), "slot count")?;
1880    let generation_base_count = checked_u32(generation_bases.len(), "generation baseline count")?;
1881    validate_wave_partition(waves, op_count)?;
1882    validate_region_control_and_ranges(regions, wave_count, slot_count)?;
1883    validate_generation_baseline_ranges(regions, generation_base_count)?;
1884    let head_count = checked_u32(schema_defaults.len(), "schema default count")?;
1885    let mut first_schema_candidates = vec![None; schema_defaults.len()];
1886    let mut requirements = ResidentScheduleRequirements::default();
1887    let allowed_slot_flags = RESIDENT_SCHEDULE_SLOT_SOURCE
1888        | RESIDENT_SCHEDULE_SLOT_PERMANENT
1889        | RESIDENT_SCHEDULE_SLOT_DEFINED;
1890    for slot in slots {
1891        if slot.flags & !allowed_slot_flags != 0
1892            || slot.flags & RESIDENT_SCHEDULE_SLOT_SOURCE != 0
1893                && slot.flags & RESIDENT_SCHEDULE_SLOT_PERMANENT != 0
1894        {
1895            return Err(XlogError::Kernel(
1896                "resident schedule relation slot flags are invalid".into(),
1897            ));
1898        }
1899    }
1900
1901    for region in regions {
1902        let recursive = region.flags == RESIDENT_SCHEDULE_REGION_RECURSIVE;
1903        let mut novelty_count = 0_usize;
1904        let mut state = slots
1905            .iter()
1906            .map(|slot| (reset_slot_flags(slot.flags), slot.generation))
1907            .collect::<Vec<_>>();
1908        for offset in 0..region.slot_count {
1909            let slot = usize::try_from(region.first_slot + offset).unwrap_or(usize::MAX);
1910            let baseline = usize::try_from(region.generation_offset + offset).unwrap_or(usize::MAX);
1911            state[slot] = (
1912                reset_slot_flags(slots[slot].flags),
1913                generation_bases[baseline],
1914            );
1915        }
1916        let wave_end = region.first_wave + region.wave_count;
1917        for wave in &waves[region.first_wave as usize..wave_end as usize] {
1918            let op_end = wave.first_op + wave.op_count;
1919            for op in &ops[wave.first_op as usize..op_end as usize] {
1920                if op.kind == OP_TEST_STATUS {
1921                    decode_test_status(op)?;
1922                    continue;
1923                }
1924                if op.kind == OP_TRACE_DELTA {
1925                    let (_, _, semantic_guard) = decode_trace_delta(op)?;
1926                    if let Some((slot, generation)) = semantic_guard {
1927                        let slot_index = usize::try_from(slot).unwrap_or(usize::MAX);
1928                        let slot_end = region.first_slot + region.slot_count;
1929                        if slot_index >= slots.len() || slot < region.first_slot || slot >= slot_end
1930                        {
1931                            return Err(XlogError::Kernel(
1932                                "resident schedule trace guard is outside its region scope".into(),
1933                            ));
1934                        }
1935                        if !slot_input_is_ready(
1936                            state[slot_index].0,
1937                            state[slot_index].1,
1938                            generation,
1939                        ) {
1940                            return Err(XlogError::Kernel(
1941                                "resident schedule trace guard is undefined or stale".into(),
1942                            ));
1943                        }
1944                    }
1945                    continue;
1946                }
1947                let marks_novelty = op.flags & RESIDENT_SCHEDULE_OP_MARK_NOVELTY != 0;
1948                let marks_schema_winner = op.flags & RESIDENT_SCHEDULE_OP_MARK_SCHEMA_WINNER != 0;
1949                if op.kind > OP_DIFF
1950                    || op.flags
1951                        & !(RESIDENT_SCHEDULE_OP_MARK_NOVELTY
1952                            | RESIDENT_SCHEDULE_OP_MARK_SCHEMA_WINNER)
1953                        != 0
1954                    || (marks_novelty && (!matches!(op.kind, OP_DIFF | OP_PROJECT) || !recursive))
1955                    || op.scan_delta != 0
1956                    || op.filter_delta != 0
1957                    || op.reserved != 0
1958                {
1959                    return Err(XlogError::Kernel(format!(
1960                        "resident schedule operation {} has an unsupported kind, flag, or payload",
1961                        op.op_id
1962                    )));
1963                }
1964                validate_schema_winner_encoding(op, head_count)?;
1965                if marks_novelty {
1966                    novelty_count += 1;
1967                }
1968                if marks_schema_winner {
1969                    let candidate = &mut first_schema_candidates[op.schema_winner_head as usize];
1970                    if candidate.is_none() {
1971                        *candidate = Some(op.schema_winner_id);
1972                    }
1973                }
1974                let uses_in0 = op.kind != OP_UNIT;
1975                let uses_in1 = matches!(op.kind, OP_JOIN_INNER | OP_JOIN_SEMI | OP_UNION | OP_DIFF);
1976                let out = usize::try_from(op.out).unwrap_or(usize::MAX);
1977                let in0 = usize::try_from(op.in0).unwrap_or(usize::MAX);
1978                let in1 = usize::try_from(op.in1).unwrap_or(usize::MAX);
1979                if out >= slots.len()
1980                    || (uses_in0 && in0 >= slots.len())
1981                    || (uses_in1 && in1 >= slots.len())
1982                {
1983                    return Err(XlogError::Kernel(format!(
1984                        "resident schedule operation {} references a slot out of range",
1985                        op.op_id
1986                    )));
1987                }
1988                let slot_end = region.first_slot + region.slot_count;
1989                let in_scope = |slot: u32| slot >= region.first_slot && slot < slot_end;
1990                if !in_scope(op.out)
1991                    || (uses_in0 && !in_scope(op.in0))
1992                    || (uses_in1 && !in_scope(op.in1))
1993                {
1994                    return Err(XlogError::Kernel(format!(
1995                        "resident schedule operation {} references a slot outside its region scope",
1996                        op.op_id
1997                    )));
1998                }
1999                if op.kind != OP_SCAN
2000                    && ((uses_in0 && op.out == op.in0) || (uses_in1 && op.out == op.in1))
2001                {
2002                    return Err(XlogError::Kernel(format!(
2003                        "resident schedule operation {} aliases an input and output slot",
2004                        op.op_id
2005                    )));
2006                }
2007                if op.kind == OP_UNIT
2008                    && (op.in0 != 0
2009                        || op.in1 != 0
2010                        || op.in0_generation != 0
2011                        || op.in1_generation != 0
2012                        || op.aux_offset != 0
2013                        || op.aux_count != 0
2014                        || op.left_key != 0
2015                        || op.right_key != 0
2016                        || slots[out].relation.arity != 0)
2017                {
2018                    return Err(XlogError::Kernel(format!(
2019                        "resident schedule unit {} has nonzero operands or invalid output",
2020                        op.op_id
2021                    )));
2022                }
2023                if op.kind == OP_SCAN
2024                    && (op.in1 != 0
2025                        || op.in1_generation != 0
2026                        || op.aux_offset != 0
2027                        || op.aux_count != 0
2028                        || op.left_key != 0
2029                        || op.right_key != 0)
2030                {
2031                    return Err(XlogError::Kernel(format!(
2032                        "resident schedule scan {} has nonzero operands",
2033                        op.op_id
2034                    )));
2035                }
2036                match op.kind {
2037                    OP_UNIT | OP_SCAN => {}
2038                    OP_FILTER => {
2039                        if op.in1 != 0
2040                            || op.in1_generation != 0
2041                            || op.left_key != 0
2042                            || op.right_key != 0
2043                            || slots[in0].schema_tag != slots[out].schema_tag
2044                            || !same_relation_layout(&slots[in0].relation, &slots[out].relation)
2045                        {
2046                            return Err(XlogError::Kernel(format!(
2047                                "resident schedule filter {} is invalid",
2048                                op.op_id
2049                            )));
2050                        }
2051                        requirements.filter_capacity = requirements
2052                            .filter_capacity
2053                            .max(slots[in0].relation.capacity);
2054                    }
2055                    OP_PROJECT => {
2056                        if op.in1 != 0
2057                            || op.in1_generation != 0
2058                            || op.left_key != 0
2059                            || op.right_key != 0
2060                            || op.aux_count != slots[out].relation.arity
2061                        {
2062                            return Err(XlogError::Kernel(format!(
2063                                "resident schedule project {} is invalid",
2064                                op.op_id
2065                            )));
2066                        }
2067                    }
2068                    OP_UNION | OP_DIFF => {
2069                        if op.aux_offset != 0
2070                            || op.aux_count != 0
2071                            || op.left_key != 0
2072                            || op.right_key != 0
2073                            || slots[in0].schema_tag != slots[in1].schema_tag
2074                            || slots[in0].schema_tag != slots[out].schema_tag
2075                            || !same_relation_layout(&slots[in0].relation, &slots[in1].relation)
2076                            || !same_relation_layout(&slots[in0].relation, &slots[out].relation)
2077                        {
2078                            return Err(XlogError::Kernel(format!(
2079                                "resident schedule set operation {} is invalid",
2080                                op.op_id
2081                            )));
2082                        }
2083                        let candidate_capacity = u64::from(slots[in0].relation.capacity)
2084                            .checked_add(u64::from(slots[in1].relation.capacity))
2085                            .ok_or_else(|| {
2086                                XlogError::Kernel("resident schedule set capacity overflow".into())
2087                            })?;
2088                        requirements.set_candidate_capacity =
2089                            requirements.set_candidate_capacity.max(candidate_capacity);
2090                    }
2091                    OP_JOIN_INNER | OP_JOIN_SEMI => {
2092                        if op.aux_offset != 0 || op.aux_count != 0 {
2093                            return Err(XlogError::Kernel(format!(
2094                                "resident schedule join {} has invalid auxiliary operands",
2095                                op.op_id
2096                            )));
2097                        }
2098                        let left = &slots[in0].relation;
2099                        let right = &slots[in1].relation;
2100                        let output = &slots[out].relation;
2101                        let expected_arity = if op.kind == OP_JOIN_SEMI {
2102                            left.arity
2103                        } else {
2104                            left.arity.checked_add(right.arity).ok_or_else(|| {
2105                                XlogError::Kernel("resident schedule join arity overflow".into())
2106                            })?
2107                        };
2108                        let left_key = usize::try_from(op.left_key).unwrap_or(usize::MAX);
2109                        let right_key = usize::try_from(op.right_key).unwrap_or(usize::MAX);
2110                        let keys_match = left_key < left.arity as usize
2111                            && right_key < right.arity as usize
2112                            && left.widths[left_key] == right.widths[right_key]
2113                            && slot_types[in0].get(left_key) == slot_types[in1].get(right_key);
2114                        let output_widths_match = output.arity == expected_arity
2115                            && output.widths[..left.arity as usize]
2116                                == left.widths[..left.arity as usize]
2117                            && (op.kind == OP_JOIN_SEMI
2118                                || output.widths[left.arity as usize..expected_arity as usize]
2119                                    == right.widths[..right.arity as usize]);
2120                        let output_types_match = slot_types[out].get(..left.arity as usize)
2121                            == slot_types[in0].get(..left.arity as usize)
2122                            && (op.kind == OP_JOIN_SEMI
2123                                || slot_types[out]
2124                                    .get(left.arity as usize..expected_arity as usize)
2125                                    == slot_types[in1].get(..right.arity as usize));
2126                        if expected_arity as usize > RESIDENT_SCHEDULE_MAX_ARITY
2127                            || !keys_match
2128                            || !output_widths_match
2129                            || !output_types_match
2130                        {
2131                            return Err(XlogError::Kernel(format!(
2132                                "resident schedule join {} key or output schema is invalid",
2133                                op.op_id
2134                            )));
2135                        }
2136                        requirements.join_right_capacity =
2137                            requirements.join_right_capacity.max(right.capacity);
2138                    }
2139                    _ => unreachable!("operation kind validated above"),
2140                }
2141                if uses_in0 && !slot_input_is_ready(state[in0].0, state[in0].1, op.in0_generation) {
2142                    return Err(XlogError::Kernel(format!(
2143                        "resident schedule operation {} reads an undefined or stale input",
2144                        op.op_id
2145                    )));
2146                }
2147                if uses_in1 && !slot_input_is_ready(state[in1].0, state[in1].1, op.in1_generation) {
2148                    return Err(XlogError::Kernel(format!(
2149                        "resident schedule operation {} reads an undefined or stale input",
2150                        op.op_id
2151                    )));
2152                }
2153                if op.kind == OP_SCAN {
2154                    if op.out != op.in0 || op.out_generation != op.in0_generation {
2155                        return Err(XlogError::Kernel(format!(
2156                            "resident schedule scan {} is not an identity leaf",
2157                            op.op_id
2158                        )));
2159                    }
2160                } else {
2161                    if !slot_output_generation_is_valid(
2162                        state[out].0,
2163                        state[out].1,
2164                        op.out_generation,
2165                    ) {
2166                        return Err(XlogError::Kernel(format!(
2167                            "resident schedule operation {} has an invalid output generation",
2168                            op.op_id
2169                        )));
2170                    }
2171                    state[out].0 = finish_slot_write(state[out].0, true);
2172                    state[out].1 = op.out_generation;
2173                }
2174            }
2175        }
2176        if recursive && novelty_count == 0 {
2177            return Err(XlogError::Kernel(
2178                "resident schedule recursive body has no marked novelty output".into(),
2179            ));
2180        }
2181    }
2182    for (head, (&default, candidate)) in schema_defaults
2183        .iter()
2184        .zip(first_schema_candidates)
2185        .enumerate()
2186    {
2187        if candidate != Some(default) {
2188            return Err(XlogError::Kernel(format!(
2189                "resident schedule schema default for head {head} does not match its first candidate"
2190            )));
2191        }
2192    }
2193    Ok(requirements)
2194}
2195
2196fn buffers_share_storage(left: &CudaBuffer, right: &CudaBuffer) -> bool {
2197    fn allocation_aliases(
2198        left_ptr: u64,
2199        left_len: u64,
2200        left_block: Option<&crate::device_runtime::DeviceBlock>,
2201        right_ptr: u64,
2202        right_len: u64,
2203        right_block: Option<&crate::device_runtime::DeviceBlock>,
2204    ) -> bool {
2205        let same_runtime_allocation = match (left_block, right_block) {
2206            (Some(left), Some(right)) => {
2207                left.ptr == right.ptr && left.generation == right.generation
2208            }
2209            _ => false,
2210        };
2211        same_runtime_allocation || device_ranges_overlap(left_ptr, left_len, right_ptr, right_len)
2212    }
2213
2214    let left_count_aliases_right_count = allocation_aliases(
2215        left.num_rows_device().device_ptr_value(),
2216        std::mem::size_of::<u32>() as u64,
2217        left.num_rows_device().runtime_block(),
2218        right.num_rows_device().device_ptr_value(),
2219        std::mem::size_of::<u32>() as u64,
2220        right.num_rows_device().runtime_block(),
2221    );
2222    let left_count_aliases_right_column = right.columns().iter().any(|right_column| {
2223        allocation_aliases(
2224            left.num_rows_device().device_ptr_value(),
2225            std::mem::size_of::<u32>() as u64,
2226            left.num_rows_device().runtime_block(),
2227            *right_column.device_ptr(),
2228            u64::try_from(right_column.len()).unwrap_or(u64::MAX),
2229            right_column.runtime_block(),
2230        )
2231    });
2232    let left_column_aliases_right_count = left.columns().iter().any(|left_column| {
2233        allocation_aliases(
2234            *left_column.device_ptr(),
2235            u64::try_from(left_column.len()).unwrap_or(u64::MAX),
2236            left_column.runtime_block(),
2237            right.num_rows_device().device_ptr_value(),
2238            std::mem::size_of::<u32>() as u64,
2239            right.num_rows_device().runtime_block(),
2240        )
2241    });
2242    let columns_alias = left.columns().iter().any(|left_column| {
2243        right.columns().iter().any(|right_column| {
2244            allocation_aliases(
2245                *left_column.device_ptr(),
2246                u64::try_from(left_column.len()).unwrap_or(u64::MAX),
2247                left_column.runtime_block(),
2248                *right_column.device_ptr(),
2249                u64::try_from(right_column.len()).unwrap_or(u64::MAX),
2250                right_column.runtime_block(),
2251            )
2252        })
2253    });
2254    left_count_aliases_right_count
2255        || left_count_aliases_right_column
2256        || left_column_aliases_right_count
2257        || columns_alias
2258}
2259
2260fn device_ranges_overlap(left_ptr: u64, left_len: u64, right_ptr: u64, right_len: u64) -> bool {
2261    if left_len == 0 || right_len == 0 {
2262        return false;
2263    }
2264    let left_end = left_ptr.saturating_add(left_len);
2265    let right_end = right_ptr.saturating_add(right_len);
2266    left_ptr < right_end && right_ptr < left_end
2267}
2268
2269fn relation_view(buffer: &CudaBuffer) -> Result<(ResidentRelationView, u32)> {
2270    if buffer.arity() > RESIDENT_SCHEDULE_MAX_ARITY {
2271        return Err(XlogError::Kernel(format!(
2272            "resident schedule relation arity {} exceeds {RESIDENT_SCHEDULE_MAX_ARITY}",
2273            buffer.arity()
2274        )));
2275    }
2276    let capacity = checked_capacity(buffer.num_rows(), "relation")?;
2277    let mut columns = [0; RESIDENT_SCHEDULE_MAX_ARITY];
2278    let mut widths = [0; RESIDENT_SCHEDULE_MAX_ARITY];
2279    let mut schema_tag = 2_166_136_261_u32;
2280    schema_tag ^= checked_u32(buffer.arity(), "arity")?;
2281    schema_tag = schema_tag.wrapping_mul(16_777_619);
2282    for column in 0..buffer.arity() {
2283        columns[column] = *buffer.column(column).expect("arity checked").device_ptr();
2284        let scalar = buffer
2285            .schema()
2286            .column_type(column)
2287            .expect("schema arity checked");
2288        let width = resident_schedule_scalar_width(scalar)?;
2289        widths[column] = width;
2290        schema_tag ^= resident_schedule_scalar_tag(scalar);
2291        schema_tag = schema_tag.wrapping_mul(16_777_619);
2292    }
2293    Ok((
2294        ResidentRelationView {
2295            columns,
2296            widths,
2297            arity: checked_u32(buffer.arity(), "arity")?,
2298            capacity,
2299            reserved: 0,
2300            num_rows: buffer.num_rows_device().device_ptr_value(),
2301        },
2302        schema_tag,
2303    ))
2304}
2305
2306fn relation_scalar_types(buffer: &CudaBuffer) -> Vec<ScalarType> {
2307    (0..buffer.arity())
2308        .map(|column| {
2309            buffer
2310                .schema()
2311                .column_type(column)
2312                .expect("buffer schema arity")
2313        })
2314        .collect()
2315}
2316
2317fn finalize_schedule_output_counts(
2318    provider: &CudaKernelProvider,
2319    relations: &[ResidentScheduleRelation<'_>],
2320    receipt_slots: &[u32],
2321    counts: &[u32],
2322) -> Result<()> {
2323    if counts.len() != receipt_slots.len() {
2324        return Err(XlogError::Kernel(
2325            "resident schedule receipt count table is truncated".into(),
2326        ));
2327    }
2328    let mut entries = Vec::new();
2329    for (slot, relation) in relations.iter().enumerate() {
2330        if !relation.is_output() {
2331            continue;
2332        }
2333        let receipt_index = receipt_slots
2334            .iter()
2335            .position(|candidate| *candidate == slot as u32)
2336            .ok_or_else(|| {
2337                XlogError::Kernel(format!(
2338                    "resident schedule output slot {slot} has no receipt field"
2339                ))
2340            })?;
2341        entries.push((relation.buffer(), counts[receipt_index]));
2342    }
2343    provider.finalize_resident_logical_counts(&entries)
2344}
2345
2346impl CudaKernelProvider {
2347    pub fn bind_resident_execution_domain(
2348        &self,
2349        runtime: Arc<XlogDeviceRuntime>,
2350        stream_id: StreamId,
2351        stream: Arc<CudaStream>,
2352    ) -> Result<ResidentExecutionDomain> {
2353        let manager_runtime = self.memory().runtime().ok_or_else(|| {
2354            XlogError::Kernel(
2355                "resident execution domain requires a runtime-backed memory manager".into(),
2356            )
2357        })?;
2358        if !Arc::ptr_eq(manager_runtime, &runtime)
2359            || !Arc::ptr_eq(self.device(), self.memory().device())
2360            || !Arc::ptr_eq(self.device(), runtime.device())
2361        {
2362            return Err(XlogError::Kernel(
2363                "resident execution domain provider, manager, and runtime identities differ".into(),
2364            ));
2365        }
2366        let device_ordinal = u32::try_from(self.device().ordinal()).map_err(|_| {
2367            XlogError::Kernel("resident execution domain device ordinal overflow".into())
2368        })?;
2369        if runtime.device_ordinal() != device_ordinal || !runtime.supports_block_use_tracking() {
2370            return Err(XlogError::Kernel(
2371                "resident execution domain runtime is incompatible with the provider".into(),
2372            ));
2373        }
2374        let resolved_stream = runtime.stream_pool().resolve(stream_id).ok_or_else(|| {
2375            XlogError::Kernel(
2376                "resident execution domain stream id is not owned by the runtime".into(),
2377            )
2378        })?;
2379        if !Arc::ptr_eq(&resolved_stream, &stream) {
2380            return Err(XlogError::Kernel(
2381                "resident execution domain stream does not match its runtime stream id".into(),
2382            ));
2383        }
2384        let provider_context = self.device().inner().stream().context();
2385        if !Arc::ptr_eq(stream.context(), provider_context)
2386            || stream.context().cu_ctx() != provider_context.cu_ctx()
2387        {
2388            return Err(XlogError::Kernel(
2389                "resident execution domain stream belongs to a foreign CUDA context".into(),
2390            ));
2391        }
2392        Ok(ResidentExecutionDomain {
2393            provider_identity: self.provider_identity(),
2394            memory_manager_identity: Arc::as_ptr(self.memory()) as usize,
2395            runtime,
2396            stream_id,
2397            stream,
2398            context: Arc::clone(provider_context),
2399            marker: Arc::new(()),
2400        })
2401    }
2402
2403    fn upload_resident_schedule_metadata<T>(&self, values: &[T]) -> Result<TrackedCudaSlice<T>>
2404    where
2405        T: DeviceRepr + Default + Copy,
2406    {
2407        let mut allocation = self.memory.alloc::<T>(values.len().max(1))?;
2408        if values.is_empty() {
2409            self.htod_launch_metadata_sync_copy_into(&[T::default()], &mut allocation)?;
2410        } else {
2411            self.htod_launch_metadata_sync_copy_into(values, &mut allocation)?;
2412        }
2413        Ok(allocation)
2414    }
2415
2416    fn upload_resident_schedule_metadata_in_reservation<T>(
2417        &self,
2418        values: &[T],
2419        reservation: &mut GpuMemoryReservation,
2420    ) -> Result<TrackedCudaSlice<T>>
2421    where
2422        T: DeviceRepr + Default + Copy,
2423    {
2424        let mut allocation = reservation.alloc::<T>(values.len().max(1))?;
2425        if values.is_empty() {
2426            self.htod_launch_metadata_sync_copy_into(&[T::default()], &mut allocation)?;
2427        } else {
2428            self.htod_launch_metadata_sync_copy_into(values, &mut allocation)?;
2429        }
2430        Ok(allocation)
2431    }
2432
2433    /// Validate, allocate, and upload every descriptor before graph capture.
2434    #[expect(
2435        clippy::too_many_arguments,
2436        reason = "schedule preparation keeps slots, descriptors, output contract, limits, seeds, and external owners explicit"
2437    )]
2438    pub fn prepare_resident_schedule<'a>(
2439        &self,
2440        mut relations: Vec<ResidentScheduleRelation<'a>>,
2441        ops: &[ResidentOpDescriptor],
2442        waves: &[ResidentWaveDescriptor],
2443        regions: &[ResidentRegionDescriptor],
2444        filter_comparisons: &[ResidentFilterComparisonDescriptor],
2445        project_expressions: &[ResidentProjectExpressionDescriptor],
2446        receipt_slots: &[u32],
2447    ) -> Result<ResidentSchedule<'a>> {
2448        let slot_count = checked_u32(relations.len(), "slot count")?;
2449        let op_count = checked_u32(ops.len(), "operation count")?;
2450        let wave_count = checked_u32(waves.len(), "wave count")?;
2451        let region_count = checked_u32(regions.len(), "region count")?;
2452        let filter_comparison_count =
2453            checked_u32(filter_comparisons.len(), "filter comparison count")?;
2454        let project_expression_count =
2455            checked_u32(project_expressions.len(), "project expression count")?;
2456
2457        let mut slot_descriptors = Vec::with_capacity(relations.len());
2458        let mut slot_types = Vec::with_capacity(relations.len());
2459        let mut max_capacity = 0_u32;
2460        let provider_manager = Arc::as_ptr(&self.memory) as usize;
2461        let provider_context = self.device.inner().stream().context().cu_ctx();
2462        let provider_ordinal = self.device.ordinal() as u32;
2463        for relation in &mut relations {
2464            let buffer = relation.buffer();
2465            if buffer.num_rows_device().memory_manager_ptr_value() != provider_manager {
2466                return Err(XlogError::Kernel(
2467                    "resident schedule relation belongs to a foreign provider".into(),
2468                ));
2469            }
2470            for column in buffer.columns() {
2471                if column.stream().context().cu_ctx() != provider_context
2472                    || column
2473                        .runtime_block()
2474                        .is_some_and(|block| block.device_ordinal != provider_ordinal)
2475                {
2476                    return Err(XlogError::Kernel(
2477                        "resident schedule relation belongs to a foreign CUDA context".into(),
2478                    ));
2479                }
2480            }
2481            let (view, schema_tag) = relation_view(buffer)?;
2482            if u64::from(relation.initial_count()) > buffer.num_rows() {
2483                return Err(XlogError::Kernel(format!(
2484                    "resident schedule initial count {} exceeds capacity {}",
2485                    relation.initial_count(),
2486                    buffer.num_rows()
2487                )));
2488            }
2489            max_capacity = max_capacity.max(view.capacity);
2490            slot_descriptors.push(ResidentRelationSlot {
2491                relation: view,
2492                generation: relation.generation(),
2493                flags: relation.flags(),
2494                initial_count: relation.initial_count(),
2495                schema_tag,
2496            });
2497            slot_types.push(relation_scalar_types(buffer));
2498        }
2499        for (output_slot, output) in relations.iter().enumerate() {
2500            if !output.is_output() {
2501                continue;
2502            }
2503            for (other_slot, other) in relations.iter().enumerate() {
2504                if output_slot != other_slot
2505                    && buffers_share_storage(output.buffer(), other.buffer())
2506                {
2507                    return Err(XlogError::Kernel(format!(
2508                        "resident schedule output slot {output_slot} aliases storage in slot {other_slot}"
2509                    )));
2510                }
2511            }
2512        }
2513
2514        let mut region_descriptors = regions.to_vec();
2515        let slot_generations = slot_descriptors
2516            .iter()
2517            .map(|slot| slot.generation)
2518            .collect::<Vec<_>>();
2519        let generation_base_values =
2520            build_generation_baselines(&mut region_descriptors, &slot_generations)?;
2521        let generation_base_count =
2522            checked_u32(generation_base_values.len(), "generation baseline count")?;
2523        validate_generation_baseline_ranges(&region_descriptors, generation_base_count)?;
2524
2525        let requirements = validate_schedule_program(
2526            &slot_descriptors,
2527            &slot_types,
2528            ops,
2529            waves,
2530            &region_descriptors,
2531            &generation_base_values,
2532            filter_comparisons,
2533            project_expressions,
2534            &[],
2535        )?;
2536        let filter_capacity = requirements.filter_capacity;
2537        let set_candidate_capacity = requirements.set_candidate_capacity;
2538        let join_right_capacity = requirements.join_right_capacity;
2539        let set_slot_count = checked_workspace_slots(set_candidate_capacity, "set workspace")?;
2540        let join_bucket_count =
2541            checked_workspace_slots(u64::from(join_right_capacity), "join workspace")?;
2542        let filter_block_count = filter_capacity
2543            .div_ceil(RESIDENT_SCHEDULE_BLOCK_SIZE)
2544            .max(1);
2545        let requested_receipt_count = receipt_slots.len();
2546        let mut all_receipt_slots = receipt_slots.to_vec();
2547        for (slot, relation) in relations.iter().enumerate() {
2548            let slot = checked_u32(slot, "receipt slot")?;
2549            if relation.is_output() && !all_receipt_slots.contains(&slot) {
2550                all_receipt_slots.push(slot);
2551            }
2552        }
2553        let receipt_count = checked_u32(all_receipt_slots.len(), "receipt count")?;
2554        let receipt_byte_count = std::mem::size_of::<ResidentTerminalStatus>()
2555            .checked_add(
2556                std::mem::size_of::<u32>()
2557                    .checked_mul(all_receipt_slots.len() + 1)
2558                    .ok_or_else(|| {
2559                        XlogError::Kernel("resident schedule receipt overflow".into())
2560                    })?,
2561            )
2562            .ok_or_else(|| XlogError::Kernel("resident schedule receipt overflow".into()))?;
2563        let receipt_byte_count_u32 = checked_u32(receipt_byte_count, "receipt byte count")?;
2564        let mut receipt_count_ptrs = Vec::with_capacity(all_receipt_slots.len());
2565        for &slot in &all_receipt_slots {
2566            let index = usize::try_from(slot).unwrap_or(usize::MAX);
2567            let relation = relations.get(index).ok_or_else(|| {
2568                XlogError::Kernel(format!(
2569                    "resident schedule receipt slot {slot} is out of range"
2570                ))
2571            })?;
2572            receipt_count_ptrs.push(relation.buffer().num_rows_device().device_ptr_value());
2573        }
2574
2575        let function = self
2576            .device()
2577            .inner()
2578            .get_func(MODULE, KERNEL)
2579            .ok_or_else(|| XlogError::Kernel("resident_schedule_execute kernel missing".into()))?;
2580        let cooperative = self
2581            .device()
2582            .inner()
2583            .attribute(sys::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_COOPERATIVE_LAUNCH)
2584            .map_err(|error| XlogError::Kernel(format!("query cooperative launch: {error}")))?;
2585        if cooperative == 0 {
2586            return Err(XlogError::Kernel(
2587                "CUDA device does not support cooperative kernel launch".into(),
2588            ));
2589        }
2590        let active_per_sm = function
2591            .occupancy_max_active_blocks_per_multiprocessor(RESIDENT_SCHEDULE_BLOCK_SIZE, 0, None)
2592            .map_err(|error| XlogError::Kernel(format!("resident schedule occupancy: {error}")))?;
2593        let multiprocessors = self
2594            .device()
2595            .inner()
2596            .attribute(sys::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MULTIPROCESSOR_COUNT)
2597            .map_err(|error| XlogError::Kernel(format!("query multiprocessor count: {error}")))?;
2598        let cooperative_limit =
2599            active_per_sm
2600                .checked_mul(u32::try_from(multiprocessors).map_err(|_| {
2601                    XlogError::Kernel("CUDA multiprocessor count is invalid".into())
2602                })?)
2603                .ok_or_else(|| XlogError::Kernel("resident schedule grid overflow".into()))?;
2604        if cooperative_limit == 0 {
2605            return Err(XlogError::Kernel(
2606                "resident schedule has zero cooperative occupancy".into(),
2607            ));
2608        }
2609        let required_blocks = max_capacity
2610            .max(filter_capacity)
2611            .div_ceil(RESIDENT_SCHEDULE_BLOCK_SIZE)
2612            .max(1);
2613        let launch_config = LaunchConfig {
2614            grid_dim: (required_blocks.min(cooperative_limit), 1, 1),
2615            block_dim: (RESIDENT_SCHEDULE_BLOCK_SIZE, 1, 1),
2616            shared_mem_bytes: 0,
2617        };
2618
2619        let slots = self.upload_resident_schedule_metadata(&slot_descriptors)?;
2620        let ops = self.upload_resident_schedule_metadata(ops)?;
2621        let waves = self.upload_resident_schedule_metadata(waves)?;
2622        let regions = self.upload_resident_schedule_metadata(&region_descriptors)?;
2623        let generation_bases = self.upload_resident_schedule_metadata(&generation_base_values)?;
2624        let filter_comparisons = self.upload_resident_schedule_metadata(filter_comparisons)?;
2625        let project_expressions = self.upload_resident_schedule_metadata(project_expressions)?;
2626        let filter_mask = self
2627            .memory
2628            .alloc::<u32>(usize::try_from(filter_capacity).unwrap_or(0).max(1))?;
2629        let filter_prefix = self
2630            .memory
2631            .alloc::<u32>(usize::try_from(filter_capacity).unwrap_or(0).max(1))?;
2632        let filter_block_sums = self
2633            .memory
2634            .alloc::<u32>(usize::try_from(filter_block_count).unwrap_or(1))?;
2635        let filter_block_offsets = self
2636            .memory
2637            .alloc::<u32>(usize::try_from(filter_block_count).unwrap_or(1))?;
2638        let set_slots = self
2639            .memory
2640            .alloc::<u64>(usize::try_from(set_slot_count).unwrap_or(1))?;
2641        let set_required = self.memory.alloc::<u64>(1)?;
2642        let join_buckets = self
2643            .memory
2644            .alloc::<u32>(usize::try_from(join_bucket_count).unwrap_or(1))?;
2645        let join_next = self
2646            .memory
2647            .alloc::<u32>(usize::try_from(join_right_capacity).unwrap_or(0).max(1))?;
2648        let join_required = self.memory.alloc::<u64>(1)?;
2649        let status =
2650            self.upload_resident_schedule_metadata(&[ResidentTerminalStatus::default()])?;
2651        let changed = self.upload_resident_schedule_metadata(&[0_u32])?;
2652        let iterations = self.upload_resident_schedule_metadata(&[0_u32])?;
2653        let scan_trace = self.upload_resident_schedule_metadata(&[0_u32])?;
2654        let filter_trace = self.upload_resident_schedule_metadata(&[0_u32])?;
2655        let semantic_scan_trace = self.upload_resident_schedule_metadata(&[0_u32])?;
2656        let semantic_filter_trace = self.upload_resident_schedule_metadata(&[0_u32])?;
2657        let receipt_table = self.upload_resident_schedule_metadata(&receipt_count_ptrs)?;
2658        let receipt_bytes = self.memory.alloc::<u8>(receipt_byte_count.max(1))?;
2659        let pinned_receipt = ResidentSchedulePinnedReceipt::allocate(
2660            self.device().inner().stream(),
2661            receipt_byte_count,
2662        )?;
2663
2664        let header_value = ResidentScheduleHeader {
2665            slots: slots.device_ptr_value(),
2666            ops: ops.device_ptr_value(),
2667            waves: waves.device_ptr_value(),
2668            regions: regions.device_ptr_value(),
2669            generation_metadata: generation_bases.device_ptr_value(),
2670            filter_comparisons: filter_comparisons.device_ptr_value(),
2671            project_expressions: project_expressions.device_ptr_value(),
2672            filter_mask: filter_mask.device_ptr_value(),
2673            filter_prefix: filter_prefix.device_ptr_value(),
2674            filter_block_sums: filter_block_sums.device_ptr_value(),
2675            filter_block_offsets: filter_block_offsets.device_ptr_value(),
2676            set_slots: set_slots.device_ptr_value(),
2677            set_required: set_required.device_ptr_value(),
2678            join_buckets: join_buckets.device_ptr_value(),
2679            join_next: join_next.device_ptr_value(),
2680            join_required: join_required.device_ptr_value(),
2681            status: status.device_ptr_value(),
2682            changed: changed.device_ptr_value(),
2683            iterations: iterations.device_ptr_value(),
2684            scan_trace: scan_trace.device_ptr_value(),
2685            filter_trace: filter_trace.device_ptr_value(),
2686            semantic_scan_trace: semantic_scan_trace.device_ptr_value(),
2687            semantic_filter_trace: semantic_filter_trace.device_ptr_value(),
2688            schema_seen_nonempty: 0,
2689            schema_winner_ids: 0,
2690            receipt_table: receipt_table.device_ptr_value(),
2691            receipt_bytes: receipt_bytes.device_ptr_value(),
2692            slot_count,
2693            op_count,
2694            wave_count,
2695            region_count,
2696            filter_comparison_count,
2697            project_expression_count,
2698            filter_capacity,
2699            filter_block_count,
2700            set_slot_mask: set_slot_count - 1,
2701            set_candidate_capacity: u32::try_from(set_candidate_capacity).map_err(|_| {
2702                XlogError::Kernel("resident schedule set capacity exceeds u32".into())
2703            })?,
2704            join_bucket_mask: join_bucket_count - 1,
2705            join_right_capacity,
2706            schema_winner_count: 0,
2707            receipt_count,
2708            receipt_byte_count: receipt_byte_count_u32,
2709            generation_metadata_count: generation_base_count,
2710            abi_version: RESIDENT_SCHEDULE_ABI_VERSION,
2711            reserved: 0,
2712        };
2713        let header = self.upload_resident_schedule_metadata(&[header_value])?;
2714        for relation in &mut relations {
2715            relation.invalidate_output_metadata();
2716        }
2717
2718        Ok(ResidentSchedule {
2719            origin_provider_identity: self.provider_identity(),
2720            origin_memory_manager: Arc::as_ptr(&self.memory) as usize,
2721            header,
2722            _slots: slots,
2723            _ops: ops,
2724            _waves: waves,
2725            _regions: regions,
2726            _generation_metadata: generation_bases,
2727            _filter_comparisons: filter_comparisons,
2728            _project_expressions: project_expressions,
2729            _filter_mask: filter_mask,
2730            _filter_prefix: filter_prefix,
2731            _filter_block_sums: filter_block_sums,
2732            _filter_block_offsets: filter_block_offsets,
2733            _set_slots: set_slots,
2734            _set_required: set_required,
2735            _join_buckets: join_buckets,
2736            _join_next: join_next,
2737            _join_required: join_required,
2738            _status: status,
2739            _changed: changed,
2740            _iterations: iterations,
2741            _scan_trace: scan_trace,
2742            _filter_trace: filter_trace,
2743            _semantic_scan_trace: semantic_scan_trace,
2744            _semantic_filter_trace: semantic_filter_trace,
2745            _receipt_table: receipt_table,
2746            receipt_bytes,
2747            pinned_receipt,
2748            launch_config,
2749            region_count,
2750            region_descriptors,
2751            requested_receipt_count,
2752            receipt_slots: all_receipt_slots,
2753            relations,
2754        })
2755    }
2756
2757    /// Materialize only compact scheduler metadata from the enclosing runtime's
2758    /// already-admitted reservation. All relation, workspace, control, trace,
2759    /// schema-winner, receipt, graph, and lifecycle owners remain external.
2760    #[expect(
2761        clippy::too_many_arguments,
2762        reason = "in-reservation preparation keeps the admitted budget plus every fixed graph owner explicit"
2763    )]
2764    pub fn prepare_resident_schedule_program_in_reservation<'a>(
2765        &self,
2766        domain: &ResidentExecutionDomain,
2767        bindings: &[ResidentScheduleSlotBinding<'a>],
2768        ops: &[ResidentOpDescriptor],
2769        waves: &[ResidentWaveDescriptor],
2770        regions: &[ResidentRegionDescriptor],
2771        generation_bases: &[u32],
2772        filter_comparisons: &[ResidentFilterComparisonDescriptor],
2773        project_expressions: &[ResidentProjectExpressionDescriptor],
2774        receipt_slots: &[u32],
2775        external: ResidentScheduleExternalBindings<'a>,
2776        reservation: &mut GpuMemoryReservation,
2777    ) -> Result<ResidentScheduleDeviceProgram> {
2778        validate_execution_domain(self, domain)?;
2779        if reservation.memory_manager_ptr_value() != domain.memory_manager_identity {
2780            return Err(XlogError::Kernel(
2781                "resident schedule reservation belongs to a foreign memory manager".into(),
2782            ));
2783        }
2784        let slot_count = checked_u32(bindings.len(), "slot count")?;
2785        let op_count = checked_u32(ops.len(), "op count")?;
2786        let wave_count = checked_u32(waves.len(), "wave count")?;
2787        let region_count = checked_u32(regions.len(), "region count")?;
2788        let generation_base_count =
2789            checked_u32(generation_bases.len(), "generation baseline count")?;
2790        let filter_comparison_count =
2791            checked_u32(filter_comparisons.len(), "filter comparison count")?;
2792        let project_expression_count =
2793            checked_u32(project_expressions.len(), "project expression count")?;
2794
2795        if bindings.is_empty() {
2796            return Err(XlogError::Kernel(
2797                "resident schedule program requires slots".into(),
2798            ));
2799        }
2800        validate_region_control_and_ranges(regions, wave_count, slot_count)?;
2801        validate_generation_baseline_ranges(regions, generation_base_count)?;
2802        validate_wave_partition(waves, op_count)?;
2803
2804        let mut slot_descriptors = Vec::with_capacity(bindings.len());
2805        let mut slot_types = Vec::with_capacity(bindings.len());
2806        let mut slot_count_identities = Vec::with_capacity(bindings.len());
2807        let mut allocation_ranges = Vec::new();
2808        let mut max_capacity = 0_u32;
2809        for binding in bindings {
2810            for column in binding.buffer().columns() {
2811                validate_schedule_allocation(
2812                    column.runtime_allocation_identity()?,
2813                    domain,
2814                    &mut allocation_ranges,
2815                )?;
2816            }
2817            slot_count_identities.push(validate_schedule_allocation(
2818                binding
2819                    .buffer()
2820                    .num_rows_device()
2821                    .runtime_allocation_identity()?,
2822                domain,
2823                &mut allocation_ranges,
2824            )?);
2825            let (relation, schema_tag) = relation_view(binding.buffer())?;
2826            max_capacity = max_capacity.max(relation.capacity);
2827            slot_descriptors.push(ResidentRelationSlot {
2828                relation,
2829                generation: binding.generation(),
2830                flags: binding.flags(),
2831                initial_count: binding.initial_count(),
2832                schema_tag,
2833            });
2834            slot_types.push(relation_scalar_types(binding.buffer()));
2835        }
2836
2837        let (receipt_table, receipt_bytes, receipt_count, receipt_byte_count) =
2838            external.receipt.schedule_parts();
2839        let (schema_seen_nonempty, schema_winner_ids, schema_winner_count) =
2840            external.schema_winners.schedule_parts();
2841        let head_count =
2842            checked_schedule_winner_count(receipt_count, receipt_byte_count, schema_winner_count)?;
2843        let schema_defaults = external.schema_winners.default_schema_ids();
2844        if schema_defaults.len() != head_count as usize {
2845            return Err(XlogError::Kernel(
2846                "resident schedule schema-default count differs from the receipt".into(),
2847            ));
2848        }
2849        let generation_metadata = build_generation_metadata(generation_bases, schema_defaults)?;
2850        let generation_metadata_count =
2851            checked_u32(generation_metadata.len(), "generation metadata count")?;
2852        let requirements = validate_schedule_program(
2853            &slot_descriptors,
2854            &slot_types,
2855            ops,
2856            waves,
2857            regions,
2858            generation_bases,
2859            filter_comparisons,
2860            project_expressions,
2861            schema_defaults,
2862        )?;
2863
2864        if let Some(filter_scratch) = external.filter_scratch {
2865            for snapshot in filter_scratch.schedule_owner_snapshots()? {
2866                validate_schedule_allocation(snapshot, domain, &mut allocation_ranges)?;
2867            }
2868        }
2869        for snapshot in external.set_workspace.schedule_owner_snapshots()? {
2870            validate_schedule_allocation(snapshot, domain, &mut allocation_ranges)?;
2871        }
2872        for snapshot in external.join_workspace.schedule_owner_snapshots()? {
2873            validate_schedule_allocation(snapshot, domain, &mut allocation_ranges)?;
2874        }
2875        for snapshot in external.control.schedule_owner_snapshots()? {
2876            validate_schedule_allocation(snapshot, domain, &mut allocation_ranges)?;
2877        }
2878        let [scan_trace_snapshot, filter_trace_snapshot, semantic_scan_trace_snapshot, semantic_filter_trace_snapshot] =
2879            external.trace.schedule_owner_snapshots()?;
2880        let scan_trace_identity =
2881            validate_schedule_allocation(scan_trace_snapshot, domain, &mut allocation_ranges)?;
2882        let filter_trace_identity =
2883            validate_schedule_allocation(filter_trace_snapshot, domain, &mut allocation_ranges)?;
2884        let semantic_scan_trace_identity = validate_schedule_allocation(
2885            semantic_scan_trace_snapshot,
2886            domain,
2887            &mut allocation_ranges,
2888        )?;
2889        let semantic_filter_trace_identity = validate_schedule_allocation(
2890            semantic_filter_trace_snapshot,
2891            domain,
2892            &mut allocation_ranges,
2893        )?;
2894        let [schema_seen_snapshot, schema_winner_snapshot] =
2895            external.schema_winners.schedule_owner_snapshots()?;
2896        validate_schedule_allocation(schema_seen_snapshot, domain, &mut allocation_ranges)?;
2897        let schema_winner_identity =
2898            validate_schedule_allocation(schema_winner_snapshot, domain, &mut allocation_ranges)?;
2899        for snapshot in external.receipt.schedule_owner_snapshots()? {
2900            validate_schedule_allocation(snapshot, domain, &mut allocation_ranges)?;
2901        }
2902
2903        if external.receipt.relation_count_len() != head_count
2904            || external.receipt.device_trace_field_count() != 4
2905            || external.receipt.schema_winner_count() != head_count
2906            || external.receipt.total_count_field_len() != receipt_count
2907        {
2908            return Err(XlogError::Kernel(
2909                "resident schedule receipt owner shape differs from the header".into(),
2910            ));
2911        }
2912        let slot_flags: Vec<u32> = slot_descriptors.iter().map(|slot| slot.flags).collect();
2913        let receipt_slot_indices =
2914            validate_receipt_slot_mapping(receipt_slots, &slot_flags, head_count)?;
2915        let mut relation_count_ptrs = Vec::with_capacity(receipt_slot_indices.len());
2916        let expected_block_count = receipt_slot_indices
2917            .len()
2918            .checked_mul(2)
2919            .and_then(|count| count.checked_add(4))
2920            .ok_or_else(|| XlogError::Kernel("resident receipt block count overflow".into()))?;
2921        let mut expected_receipt_blocks = Vec::with_capacity(expected_block_count);
2922        for slot in receipt_slot_indices {
2923            relation_count_ptrs.push(bindings[slot].buffer().num_rows_device().device_ptr_value());
2924            expected_receipt_blocks.push(slot_count_identities[slot].block_id);
2925        }
2926        let (scan_trace, filter_trace, semantic_scan_trace, semantic_filter_trace) =
2927            external.trace.schedule_parts();
2928        expected_receipt_blocks.push(scan_trace_identity.block_id);
2929        expected_receipt_blocks.push(filter_trace_identity.block_id);
2930        expected_receipt_blocks.push(semantic_scan_trace_identity.block_id);
2931        expected_receipt_blocks.push(semantic_filter_trace_identity.block_id);
2932        let mut schema_winner_ptrs = Vec::with_capacity(receipt_slots.len());
2933        for index in 0..head_count {
2934            let offset = u64::from(index)
2935                .checked_mul(u64::try_from(std::mem::size_of::<u32>()).map_err(|_| {
2936                    XlogError::Kernel("resident schema-winner element size overflow".into())
2937                })?)
2938                .ok_or_else(|| {
2939                    XlogError::Kernel("resident schema-winner offset overflow".into())
2940                })?;
2941            schema_winner_ptrs.push(schema_winner_ids.checked_add(offset).ok_or_else(|| {
2942                XlogError::Kernel("resident schema-winner pointer overflow".into())
2943            })?);
2944            expected_receipt_blocks.push(schema_winner_identity.block_id);
2945        }
2946        external.receipt.validate_schedule_pointees(
2947            domain.memory_manager_identity,
2948            domain.runtime.device_ordinal(),
2949            &relation_count_ptrs,
2950            [
2951                scan_trace,
2952                filter_trace,
2953                semantic_scan_trace,
2954                semantic_filter_trace,
2955            ],
2956            &schema_winner_ptrs,
2957            &expected_receipt_blocks,
2958        )?;
2959
2960        let filter_capacity = requirements.filter_capacity;
2961        let set_candidate_capacity = requirements.set_candidate_capacity;
2962        let join_right_capacity = requirements.join_right_capacity;
2963
2964        let (
2965            filter_mask,
2966            filter_prefix,
2967            filter_block_sums,
2968            filter_block_offsets,
2969            supplied_filter_capacity,
2970            filter_block_count,
2971        ) = match external.filter_scratch {
2972            Some(scratch) => scratch.schedule_parts(),
2973            None if filter_capacity == 0 => (0, 0, 0, 0, 0, 0),
2974            None => {
2975                return Err(XlogError::Kernel(
2976                    "resident schedule filter scratch is missing".into(),
2977                ));
2978            }
2979        };
2980        if supplied_filter_capacity < filter_capacity {
2981            return Err(XlogError::Kernel(
2982                "resident schedule filter scratch is undersized".into(),
2983            ));
2984        }
2985        let (set_slots, set_required, set_slot_mask, supplied_set_capacity) =
2986            external.set_workspace.schedule_parts();
2987        if u64::from(supplied_set_capacity) < set_candidate_capacity {
2988            return Err(XlogError::Kernel(
2989                "resident schedule set workspace is undersized".into(),
2990            ));
2991        }
2992        let (join_buckets, join_next, join_required, join_bucket_mask, supplied_join_capacity) =
2993            external.join_workspace.schedule_parts();
2994        if supplied_join_capacity < join_right_capacity {
2995            return Err(XlogError::Kernel(
2996                "resident schedule join workspace is undersized".into(),
2997            ));
2998        }
2999        let function = self
3000            .device()
3001            .inner()
3002            .get_func(MODULE, KERNEL)
3003            .ok_or_else(|| XlogError::Kernel("resident_schedule_execute kernel missing".into()))?;
3004        let active_per_sm = function
3005            .occupancy_max_active_blocks_per_multiprocessor(RESIDENT_SCHEDULE_BLOCK_SIZE, 0, None)
3006            .map_err(|error| XlogError::Kernel(format!("resident schedule occupancy: {error}")))?;
3007        let multiprocessors = self
3008            .device()
3009            .inner()
3010            .attribute(sys::CUdevice_attribute::CU_DEVICE_ATTRIBUTE_MULTIPROCESSOR_COUNT)
3011            .map_err(|error| XlogError::Kernel(format!("query multiprocessor count: {error}")))?;
3012        let cooperative_limit =
3013            active_per_sm
3014                .checked_mul(u32::try_from(multiprocessors).map_err(|_| {
3015                    XlogError::Kernel("CUDA multiprocessor count is invalid".into())
3016                })?)
3017                .ok_or_else(|| XlogError::Kernel("resident schedule grid overflow".into()))?;
3018        if cooperative_limit == 0 {
3019            return Err(XlogError::Kernel(
3020                "resident schedule has zero cooperative occupancy".into(),
3021            ));
3022        }
3023        let launch_config = LaunchConfig {
3024            grid_dim: (
3025                max_capacity
3026                    .div_ceil(RESIDENT_SCHEDULE_BLOCK_SIZE)
3027                    .max(1)
3028                    .min(cooperative_limit),
3029                1,
3030                1,
3031            ),
3032            block_dim: (RESIDENT_SCHEDULE_BLOCK_SIZE, 1, 1),
3033            shared_mem_bytes: 0,
3034        };
3035
3036        let required_metadata_bytes = resident_schedule_metadata_device_bytes(
3037            bindings.len(),
3038            ops.len(),
3039            waves.len(),
3040            regions.len(),
3041            generation_metadata.len(),
3042            filter_comparisons.len(),
3043            project_expressions.len(),
3044        )?;
3045        if reservation.remaining_bytes() < required_metadata_bytes {
3046            return Err(XlogError::Kernel(format!(
3047                "resident schedule metadata requires {required_metadata_bytes} reserved bytes"
3048            )));
3049        }
3050        let slots =
3051            self.upload_resident_schedule_metadata_in_reservation(&slot_descriptors, reservation)?;
3052        let op_table = self.upload_resident_schedule_metadata_in_reservation(ops, reservation)?;
3053        let wave_table =
3054            self.upload_resident_schedule_metadata_in_reservation(waves, reservation)?;
3055        let region_table =
3056            self.upload_resident_schedule_metadata_in_reservation(regions, reservation)?;
3057        let generation_table = self
3058            .upload_resident_schedule_metadata_in_reservation(&generation_metadata, reservation)?;
3059        let filter_table =
3060            self.upload_resident_schedule_metadata_in_reservation(filter_comparisons, reservation)?;
3061        let project_table = self
3062            .upload_resident_schedule_metadata_in_reservation(project_expressions, reservation)?;
3063
3064        let header_value = ResidentScheduleHeader {
3065            slots: slots.device_ptr_value(),
3066            ops: op_table.device_ptr_value(),
3067            waves: wave_table.device_ptr_value(),
3068            regions: region_table.device_ptr_value(),
3069            generation_metadata: generation_table.device_ptr_value(),
3070            filter_comparisons: filter_table.device_ptr_value(),
3071            project_expressions: project_table.device_ptr_value(),
3072            filter_mask,
3073            filter_prefix,
3074            filter_block_sums,
3075            filter_block_offsets,
3076            set_slots,
3077            set_required,
3078            join_buckets,
3079            join_next,
3080            join_required,
3081            status: external.control.status_device_ptr(),
3082            changed: external.control.changed_device_ptr(),
3083            iterations: external.control.loop_iterations_device().device_ptr_value(),
3084            scan_trace,
3085            filter_trace,
3086            semantic_scan_trace,
3087            semantic_filter_trace,
3088            schema_seen_nonempty,
3089            schema_winner_ids,
3090            receipt_table,
3091            receipt_bytes,
3092            slot_count,
3093            op_count,
3094            wave_count,
3095            region_count,
3096            filter_comparison_count,
3097            project_expression_count,
3098            filter_capacity: supplied_filter_capacity,
3099            filter_block_count,
3100            set_slot_mask,
3101            set_candidate_capacity: supplied_set_capacity,
3102            join_bucket_mask,
3103            join_right_capacity: supplied_join_capacity,
3104            schema_winner_count,
3105            receipt_count,
3106            receipt_byte_count,
3107            generation_metadata_count,
3108            abi_version: RESIDENT_SCHEDULE_ABI_VERSION,
3109            reserved: 0,
3110        };
3111        let header =
3112            self.upload_resident_schedule_metadata_in_reservation(&[header_value], reservation)?;
3113
3114        Ok(ResidentScheduleDeviceProgram {
3115            origin_provider_identity: self.provider_identity(),
3116            domain: domain.clone(),
3117            header,
3118            _slots: slots,
3119            _ops: op_table,
3120            _waves: wave_table,
3121            _regions: region_table,
3122            _generation_metadata: generation_table,
3123            _filter_comparisons: filter_table,
3124            _project_expressions: project_table,
3125            launch_config,
3126            region_descriptors: regions.to_vec(),
3127        })
3128    }
3129
3130    fn record_resident_schedule_on_stream(
3131        &self,
3132        schedule: &ResidentSchedule<'_>,
3133        region_index: u32,
3134        conditional_handle: u64,
3135        enqueue: &crate::launch::CudaEnqueue<'_>,
3136    ) -> Result<()> {
3137        if region_index >= schedule.region_count {
3138            return Err(XlogError::Kernel(format!(
3139                "resident schedule region {region_index} is out of range"
3140            )));
3141        }
3142        let recursive = schedule.region_descriptors[region_index as usize].flags
3143            == RESIDENT_SCHEDULE_REGION_RECURSIVE;
3144        if recursive != (conditional_handle != 0) {
3145            return Err(XlogError::Kernel(
3146                "resident schedule conditional handle does not match the region kind".into(),
3147            ));
3148        }
3149        let function = self
3150            .device()
3151            .inner()
3152            .get_func(MODULE, KERNEL)
3153            .ok_or_else(|| XlogError::Kernel("resident_schedule_execute kernel missing".into()))?;
3154        let header = schedule.header.device_ptr_value();
3155        let mut params = vec![
3156            header.as_kernel_param(),
3157            region_index.as_kernel_param(),
3158            conditional_handle.as_kernel_param(),
3159        ];
3160        // SAFETY: parameters exactly match resident_schedule_execute, all captured
3161        // allocations are retained by `schedule`, and its grid is occupancy-capped.
3162        unsafe { function.launch_cooperative_in(enqueue, schedule.launch_config, &mut params) }
3163            .map_err(|error| XlogError::Kernel(format!("resident schedule launch: {error}")))
3164    }
3165
3166    /// Record one compact scheduler region into a graph owned by the caller.
3167    ///
3168    /// # Safety
3169    /// The caller must register the program, every slot and external owner, and every indirect
3170    /// receipt pointee with the one enclosing strict recorder before consuming that recorder
3171    /// through [`ResidentExecutionDomain::enqueue`]. It must enqueue on the exact stream supplied
3172    /// by that same execution domain, then commit or abort the returned owner. The program and all
3173    /// registered owners must remain alive through graph destruction and completion of all
3174    /// in-flight work. For a recursive region, the conditional body passed here must be the one
3175    /// minted for the enclosing graph, and this call must occur inside that body's active
3176    /// `capture_on_stream` callback.
3177    pub unsafe fn record_resident_schedule_region_on_stream(
3178        &self,
3179        program: &ResidentScheduleDeviceProgram,
3180        region_index: u32,
3181        conditional_body: Option<&ConditionalCudaGraphBody>,
3182        enqueue: &crate::launch::CudaEnqueue<'_>,
3183    ) -> Result<()> {
3184        let stream = enqueue.stream().as_ref();
3185        validate_execution_domain(self, &program.domain)?;
3186        if program.origin_provider_identity != self.provider_identity() {
3187            return Err(XlogError::Kernel(
3188                "resident schedule program belongs to a foreign provider".into(),
3189            ));
3190        }
3191        if !std::ptr::eq(program.domain.stream.as_ref(), stream)
3192            || program.domain.stream.cu_stream() != stream.cu_stream()
3193            || !Arc::ptr_eq(stream.context(), &program.domain.context)
3194            || stream.context().cu_ctx() != program.domain.context.cu_ctx()
3195        {
3196            return Err(XlogError::Kernel(
3197                "resident schedule record stream differs from its execution domain".into(),
3198            ));
3199        }
3200        if region_index as usize >= program.region_descriptors.len() {
3201            return Err(XlogError::Kernel(format!(
3202                "resident schedule region {region_index} is out of range"
3203            )));
3204        }
3205        let recursive = program.region_descriptors[region_index as usize].flags
3206            == RESIDENT_SCHEDULE_REGION_RECURSIVE;
3207        if recursive != conditional_body.is_some() {
3208            return Err(XlogError::Kernel(
3209                "resident schedule conditional handle does not match the region kind".into(),
3210            ));
3211        }
3212        let conditional_handle = conditional_body.map_or(0, ConditionalCudaGraphBody::handle);
3213        if conditional_body.is_some_and(|body| body.context() != program.domain.context.cu_ctx()) {
3214            return Err(XlogError::Kernel(
3215                "resident schedule conditional body belongs to a foreign CUDA context".into(),
3216            ));
3217        }
3218        let function = self
3219            .device()
3220            .inner()
3221            .get_func(MODULE, KERNEL)
3222            .ok_or_else(|| XlogError::Kernel("resident_schedule_execute kernel missing".into()))?;
3223        let header = program.header.device_ptr_value();
3224        let mut params = vec![
3225            header.as_kernel_param(),
3226            region_index.as_kernel_param(),
3227            conditional_handle.as_kernel_param(),
3228        ];
3229        function
3230            .launch_cooperative_in(enqueue, program.launch_config, &mut params)
3231            .map_err(|error| XlogError::Kernel(format!("resident schedule launch: {error}")))
3232    }
3233
3234    /// Capture every ordered region while retaining every raw-pointer owner.
3235    pub fn capture_resident_schedule<'a>(
3236        &'a self,
3237        schedule: ResidentSchedule<'a>,
3238        region_index: u32,
3239        stream: Arc<CudaStream>,
3240    ) -> Result<ResidentScheduleGraph<'a>> {
3241        if schedule.origin_provider_identity != self.provider_identity()
3242            || schedule.origin_memory_manager != Arc::as_ptr(&self.memory) as usize
3243        {
3244            return Err(XlogError::Kernel(
3245                "resident schedule belongs to a different CUDA kernel provider".into(),
3246            ));
3247        }
3248        let provider_context = self.device.inner().stream().context();
3249        if !Arc::ptr_eq(stream.context(), provider_context)
3250            || stream.context().cu_ctx() != provider_context.cu_ctx()
3251        {
3252            return Err(XlogError::Kernel(
3253                "resident schedule stream belongs to a foreign CUDA context".into(),
3254            ));
3255        }
3256        if region_index != 0 {
3257            return Err(XlogError::Kernel(
3258                "resident schedule capture must begin with its first region".into(),
3259            ));
3260        }
3261        let graph_error =
3262            |error| XlogError::Kernel(format!("resident schedule conditional graph: {error}"));
3263        let record_region = |region_index, handle| {
3264            crate::memory::with_memory_access(
3265                Arc::clone(&stream),
3266                schedule
3267                    .memory_accesses()
3268                    .map_err(|error| XlogError::Kernel(error.to_string()))?,
3269                |memory| {
3270                    self.record_resident_schedule_on_stream(
3271                        &schedule,
3272                        region_index,
3273                        handle,
3274                        &memory.cuda_enqueue()?,
3275                    )
3276                    .map_err(|error| {
3277                        crate::device_runtime::ResourceError::Driver(error.to_string())
3278                    })
3279                },
3280            )
3281            .map_err(|error| XlogError::Kernel(error.to_string()))
3282        };
3283        let mut builder = ConditionalCudaGraphSequenceBuilder::new(&stream).map_err(graph_error)?;
3284        for (index, region) in schedule.region_descriptors.iter().enumerate() {
3285            let region_index = checked_u32(index, "region index")?;
3286            if region.flags == RESIDENT_SCHEDULE_REGION_RECURSIVE {
3287                let initial_value = u32::from(region.iteration_limit != 0);
3288                builder
3289                    .add_conditional_while(initial_value, true, |body| {
3290                        let handle = body.handle();
3291                        body.capture_on_stream(&stream, || record_region(region_index, handle))
3292                    })
3293                    .map_err(graph_error)?;
3294            } else {
3295                builder
3296                    .capture_segment_on_stream(&stream, || record_region(region_index, 0))
3297                    .map_err(graph_error)?;
3298            }
3299        }
3300        let graph = builder.instantiate().map_err(graph_error)?;
3301        Ok(ResidentScheduleGraph {
3302            graph,
3303            schedule,
3304            provider: self,
3305            stream,
3306            in_flight: false,
3307        })
3308    }
3309
3310    fn observe_resident_schedule(
3311        &self,
3312        schedule: &mut ResidentSchedule<'_>,
3313        stream: &Arc<CudaStream>,
3314    ) -> Result<ResidentScheduleReceipt> {
3315        if schedule.origin_provider_identity != self.provider_identity()
3316            || schedule.origin_memory_manager != Arc::as_ptr(&self.memory) as usize
3317        {
3318            return Err(XlogError::Kernel(
3319                "resident schedule belongs to a different CUDA kernel provider".into(),
3320            ));
3321        }
3322        let bytes = schedule
3323            .pinned_receipt
3324            .copy_from_device(&schedule.receipt_bytes, stream)?;
3325        self.record_final_observation_transfer(bytes.len() as u64);
3326        let status_bytes = std::mem::size_of::<ResidentTerminalStatus>();
3327        let expected_bytes = status_bytes
3328            .checked_add(
3329                std::mem::size_of::<u32>()
3330                    .checked_mul(schedule.receipt_slots.len() + 1)
3331                    .ok_or_else(|| {
3332                        XlogError::Kernel("resident schedule receipt size overflow".into())
3333                    })?,
3334            )
3335            .ok_or_else(|| XlogError::Kernel("resident schedule receipt size overflow".into()))?;
3336        if bytes.len() != expected_bytes {
3337            return Err(XlogError::Kernel(
3338                "resident schedule receipt has an invalid byte length".into(),
3339            ));
3340        }
3341        // SAFETY: length is checked and the wire type accepts every bit pattern.
3342        let status =
3343            unsafe { std::ptr::read_unaligned(bytes.as_ptr().cast::<ResidentTerminalStatus>()) };
3344        let changed = u32::from_ne_bytes(
3345            bytes[status_bytes..status_bytes + 4]
3346                .try_into()
3347                .expect("four bytes checked"),
3348        );
3349        let mut counts = Vec::new();
3350        for chunk in bytes[status_bytes + 4..].as_chunks::<4>().0 {
3351            counts.push(u32::from_ne_bytes(*chunk));
3352        }
3353        finalize_schedule_output_counts(
3354            self,
3355            &schedule.relations,
3356            &schedule.receipt_slots,
3357            &counts,
3358        )?;
3359        counts.truncate(schedule.requested_receipt_count);
3360        Ok(ResidentScheduleReceipt {
3361            status,
3362            changed,
3363            counts,
3364        })
3365    }
3366}
3367
3368#[cfg(test)]
3369mod tests {
3370    use std::mem::{align_of, offset_of, size_of};
3371    use std::sync::Arc;
3372    use std::time::{Duration, Instant};
3373
3374    use xlog_core::MemoryBudget;
3375
3376    use crate::cuda_graph::{CapturedCudaGraph, CudaGraphNodeKind};
3377    use crate::memory::GpuMemoryManager;
3378    use crate::provider::resident_filter_project::{
3379        ResidentFilterComparison, ResidentFilterOperand, ResidentProjectExpr, ResidentScalar,
3380    };
3381    use crate::provider::resident_relational::{
3382        ResidentJoinKind, ResidentResourceCode, ResidentTerminalCode,
3383    };
3384    use crate::provider::CompareOp;
3385    use crate::{CudaBuffer, CudaColumn, CudaKernelProvider, DlpackManagedTensor};
3386    use xlog_core::{ScalarType, Schema, XlogError};
3387
3388    fn provider() -> Option<CudaKernelProvider> {
3389        match crate::CudaProviderBuilder::new(0, MemoryBudget::with_limit(512 * 1024 * 1024))
3390            .build()
3391        {
3392            Ok(provider) => Some(provider),
3393            Err(error) if std::env::var("XLOG_REQUIRE_CUDA").as_deref() == Ok("1") => {
3394                panic!("XLOG_REQUIRE_CUDA=1 but resident schedule setup failed: {error}")
3395            }
3396            Err(error) => {
3397                eprintln!("Skipping resident schedule CUDA test: {error}");
3398                None
3399            }
3400        }
3401    }
3402
3403    #[track_caller]
3404    fn schedule_kernel_error(result: xlog_core::Result<super::ResidentSchedule<'_>>) -> String {
3405        match result {
3406            Err(XlogError::Kernel(message)) => message,
3407            Err(error) => panic!("unexpected resident schedule error: {error}"),
3408            Ok(_) => panic!("malformed resident schedule unexpectedly prepared"),
3409        }
3410    }
3411
3412    fn schema(prefix: &str, types: &[ScalarType]) -> Schema {
3413        Schema::new(
3414            types
3415                .iter()
3416                .copied()
3417                .enumerate()
3418                .map(|(index, scalar)| (format!("{prefix}_{index}"), scalar))
3419                .collect(),
3420        )
3421    }
3422
3423    fn buffer(provider: &CudaKernelProvider, schema: Schema, columns: &[Vec<u64>]) -> CudaBuffer {
3424        assert_eq!(columns.len(), schema.arity());
3425        let encoded: Vec<Vec<u8>> = columns
3426            .iter()
3427            .enumerate()
3428            .map(|(column, values)| {
3429                if schema
3430                    .column_type(column)
3431                    .expect("column type")
3432                    .size_bytes()
3433                    == 4
3434                {
3435                    values
3436                        .iter()
3437                        .flat_map(|value| (*value as u32).to_le_bytes())
3438                        .collect()
3439                } else {
3440                    values
3441                        .iter()
3442                        .flat_map(|value| value.to_le_bytes())
3443                        .collect()
3444                }
3445            })
3446            .collect();
3447        let slices: Vec<&[u8]> = encoded.iter().map(Vec::as_slice).collect();
3448        provider
3449            .create_buffer_from_slices(&slices, schema)
3450            .expect("resident schedule test input")
3451    }
3452
3453    fn columns_from_rows(rows: &[Vec<u64>]) -> Vec<Vec<u64>> {
3454        let arity = rows.first().map_or(0, Vec::len);
3455        (0..arity)
3456            .map(|column| rows.iter().map(|row| row[column]).collect())
3457            .collect()
3458    }
3459
3460    fn rows_in_device_order(provider: &CudaKernelProvider, buffer: &CudaBuffer) -> Vec<Vec<u64>> {
3461        let count = provider
3462            .device_row_count(buffer)
3463            .expect("logical row count");
3464        let columns: Vec<Vec<u64>> = (0..buffer.arity())
3465            .map(|column| {
3466                if buffer
3467                    .schema()
3468                    .column_type(column)
3469                    .expect("column type")
3470                    .size_bytes()
3471                    == 4
3472                {
3473                    provider
3474                        .download_column::<u32>(buffer, column)
3475                        .expect("u32 column")
3476                        .into_iter()
3477                        .map(u64::from)
3478                        .collect()
3479                } else {
3480                    provider
3481                        .download_column::<u64>(buffer, column)
3482                        .expect("u64 column")
3483                }
3484            })
3485            .collect();
3486        (0..count)
3487            .map(|row| columns.iter().map(|column| column[row]).collect())
3488            .collect()
3489    }
3490
3491    fn normalized_rows(provider: &CudaKernelProvider, buffer: &CudaBuffer) -> Vec<Vec<u64>> {
3492        let mut rows = rows_in_device_order(provider, buffer);
3493        rows.sort_unstable();
3494        rows
3495    }
3496
3497    fn compact_set_rows(
3498        provider: &CudaKernelProvider,
3499        relation_schema: Schema,
3500        left_columns: &[Vec<u64>],
3501        right_columns: &[Vec<u64>],
3502        operation_kind: super::ResidentScheduleOpKind,
3503        output_capacity: u64,
3504    ) -> (super::ResidentScheduleReceipt, Vec<Vec<u64>>) {
3505        let left = buffer(provider, relation_schema.clone(), left_columns);
3506        let right = buffer(provider, relation_schema.clone(), right_columns);
3507        let mut output = provider
3508            .prepare_resident_relation(relation_schema, output_capacity)
3509            .expect("compact set output")
3510            .into_buffer();
3511        let relations = vec![
3512            super::ResidentScheduleRelation::source(&left, 1).expect("compact set left"),
3513            super::ResidentScheduleRelation::source(&right, 2).expect("compact set right"),
3514            super::ResidentScheduleRelation::output(&mut output, 3),
3515        ];
3516        let operation = super::ResidentOpDescriptor {
3517            kind: operation_kind,
3518            op_id: 980,
3519            out: 2,
3520            in0: 0,
3521            in1: 1,
3522            in0_generation: 1,
3523            in1_generation: 2,
3524            out_generation: 3,
3525            ..Default::default()
3526        };
3527        let wave = super::ResidentWaveDescriptor {
3528            op_count: 1,
3529            ..Default::default()
3530        };
3531        let region = super::ResidentRegionDescriptor {
3532            wave_count: 1,
3533            iteration_limit: 1,
3534            op_id: 981,
3535            flags: super::RESIDENT_SCHEDULE_REGION_INITIALIZE
3536                | super::RESIDENT_SCHEDULE_REGION_FINALIZE,
3537            slot_count: 3,
3538            ..Default::default()
3539        };
3540        let schedule = provider
3541            .prepare_resident_schedule(relations, &[operation], &[wave], &[region], &[], &[], &[2])
3542            .expect("prepare compact set schedule");
3543        let stream = provider
3544            .device()
3545            .inner()
3546            .stream()
3547            .fork()
3548            .expect("compact set stream");
3549        let mut graph = provider
3550            .capture_resident_schedule(schedule, 0, Arc::clone(&stream))
3551            .expect("capture compact set schedule");
3552        graph.launch().expect("launch compact set schedule");
3553        let receipt = graph
3554            .synchronize_and_observe()
3555            .expect("observe compact set schedule");
3556        let rows = rows_in_device_order(
3557            provider,
3558            graph.relation(2).expect("compact set output relation"),
3559        );
3560        (receipt, rows)
3561    }
3562
3563    fn compact_nullary_set_count(
3564        provider: &CudaKernelProvider,
3565        left_present: bool,
3566        right_present: bool,
3567        operation_kind: super::ResidentScheduleOpKind,
3568    ) -> u32 {
3569        let relation_schema = Schema::new(Vec::<(String, ScalarType)>::new());
3570        let mut left_relation = provider
3571            .prepare_resident_relation(relation_schema.clone(), 1)
3572            .expect("nullary left");
3573        provider
3574            .initialize_resident_relation_count(&mut left_relation, 0)
3575            .expect("initialize nullary left");
3576        let mut left = left_relation.into_buffer();
3577        let mut right_relation = provider
3578            .prepare_resident_relation(relation_schema.clone(), 1)
3579            .expect("nullary right");
3580        provider
3581            .initialize_resident_relation_count(&mut right_relation, 0)
3582            .expect("initialize nullary right");
3583        let mut right = right_relation.into_buffer();
3584        let mut output = provider
3585            .prepare_resident_relation(relation_schema, 1)
3586            .expect("nullary set output")
3587            .into_buffer();
3588        left.set_cached_row_count_if_unset(0);
3589        right.set_cached_row_count_if_unset(0);
3590        let mut operations = Vec::new();
3591        if left_present {
3592            operations.push(super::ResidentOpDescriptor {
3593                kind: super::OP_UNIT,
3594                op_id: 984,
3595                out: 0,
3596                out_generation: 1,
3597                ..Default::default()
3598            });
3599        }
3600        if right_present {
3601            operations.push(super::ResidentOpDescriptor {
3602                kind: super::OP_UNIT,
3603                op_id: 985,
3604                out: 1,
3605                out_generation: 2,
3606                ..Default::default()
3607            });
3608        }
3609        operations.push(super::ResidentOpDescriptor {
3610            kind: operation_kind,
3611            op_id: 986,
3612            out: 2,
3613            in0: 0,
3614            in1: 1,
3615            in0_generation: 1,
3616            in1_generation: 2,
3617            out_generation: 3,
3618            ..Default::default()
3619        });
3620        let relations = vec![
3621            if left_present {
3622                super::ResidentScheduleRelation::output(&mut left, 1)
3623            } else {
3624                super::ResidentScheduleRelation::source(&left, 1).expect("empty nullary left")
3625            },
3626            if right_present {
3627                super::ResidentScheduleRelation::output(&mut right, 2)
3628            } else {
3629                super::ResidentScheduleRelation::source(&right, 2).expect("empty nullary right")
3630            },
3631            super::ResidentScheduleRelation::output(&mut output, 3),
3632        ];
3633        let wave = super::ResidentWaveDescriptor {
3634            op_count: operations.len() as u32,
3635            ..Default::default()
3636        };
3637        let region = super::ResidentRegionDescriptor {
3638            wave_count: 1,
3639            iteration_limit: 1,
3640            op_id: 987,
3641            flags: super::RESIDENT_SCHEDULE_REGION_INITIALIZE
3642                | super::RESIDENT_SCHEDULE_REGION_FINALIZE,
3643            slot_count: 3,
3644            ..Default::default()
3645        };
3646        let schedule = provider
3647            .prepare_resident_schedule(relations, &operations, &[wave], &[region], &[], &[], &[2])
3648            .expect("prepare nullary compact set schedule");
3649        let stream = provider
3650            .device()
3651            .inner()
3652            .stream()
3653            .fork()
3654            .expect("nullary compact set stream");
3655        let mut graph = provider
3656            .capture_resident_schedule(schedule, 0, Arc::clone(&stream))
3657            .expect("capture nullary compact set schedule");
3658        graph.launch().expect("launch nullary compact set schedule");
3659        let receipt = graph
3660            .synchronize_and_observe()
3661            .expect("observe nullary compact set schedule");
3662        assert_eq!(
3663            receipt.status.code,
3664            ResidentTerminalCode::Success as u32,
3665            "nullary set terminal status: {:?}",
3666            receipt.status
3667        );
3668        receipt.counts[0]
3669    }
3670
3671    fn passthrough_schedule<'a>(
3672        provider: &CudaKernelProvider,
3673        input: &'a CudaBuffer,
3674        output: &'a mut CudaBuffer,
3675        op_id: u32,
3676    ) -> super::ResidentSchedule<'a> {
3677        let relations = vec![
3678            super::ResidentScheduleRelation::source(input, 1).expect("passthrough source"),
3679            super::ResidentScheduleRelation::output(output, 2),
3680        ];
3681        let operation = super::ResidentOpDescriptor {
3682            kind: super::OP_FILTER,
3683            op_id,
3684            out: 1,
3685            in0: 0,
3686            in0_generation: 1,
3687            out_generation: 2,
3688            ..Default::default()
3689        };
3690        let wave = super::ResidentWaveDescriptor {
3691            op_count: 1,
3692            ..Default::default()
3693        };
3694        let region = super::ResidentRegionDescriptor {
3695            wave_count: 1,
3696            iteration_limit: 1,
3697            op_id: op_id + 1,
3698            flags: super::RESIDENT_SCHEDULE_REGION_INITIALIZE
3699                | super::RESIDENT_SCHEDULE_REGION_FINALIZE,
3700            slot_count: 2,
3701            ..Default::default()
3702        };
3703        provider
3704            .prepare_resident_schedule(relations, &[operation], &[wave], &[region], &[], &[], &[1])
3705            .expect("prepare passthrough schedule")
3706    }
3707
3708    fn run_single_recursive_diff(
3709        provider: &CudaKernelProvider,
3710        left_values: &[u64],
3711        right_values: &[u64],
3712        iteration_limit: u32,
3713    ) -> (super::ResidentScheduleReceipt, Vec<CudaGraphNodeKind>) {
3714        let relation_schema = schema("single_recursive", &[ScalarType::U32]);
3715        let left = buffer(provider, relation_schema.clone(), &[left_values.to_vec()]);
3716        let right = buffer(provider, relation_schema.clone(), &[right_values.to_vec()]);
3717        let mut novelty = provider
3718            .prepare_resident_relation(relation_schema, left_values.len().max(1) as u64)
3719            .expect("single recursive novelty output")
3720            .into_buffer();
3721        let relations = vec![
3722            super::ResidentScheduleRelation::source(&left, 1).expect("left source"),
3723            super::ResidentScheduleRelation::source(&right, 2).expect("right source"),
3724            super::ResidentScheduleRelation::output(&mut novelty, 3),
3725        ];
3726        let operation = super::ResidentOpDescriptor {
3727            kind: super::OP_DIFF,
3728            flags: super::RESIDENT_SCHEDULE_OP_MARK_NOVELTY,
3729            op_id: 601,
3730            out: 2,
3731            in0: 0,
3732            in1: 1,
3733            in0_generation: 1,
3734            in1_generation: 2,
3735            out_generation: 3,
3736            ..Default::default()
3737        };
3738        let wave = super::ResidentWaveDescriptor {
3739            first_op: 0,
3740            op_count: 1,
3741            ..Default::default()
3742        };
3743        let regions = [
3744            super::ResidentRegionDescriptor {
3745                first_wave: 0,
3746                wave_count: 0,
3747                iteration_limit,
3748                op_id: 600,
3749                flags: super::RESIDENT_SCHEDULE_REGION_INITIALIZE
3750                    | super::RESIDENT_SCHEDULE_REGION_SCC_BEGIN,
3751                first_slot: 0,
3752                slot_count: 3,
3753                generation_offset: 0,
3754            },
3755            super::ResidentRegionDescriptor {
3756                first_wave: 0,
3757                wave_count: 1,
3758                iteration_limit,
3759                op_id: 600,
3760                flags: super::RESIDENT_SCHEDULE_REGION_RECURSIVE,
3761                first_slot: 0,
3762                slot_count: 3,
3763                generation_offset: 0,
3764            },
3765            super::ResidentRegionDescriptor {
3766                first_wave: 1,
3767                wave_count: 0,
3768                iteration_limit: 1,
3769                op_id: 602,
3770                flags: super::RESIDENT_SCHEDULE_REGION_FINALIZE,
3771                first_slot: 0,
3772                slot_count: 3,
3773                generation_offset: 0,
3774            },
3775        ];
3776        let schedule = provider
3777            .prepare_resident_schedule(relations, &[operation], &[wave], &regions, &[], &[], &[2])
3778            .expect("prepare single recursive schedule");
3779        let stream = provider
3780            .device()
3781            .inner()
3782            .stream()
3783            .fork()
3784            .expect("single recursive stream");
3785        let mut graph = provider
3786            .capture_resident_schedule(schedule, 0, Arc::clone(&stream))
3787            .expect("capture single recursive schedule");
3788        let kinds = graph
3789            .nodes()
3790            .expect("single recursive inventory")
3791            .into_iter()
3792            .map(|node| node.kind)
3793            .collect();
3794        graph.launch().expect("launch single recursive schedule");
3795        let receipt = graph
3796            .synchronize_and_observe()
3797            .expect("single recursive receipt");
3798        (receipt, kinds)
3799    }
3800
3801    fn run_two_scc_diff(
3802        provider: &CudaKernelProvider,
3803        first_limit: u32,
3804        second_limit: u32,
3805        first_changes: bool,
3806        second_changes: bool,
3807    ) -> (
3808        super::ResidentScheduleReceipt,
3809        Vec<CudaGraphNodeKind>,
3810        [u32; 2],
3811    ) {
3812        let relation_schema = schema("serial_recursive", &[ScalarType::U32]);
3813        let first_left = buffer(provider, relation_schema.clone(), &[vec![11]]);
3814        let first_right = buffer(
3815            provider,
3816            relation_schema.clone(),
3817            &[if first_changes { Vec::new() } else { vec![11] }],
3818        );
3819        let second_left = buffer(provider, relation_schema.clone(), &[vec![22]]);
3820        let second_right = buffer(
3821            provider,
3822            relation_schema.clone(),
3823            &[if second_changes { Vec::new() } else { vec![22] }],
3824        );
3825        let mut first_novelty = buffer(provider, relation_schema.clone(), &[vec![0x1111_1111]]);
3826        let mut second_novelty = buffer(provider, relation_schema, &[vec![0x2222_2222]]);
3827        let relations = vec![
3828            super::ResidentScheduleRelation::source(&first_left, 1).expect("first left"),
3829            super::ResidentScheduleRelation::source(&first_right, 2).expect("first right"),
3830            super::ResidentScheduleRelation::source(&second_left, 3).expect("second left"),
3831            super::ResidentScheduleRelation::source(&second_right, 4).expect("second right"),
3832            super::ResidentScheduleRelation::output(&mut first_novelty, 5),
3833            super::ResidentScheduleRelation::output(&mut second_novelty, 6),
3834        ];
3835        let operations = [
3836            super::ResidentOpDescriptor {
3837                kind: super::OP_DIFF,
3838                flags: super::RESIDENT_SCHEDULE_OP_MARK_NOVELTY,
3839                op_id: 711,
3840                out: 4,
3841                in0: 0,
3842                in1: 1,
3843                in0_generation: 1,
3844                in1_generation: 2,
3845                out_generation: 5,
3846                ..Default::default()
3847            },
3848            super::ResidentOpDescriptor {
3849                kind: super::OP_DIFF,
3850                flags: super::RESIDENT_SCHEDULE_OP_MARK_NOVELTY,
3851                op_id: 712,
3852                out: 5,
3853                in0: 2,
3854                in1: 3,
3855                in0_generation: 3,
3856                in1_generation: 4,
3857                out_generation: 6,
3858                ..Default::default()
3859            },
3860        ];
3861        let waves = [
3862            super::ResidentWaveDescriptor {
3863                first_op: 0,
3864                op_count: 1,
3865                ..Default::default()
3866            },
3867            super::ResidentWaveDescriptor {
3868                first_op: 1,
3869                op_count: 1,
3870                ..Default::default()
3871            },
3872        ];
3873        let regions = [
3874            super::ResidentRegionDescriptor {
3875                first_wave: 0,
3876                wave_count: 0,
3877                iteration_limit: first_limit,
3878                op_id: 701,
3879                flags: super::RESIDENT_SCHEDULE_REGION_INITIALIZE
3880                    | super::RESIDENT_SCHEDULE_REGION_SCC_BEGIN,
3881                first_slot: 0,
3882                slot_count: 6,
3883                generation_offset: 0,
3884            },
3885            super::ResidentRegionDescriptor {
3886                first_wave: 0,
3887                wave_count: 1,
3888                iteration_limit: first_limit,
3889                op_id: 701,
3890                flags: super::RESIDENT_SCHEDULE_REGION_RECURSIVE,
3891                first_slot: 0,
3892                slot_count: 6,
3893                generation_offset: 0,
3894            },
3895            super::ResidentRegionDescriptor {
3896                first_wave: 1,
3897                wave_count: 0,
3898                iteration_limit: second_limit,
3899                op_id: 702,
3900                flags: super::RESIDENT_SCHEDULE_REGION_SCC_BEGIN,
3901                first_slot: 0,
3902                slot_count: 6,
3903                generation_offset: 0,
3904            },
3905            super::ResidentRegionDescriptor {
3906                first_wave: 1,
3907                wave_count: 1,
3908                iteration_limit: second_limit,
3909                op_id: 702,
3910                flags: super::RESIDENT_SCHEDULE_REGION_RECURSIVE,
3911                first_slot: 0,
3912                slot_count: 6,
3913                generation_offset: 0,
3914            },
3915            super::ResidentRegionDescriptor {
3916                first_wave: 2,
3917                wave_count: 0,
3918                iteration_limit: 1,
3919                op_id: 703,
3920                flags: super::RESIDENT_SCHEDULE_REGION_FINALIZE,
3921                first_slot: 0,
3922                slot_count: 6,
3923                generation_offset: 0,
3924            },
3925        ];
3926        let schedule = provider
3927            .prepare_resident_schedule(relations, &operations, &waves, &regions, &[], &[], &[4, 5])
3928            .expect("prepare serial recursive schedule");
3929        let stream = provider
3930            .device()
3931            .inner()
3932            .stream()
3933            .fork()
3934            .expect("serial recursive stream");
3935        let mut graph = provider
3936            .capture_resident_schedule(schedule, 0, Arc::clone(&stream))
3937            .expect("capture serial recursive schedule");
3938        let kinds = graph
3939            .nodes()
3940            .expect("serial recursive inventory")
3941            .into_iter()
3942            .map(|node| node.kind)
3943            .collect();
3944        graph.launch().expect("launch serial recursive schedule");
3945        let receipt = graph
3946            .synchronize_and_observe()
3947            .expect("serial recursive receipt");
3948        let stored = [4_usize, 5].map(|slot| {
3949            let bytes: Vec<u8> = provider
3950                .device()
3951                .inner()
3952                .dtoh_sync_copy(
3953                    graph
3954                        .relation(slot)
3955                        .expect("novelty relation")
3956                        .column(0)
3957                        .expect("novelty column"),
3958                )
3959                .expect("novelty storage");
3960            u32::from_le_bytes(bytes[..4].try_into().expect("u32 storage"))
3961        });
3962        (receipt, kinds, stored)
3963    }
3964
3965    #[test]
3966    fn schedule_wire_abi_has_exact_sizes_alignments_and_offsets() {
3967        assert_eq!(size_of::<super::ResidentScheduleOpKind>(), 4);
3968        assert_eq!(align_of::<super::ResidentScheduleOpKind>(), 4);
3969        assert_eq!(size_of::<super::ResidentRelationView>(), 224);
3970        assert_eq!(align_of::<super::ResidentRelationView>(), 8);
3971        assert_eq!(offset_of!(super::ResidentRelationView, widths), 136);
3972        assert_eq!(offset_of!(super::ResidentRelationView, num_rows), 216);
3973
3974        assert_eq!(size_of::<super::ResidentRelationSlot>(), 240);
3975        assert_eq!(align_of::<super::ResidentRelationSlot>(), 16);
3976        assert_eq!(offset_of!(super::ResidentRelationSlot, generation), 224);
3977        assert_eq!(offset_of!(super::ResidentRelationSlot, schema_tag), 236);
3978
3979        assert_eq!(size_of::<super::ResidentOpDescriptor>(), 72);
3980        assert_eq!(align_of::<super::ResidentOpDescriptor>(), 4);
3981        assert_eq!(offset_of!(super::ResidentOpDescriptor, aux_offset), 36);
3982        assert_eq!(
3983            offset_of!(super::ResidentOpDescriptor, schema_winner_head),
3984            60
3985        );
3986        assert_eq!(
3987            offset_of!(super::ResidentOpDescriptor, schema_winner_id),
3988            64
3989        );
3990        assert_eq!(offset_of!(super::ResidentOpDescriptor, reserved), 68);
3991
3992        assert_eq!(size_of::<super::ResidentWaveDescriptor>(), 16);
3993        assert_eq!(align_of::<super::ResidentWaveDescriptor>(), 4);
3994        assert_eq!(offset_of!(super::ResidentWaveDescriptor, op_count), 4);
3995
3996        assert_eq!(size_of::<super::ResidentRegionDescriptor>(), 32);
3997        assert_eq!(align_of::<super::ResidentRegionDescriptor>(), 4);
3998        assert_eq!(offset_of!(super::ResidentRegionDescriptor, slot_count), 24);
3999        assert_eq!(
4000            offset_of!(super::ResidentRegionDescriptor, generation_offset),
4001            28
4002        );
4003
4004        assert_eq!(size_of::<super::ResidentScheduleHeader>(), 288);
4005        assert_eq!(align_of::<super::ResidentScheduleHeader>(), 16);
4006        assert_eq!(offset_of!(super::ResidentScheduleHeader, slots), 0);
4007        assert_eq!(
4008            offset_of!(super::ResidentScheduleHeader, receipt_bytes),
4009            208
4010        );
4011        assert_eq!(
4012            offset_of!(super::ResidentScheduleHeader, generation_metadata),
4013            32
4014        );
4015        assert_eq!(
4016            offset_of!(super::ResidentScheduleHeader, schema_seen_nonempty),
4017            184
4018        );
4019        assert_eq!(
4020            offset_of!(super::ResidentScheduleHeader, schema_winner_ids),
4021            192
4022        );
4023        assert_eq!(
4024            offset_of!(super::ResidentScheduleHeader, semantic_scan_trace),
4025            168
4026        );
4027        assert_eq!(
4028            offset_of!(super::ResidentScheduleHeader, semantic_filter_trace),
4029            176
4030        );
4031        assert_eq!(offset_of!(super::ResidentScheduleHeader, slot_count), 216);
4032        assert_eq!(
4033            offset_of!(super::ResidentScheduleHeader, generation_metadata_count),
4034            276
4035        );
4036        assert_eq!(
4037            offset_of!(super::ResidentScheduleHeader, schema_winner_count),
4038            264
4039        );
4040        assert_eq!(offset_of!(super::ResidentScheduleHeader, abi_version), 280);
4041        assert_eq!(offset_of!(super::ResidentScheduleHeader, reserved), 284);
4042        assert_eq!(super::RESIDENT_SCHEDULE_ABI_VERSION, 3);
4043    }
4044
4045    #[test]
4046    fn cuda_schedule_wire_matches_active_host_abi() {
4047        let source = include_str!("../../kernels/resident_schedule.cu");
4048        for required in [
4049            "constexpr uint32_t kAbiVersion = 3;",
4050            "uint32_t schema_winner_head;",
4051            "uint32_t schema_winner_id;",
4052            "uint32_t generation_offset;",
4053            "uint64_t generation_metadata;",
4054            "uint64_t schema_seen_nonempty;",
4055            "uint64_t schema_winner_ids;",
4056            "uint64_t semantic_scan_trace;",
4057            "uint64_t semantic_filter_trace;",
4058            "uint32_t generation_metadata_count;",
4059            "uint32_t abi_version;",
4060            "static_assert(sizeof(ResidentOpDescriptor) == 72",
4061            "static_assert(sizeof(ResidentScheduleHeader) == 288",
4062        ] {
4063            assert!(
4064                source.contains(required),
4065                "missing CUDA ABI fragment: {required}"
4066            );
4067        }
4068    }
4069
4070    #[test]
4071    fn flattened_descriptor_tables_have_exact_host_and_cuda_layouts() {
4072        use std::mem::{align_of, offset_of, size_of};
4073
4074        assert_eq!(size_of::<super::ResidentFilterComparisonDescriptor>(), 48);
4075        assert_eq!(align_of::<super::ResidentFilterComparisonDescriptor>(), 8);
4076        assert_eq!(
4077            offset_of!(super::ResidentFilterComparisonDescriptor, left_constant),
4078            32
4079        );
4080        assert_eq!(
4081            offset_of!(super::ResidentFilterComparisonDescriptor, right_constant),
4082            40
4083        );
4084        assert_eq!(size_of::<super::ResidentProjectExpressionDescriptor>(), 24);
4085        assert_eq!(align_of::<super::ResidentProjectExpressionDescriptor>(), 8);
4086        assert_eq!(
4087            offset_of!(super::ResidentProjectExpressionDescriptor, constant),
4088            16
4089        );
4090
4091        let cuda = include_str!("../../kernels/resident_schedule.cu");
4092        for required in [
4093            "static_assert(sizeof(ResidentFilterComparisonDescriptor) == 48",
4094            "static_assert(offsetof(ResidentFilterComparisonDescriptor, left_constant) == 32",
4095            "static_assert(offsetof(ResidentFilterComparisonDescriptor, right_constant) == 40",
4096            "static_assert(sizeof(ResidentProjectExpressionDescriptor) == 24",
4097            "static_assert(offsetof(ResidentProjectExpressionDescriptor, constant) == 16",
4098        ] {
4099            assert!(
4100                cuda.contains(required),
4101                "missing CUDA layout assertion: {required}"
4102            );
4103        }
4104    }
4105
4106    #[test]
4107    fn flattened_filter_and_project_descriptors_are_fully_validated() {
4108        let slot = |widths: &[u32], schema_tag| {
4109            let mut relation = super::ResidentRelationView {
4110                arity: widths.len() as u32,
4111                capacity: 4,
4112                ..Default::default()
4113            };
4114            relation.widths[..widths.len()].copy_from_slice(widths);
4115            super::ResidentRelationSlot {
4116                relation,
4117                schema_tag,
4118                ..Default::default()
4119            }
4120        };
4121        let slots = [slot(&[4, 4], 1), slot(&[4, 4], 1), slot(&[4, 8], 2)];
4122        let slot_types = [
4123            vec![ScalarType::Symbol, ScalarType::Symbol],
4124            vec![ScalarType::Symbol, ScalarType::Symbol],
4125            vec![ScalarType::Symbol, ScalarType::U64],
4126        ];
4127        let filter = super::ResidentOpDescriptor {
4128            kind: super::ResidentScheduleOpKind::Filter,
4129            out: 1,
4130            in0: 0,
4131            aux_count: 1,
4132            ..Default::default()
4133        };
4134        let project = super::ResidentOpDescriptor {
4135            kind: super::ResidentScheduleOpKind::Project,
4136            out: 2,
4137            in0: 0,
4138            aux_count: 2,
4139            ..Default::default()
4140        };
4141        let comparison = super::ResidentFilterComparisonDescriptor {
4142            left_kind: 0,
4143            left_column: 0,
4144            right_kind: 1,
4145            op: 0,
4146            width: 4,
4147            right_constant: 7,
4148            ..Default::default()
4149        };
4150        let expressions = [
4151            super::ResidentProjectExpressionDescriptor::column(0, 4),
4152            super::ResidentProjectExpressionDescriptor::constant(8, 9),
4153        ];
4154        super::validate_flattened_filter_project_descriptors(
4155            &slots,
4156            &slot_types,
4157            &[filter, project],
4158            &[comparison],
4159            &expressions,
4160        )
4161        .expect("valid flattened descriptors");
4162
4163        let invalid_comparisons = [
4164            super::ResidentFilterComparisonDescriptor {
4165                left_kind: 2,
4166                ..comparison
4167            },
4168            super::ResidentFilterComparisonDescriptor {
4169                left_column: 2,
4170                ..comparison
4171            },
4172            super::ResidentFilterComparisonDescriptor {
4173                width: 8,
4174                ..comparison
4175            },
4176            super::ResidentFilterComparisonDescriptor {
4177                op: 6,
4178                ..comparison
4179            },
4180            super::ResidentFilterComparisonDescriptor {
4181                reserved_zero: 1,
4182                ..comparison
4183            },
4184        ];
4185        for invalid in invalid_comparisons {
4186            assert!(super::validate_flattened_filter_project_descriptors(
4187                &slots,
4188                &slot_types,
4189                &[filter],
4190                &[invalid],
4191                &[],
4192            )
4193            .is_err());
4194        }
4195
4196        let mismatched_types = [
4197            vec![ScalarType::Symbol, ScalarType::U32],
4198            slot_types[1].clone(),
4199            slot_types[2].clone(),
4200        ];
4201        let two_columns = super::ResidentFilterComparisonDescriptor {
4202            right_kind: 0,
4203            right_column: 1,
4204            ..comparison
4205        };
4206        assert!(super::validate_flattened_filter_project_descriptors(
4207            &slots,
4208            &mismatched_types,
4209            &[filter],
4210            &[two_columns],
4211            &[],
4212        )
4213        .is_err());
4214
4215        for invalid in [
4216            super::ResidentProjectExpressionDescriptor {
4217                kind: 2,
4218                ..expressions[0]
4219            },
4220            super::ResidentProjectExpressionDescriptor {
4221                column: 2,
4222                ..expressions[0]
4223            },
4224            super::ResidentProjectExpressionDescriptor {
4225                width: 8,
4226                ..expressions[0]
4227            },
4228            super::ResidentProjectExpressionDescriptor {
4229                reserved: 1,
4230                ..expressions[0]
4231            },
4232        ] {
4233            assert!(super::validate_flattened_filter_project_descriptors(
4234                &slots,
4235                &slot_types,
4236                &[project],
4237                &[],
4238                &[invalid, expressions[1]],
4239            )
4240            .is_err());
4241        }
4242        assert!(super::validate_flattened_filter_project_descriptors(
4243            &slots,
4244            &slot_types,
4245            &[super::ResidentOpDescriptor {
4246                aux_offset: u32::MAX,
4247                aux_count: 1,
4248                ..filter
4249            }],
4250            &[comparison],
4251            &[],
4252        )
4253        .is_err());
4254    }
4255
4256    #[test]
4257    fn shared_validator_rejects_writing_alias_and_accepts_scan_identity() {
4258        let mut relation = super::ResidentRelationView {
4259            arity: 1,
4260            capacity: 4,
4261            ..Default::default()
4262        };
4263        relation.widths[0] = 4;
4264        let slots = [super::ResidentRelationSlot {
4265            relation,
4266            generation: 7,
4267            flags: super::RESIDENT_SCHEDULE_SLOT_PERMANENT | super::RESIDENT_SCHEDULE_SLOT_DEFINED,
4268            schema_tag: 1,
4269            ..Default::default()
4270        }];
4271        let types = [vec![ScalarType::U32]];
4272        let waves = [super::ResidentWaveDescriptor {
4273            first_op: 0,
4274            op_count: 1,
4275            ..Default::default()
4276        }];
4277        let regions = [super::ResidentRegionDescriptor {
4278            first_wave: 0,
4279            wave_count: 1,
4280            iteration_limit: 1,
4281            flags: super::RESIDENT_SCHEDULE_REGION_INITIALIZE
4282                | super::RESIDENT_SCHEDULE_REGION_FINALIZE,
4283            first_slot: 0,
4284            slot_count: 1,
4285            generation_offset: 0,
4286            ..Default::default()
4287        }];
4288        let aliased_filter = [super::ResidentOpDescriptor {
4289            kind: super::ResidentScheduleOpKind::Filter,
4290            op_id: 41,
4291            out: 0,
4292            in0: 0,
4293            in0_generation: 7,
4294            out_generation: 7,
4295            ..Default::default()
4296        }];
4297        assert!(super::validate_schedule_program(
4298            &slots,
4299            &types,
4300            &aliased_filter,
4301            &waves,
4302            &regions,
4303            &[7],
4304            &[],
4305            &[],
4306            &[],
4307        )
4308        .is_err());
4309
4310        let scan = [super::ResidentOpDescriptor::scan(42, 0, 7)];
4311        super::validate_schedule_program(
4312            &slots,
4313            &types,
4314            &scan,
4315            &waves,
4316            &regions,
4317            &[7],
4318            &[],
4319            &[],
4320            &[],
4321        )
4322        .expect("scan is the read-only same-slot exception");
4323    }
4324
4325    #[test]
4326    fn shared_validator_rejects_writes_to_immutable_source_slots() {
4327        let relation = super::ResidentRelationView {
4328            capacity: 1,
4329            ..Default::default()
4330        };
4331        let slots = [super::ResidentRelationSlot {
4332            relation,
4333            generation: 3,
4334            flags: super::RESIDENT_SCHEDULE_SLOT_SOURCE | super::RESIDENT_SCHEDULE_SLOT_DEFINED,
4335            ..Default::default()
4336        }];
4337        let op = [super::ResidentOpDescriptor {
4338            kind: super::ResidentScheduleOpKind::Unit,
4339            out: 0,
4340            out_generation: 3,
4341            ..Default::default()
4342        }];
4343        let waves = [super::ResidentWaveDescriptor {
4344            first_op: 0,
4345            op_count: 1,
4346            ..Default::default()
4347        }];
4348        let regions = [super::ResidentRegionDescriptor {
4349            first_wave: 0,
4350            wave_count: 1,
4351            iteration_limit: 1,
4352            flags: super::RESIDENT_SCHEDULE_REGION_INITIALIZE
4353                | super::RESIDENT_SCHEDULE_REGION_FINALIZE,
4354            first_slot: 0,
4355            slot_count: 1,
4356            generation_offset: 0,
4357            ..Default::default()
4358        }];
4359
4360        assert!(super::validate_schedule_program(
4361            &slots,
4362            &[Vec::new()],
4363            &op,
4364            &waves,
4365            &regions,
4366            &[3],
4367            &[],
4368            &[],
4369            &[],
4370        )
4371        .is_err());
4372    }
4373
4374    #[test]
4375    fn shared_validator_rejects_unknown_relation_slot_flags() {
4376        let mut relation = super::ResidentRelationView {
4377            arity: 1,
4378            capacity: 1,
4379            ..Default::default()
4380        };
4381        relation.widths[0] = 4;
4382        let slots = [super::ResidentRelationSlot {
4383            relation,
4384            generation: 3,
4385            flags: super::RESIDENT_SCHEDULE_SLOT_PERMANENT
4386                | super::RESIDENT_SCHEDULE_SLOT_DEFINED
4387                | 8,
4388            ..Default::default()
4389        }];
4390        let ops = [super::ResidentOpDescriptor::scan(43, 0, 3)];
4391        let waves = [super::ResidentWaveDescriptor {
4392            first_op: 0,
4393            op_count: 1,
4394            ..Default::default()
4395        }];
4396        let regions = [super::ResidentRegionDescriptor {
4397            first_wave: 0,
4398            wave_count: 1,
4399            iteration_limit: 1,
4400            flags: super::RESIDENT_SCHEDULE_REGION_INITIALIZE
4401                | super::RESIDENT_SCHEDULE_REGION_FINALIZE,
4402            first_slot: 0,
4403            slot_count: 1,
4404            generation_offset: 0,
4405            ..Default::default()
4406        }];
4407
4408        assert!(super::validate_schedule_program(
4409            &slots,
4410            &[vec![ScalarType::U32]],
4411            &ops,
4412            &waves,
4413            &regions,
4414            &[3],
4415            &[],
4416            &[],
4417            &[],
4418        )
4419        .is_err());
4420    }
4421
4422    #[test]
4423    fn shared_validator_simulates_scratch_definedness_and_generation_transitions() {
4424        let relation = super::ResidentRelationView {
4425            capacity: 1,
4426            ..Default::default()
4427        };
4428        let slots = [super::ResidentRelationSlot {
4429            relation,
4430            generation: 4,
4431            ..Default::default()
4432        }];
4433        let types = [Vec::new()];
4434        let region = super::ResidentRegionDescriptor {
4435            first_wave: 0,
4436            wave_count: 1,
4437            iteration_limit: 1,
4438            flags: super::RESIDENT_SCHEDULE_REGION_INITIALIZE
4439                | super::RESIDENT_SCHEDULE_REGION_FINALIZE,
4440            first_slot: 0,
4441            slot_count: 1,
4442            generation_offset: 0,
4443            ..Default::default()
4444        };
4445
4446        let scan_before_definition = [super::ResidentOpDescriptor::scan(51, 0, 4)];
4447        let one_op_wave = [super::ResidentWaveDescriptor {
4448            first_op: 0,
4449            op_count: 1,
4450            ..Default::default()
4451        }];
4452        assert!(super::validate_schedule_program(
4453            &slots,
4454            &types,
4455            &scan_before_definition,
4456            &one_op_wave,
4457            &[region],
4458            &[4],
4459            &[],
4460            &[],
4461            &[],
4462        )
4463        .is_err());
4464
4465        let producer_then_scan = [
4466            super::ResidentOpDescriptor::unit(52, 0, 5),
4467            super::ResidentOpDescriptor::scan(53, 0, 5),
4468        ];
4469        let two_op_wave = [super::ResidentWaveDescriptor {
4470            first_op: 0,
4471            op_count: 2,
4472            ..Default::default()
4473        }];
4474        super::validate_schedule_program(
4475            &slots,
4476            &types,
4477            &producer_then_scan,
4478            &two_op_wave,
4479            &[region],
4480            &[4],
4481            &[],
4482            &[],
4483            &[],
4484        )
4485        .expect("successful producer defines its next-generation scratch output");
4486
4487        let skipped_generation = [super::ResidentOpDescriptor::unit(54, 0, 6)];
4488        assert!(super::validate_schedule_program(
4489            &slots,
4490            &types,
4491            &skipped_generation,
4492            &one_op_wave,
4493            &[region],
4494            &[4],
4495            &[],
4496            &[],
4497            &[],
4498        )
4499        .is_err());
4500    }
4501
4502    #[test]
4503    fn shared_validator_rejects_physical_slots_outside_their_region_scope() {
4504        let mut relation = super::ResidentRelationView {
4505            arity: 1,
4506            capacity: 1,
4507            ..Default::default()
4508        };
4509        relation.widths[0] = 4;
4510        let slots = [
4511            super::ResidentRelationSlot {
4512                relation,
4513                generation: 1,
4514                flags: super::RESIDENT_SCHEDULE_SLOT_PERMANENT
4515                    | super::RESIDENT_SCHEDULE_SLOT_DEFINED,
4516                schema_tag: 1,
4517                ..Default::default()
4518            },
4519            super::ResidentRelationSlot {
4520                relation,
4521                generation: 2,
4522                flags: super::RESIDENT_SCHEDULE_SLOT_PERMANENT
4523                    | super::RESIDENT_SCHEDULE_SLOT_DEFINED,
4524                schema_tag: 1,
4525                ..Default::default()
4526            },
4527        ];
4528        let types = [vec![ScalarType::U32], vec![ScalarType::U32]];
4529        let ops = [super::ResidentOpDescriptor::scan(61, 1, 2)];
4530        let waves = [super::ResidentWaveDescriptor {
4531            first_op: 0,
4532            op_count: 1,
4533            ..Default::default()
4534        }];
4535        let regions = [
4536            super::ResidentRegionDescriptor {
4537                first_wave: 0,
4538                wave_count: 0,
4539                iteration_limit: 1,
4540                flags: super::RESIDENT_SCHEDULE_REGION_INITIALIZE,
4541                first_slot: 0,
4542                slot_count: 2,
4543                generation_offset: 0,
4544                ..Default::default()
4545            },
4546            super::ResidentRegionDescriptor {
4547                first_wave: 0,
4548                wave_count: 1,
4549                iteration_limit: 1,
4550                flags: super::RESIDENT_SCHEDULE_REGION_FINALIZE,
4551                first_slot: 0,
4552                slot_count: 1,
4553                generation_offset: 2,
4554                ..Default::default()
4555            },
4556        ];
4557
4558        assert!(super::validate_schedule_program(
4559            &slots,
4560            &types,
4561            &ops,
4562            &waves,
4563            &regions,
4564            &[1, 2, 1],
4565            &[],
4566            &[],
4567            &[],
4568        )
4569        .is_err());
4570    }
4571
4572    #[test]
4573    fn shared_validator_requires_recursive_novelty_and_accepts_final_delta_copy_marker() {
4574        let mut relation = super::ResidentRelationView {
4575            arity: 1,
4576            capacity: 1,
4577            ..Default::default()
4578        };
4579        relation.widths[0] = 4;
4580        let slots = [
4581            super::ResidentRelationSlot {
4582                relation,
4583                generation: 1,
4584                flags: super::RESIDENT_SCHEDULE_SLOT_PERMANENT
4585                    | super::RESIDENT_SCHEDULE_SLOT_DEFINED,
4586                schema_tag: 1,
4587                ..Default::default()
4588            },
4589            super::ResidentRelationSlot {
4590                relation,
4591                generation: 2,
4592                flags: super::RESIDENT_SCHEDULE_SLOT_PERMANENT
4593                    | super::RESIDENT_SCHEDULE_SLOT_DEFINED,
4594                schema_tag: 1,
4595                ..Default::default()
4596            },
4597            super::ResidentRelationSlot {
4598                relation,
4599                generation: 3,
4600                schema_tag: 1,
4601                ..Default::default()
4602            },
4603        ];
4604        let types = [
4605            vec![ScalarType::U32],
4606            vec![ScalarType::U32],
4607            vec![ScalarType::U32],
4608        ];
4609        let waves = [super::ResidentWaveDescriptor {
4610            first_op: 0,
4611            op_count: 1,
4612            ..Default::default()
4613        }];
4614        let regions = [
4615            super::ResidentRegionDescriptor {
4616                first_wave: 0,
4617                wave_count: 0,
4618                iteration_limit: 5,
4619                op_id: 70,
4620                flags: super::RESIDENT_SCHEDULE_REGION_INITIALIZE
4621                    | super::RESIDENT_SCHEDULE_REGION_SCC_BEGIN,
4622                first_slot: 0,
4623                slot_count: 3,
4624                generation_offset: 0,
4625            },
4626            super::ResidentRegionDescriptor {
4627                first_wave: 0,
4628                wave_count: 1,
4629                iteration_limit: 5,
4630                op_id: 70,
4631                flags: super::RESIDENT_SCHEDULE_REGION_RECURSIVE,
4632                first_slot: 0,
4633                slot_count: 3,
4634                generation_offset: 3,
4635            },
4636            super::ResidentRegionDescriptor {
4637                first_wave: 1,
4638                wave_count: 0,
4639                iteration_limit: 1,
4640                flags: super::RESIDENT_SCHEDULE_REGION_FINALIZE,
4641                first_slot: 0,
4642                slot_count: 3,
4643                generation_offset: 6,
4644                ..Default::default()
4645            },
4646        ];
4647        let baselines = [1, 2, 3, 1, 2, 3, 1, 2, 3];
4648        let diff = super::ResidentOpDescriptor {
4649            kind: super::ResidentScheduleOpKind::Diff,
4650            op_id: 71,
4651            out: 2,
4652            in0: 0,
4653            in1: 1,
4654            in0_generation: 1,
4655            in1_generation: 2,
4656            out_generation: 3,
4657            ..Default::default()
4658        };
4659        assert!(super::validate_schedule_program(
4660            &slots,
4661            &types,
4662            &[diff],
4663            &waves,
4664            &regions,
4665            &baselines,
4666            &[],
4667            &[],
4668            &[],
4669        )
4670        .is_err());
4671
4672        let marked = super::ResidentOpDescriptor {
4673            flags: super::RESIDENT_SCHEDULE_OP_MARK_NOVELTY
4674                | super::RESIDENT_SCHEDULE_OP_MARK_SCHEMA_WINNER,
4675            schema_winner_head: 0,
4676            schema_winner_id: 99,
4677            ..diff
4678        };
4679        super::validate_schedule_program(
4680            &slots,
4681            &types,
4682            &[marked],
4683            &waves,
4684            &regions,
4685            &baselines,
4686            &[],
4687            &[],
4688            &[99],
4689        )
4690        .expect("recursive Diff may mark novelty and a schema candidate together");
4691
4692        let delta_copy = super::ResidentOpDescriptor {
4693            kind: super::ResidentScheduleOpKind::Project,
4694            flags: super::RESIDENT_SCHEDULE_OP_MARK_NOVELTY,
4695            op_id: 72,
4696            out: 2,
4697            in0: 0,
4698            in0_generation: 1,
4699            out_generation: 3,
4700            aux_count: 1,
4701            ..Default::default()
4702        };
4703        super::validate_schedule_program(
4704            &slots,
4705            &types,
4706            &[delta_copy],
4707            &waves,
4708            &regions,
4709            &baselines,
4710            &[],
4711            &[super::ResidentProjectExpressionDescriptor::column(0, 4)],
4712            &[],
4713        )
4714        .expect("recursive final delta copy may drive convergence");
4715    }
4716
4717    #[test]
4718    fn shared_validator_exempts_exact_pseudo_ops_from_slot_scope() {
4719        let status = super::ResidentOpDescriptor::test_status(super::ResidentTerminalStatus {
4720            code: 5,
4721            op_id: 81,
4722            resource_code: 7,
4723            iterations: 9,
4724            limit: 11,
4725            required: 13,
4726            capacity: 17,
4727            ..Default::default()
4728        })
4729        .unwrap();
4730        let trace = super::ResidentOpDescriptor::trace_delta(2, 3, None);
4731        let ops = [status, trace];
4732        let waves = [super::ResidentWaveDescriptor {
4733            first_op: 0,
4734            op_count: 2,
4735            ..Default::default()
4736        }];
4737        let regions = [super::ResidentRegionDescriptor {
4738            first_wave: 0,
4739            wave_count: 1,
4740            iteration_limit: 1,
4741            flags: super::RESIDENT_SCHEDULE_REGION_INITIALIZE
4742                | super::RESIDENT_SCHEDULE_REGION_FINALIZE,
4743            ..Default::default()
4744        }];
4745        super::validate_schedule_program(&[], &[], &ops, &waves, &regions, &[], &[], &[], &[])
4746            .expect("exact pseudo ops do not reference relation slots");
4747
4748        let invalid_trace = [super::ResidentOpDescriptor {
4749            reserved: 1,
4750            ..trace
4751        }];
4752        let one_op_wave = [super::ResidentWaveDescriptor {
4753            first_op: 0,
4754            op_count: 1,
4755            ..Default::default()
4756        }];
4757        assert!(super::validate_schedule_program(
4758            &[],
4759            &[],
4760            &invalid_trace,
4761            &one_op_wave,
4762            &regions,
4763            &[],
4764            &[],
4765            &[],
4766            &[],
4767        )
4768        .is_err());
4769    }
4770
4771    #[test]
4772    fn shared_validator_requires_zero_only_unit_and_scan_operands() {
4773        let slots = [super::ResidentRelationSlot {
4774            relation: super::ResidentRelationView {
4775                capacity: 1,
4776                ..Default::default()
4777            },
4778            generation: 3,
4779            flags: super::RESIDENT_SCHEDULE_SLOT_PERMANENT | super::RESIDENT_SCHEDULE_SLOT_DEFINED,
4780            ..Default::default()
4781        }];
4782        let types = [Vec::new()];
4783        let waves = [super::ResidentWaveDescriptor {
4784            first_op: 0,
4785            op_count: 1,
4786            ..Default::default()
4787        }];
4788        let regions = [super::ResidentRegionDescriptor {
4789            first_wave: 0,
4790            wave_count: 1,
4791            iteration_limit: 1,
4792            flags: super::RESIDENT_SCHEDULE_REGION_INITIALIZE
4793                | super::RESIDENT_SCHEDULE_REGION_FINALIZE,
4794            first_slot: 0,
4795            slot_count: 1,
4796            generation_offset: 0,
4797            ..Default::default()
4798        }];
4799        let invalid_unit = [super::ResidentOpDescriptor {
4800            in0: 9,
4801            ..super::ResidentOpDescriptor::unit(91, 0, 3)
4802        }];
4803        assert!(super::validate_schedule_program(
4804            &slots,
4805            &types,
4806            &invalid_unit,
4807            &waves,
4808            &regions,
4809            &[3],
4810            &[],
4811            &[],
4812            &[],
4813        )
4814        .is_err());
4815
4816        let invalid_scan = [super::ResidentOpDescriptor {
4817            in1: 9,
4818            ..super::ResidentOpDescriptor::scan(92, 0, 3)
4819        }];
4820        assert!(super::validate_schedule_program(
4821            &slots,
4822            &types,
4823            &invalid_scan,
4824            &waves,
4825            &regions,
4826            &[3],
4827            &[],
4828            &[],
4829            &[],
4830        )
4831        .is_err());
4832    }
4833
4834    #[test]
4835    fn shared_validator_checks_set_and_join_layouts_and_workspace_envelopes() {
4836        let slot = |arity: u32, widths: &[u32], capacity: u32, generation: u32, permanent| {
4837            let mut relation = super::ResidentRelationView {
4838                arity,
4839                capacity,
4840                ..Default::default()
4841            };
4842            relation.widths[..widths.len()].copy_from_slice(widths);
4843            super::ResidentRelationSlot {
4844                relation,
4845                generation,
4846                flags: if permanent {
4847                    super::RESIDENT_SCHEDULE_SLOT_PERMANENT | super::RESIDENT_SCHEDULE_SLOT_DEFINED
4848                } else {
4849                    0
4850                },
4851                schema_tag: if widths == [4] { 1 } else { 2 },
4852                ..Default::default()
4853            }
4854        };
4855        let waves = [super::ResidentWaveDescriptor {
4856            first_op: 0,
4857            op_count: 1,
4858            ..Default::default()
4859        }];
4860        let region = super::ResidentRegionDescriptor {
4861            first_wave: 0,
4862            wave_count: 1,
4863            iteration_limit: 1,
4864            flags: super::RESIDENT_SCHEDULE_REGION_INITIALIZE
4865                | super::RESIDENT_SCHEDULE_REGION_FINALIZE,
4866            first_slot: 0,
4867            slot_count: 3,
4868            generation_offset: 0,
4869            ..Default::default()
4870        };
4871
4872        let set_slots = [
4873            slot(1, &[4], 3, 1, true),
4874            slot(1, &[4], 4, 2, true),
4875            slot(1, &[4], 7, 3, false),
4876        ];
4877        let set_types = [
4878            vec![ScalarType::U32],
4879            vec![ScalarType::U32],
4880            vec![ScalarType::U32],
4881        ];
4882        let union = [super::ResidentOpDescriptor {
4883            kind: super::ResidentScheduleOpKind::Union,
4884            out: 2,
4885            in0: 0,
4886            in1: 1,
4887            in0_generation: 1,
4888            in1_generation: 2,
4889            out_generation: 3,
4890            ..Default::default()
4891        }];
4892        let requirements = super::validate_schedule_program(
4893            &set_slots,
4894            &set_types,
4895            &union,
4896            &waves,
4897            &[region],
4898            &[1, 2, 3],
4899            &[],
4900            &[],
4901            &[],
4902        )
4903        .unwrap();
4904        assert_eq!(requirements.set_candidate_capacity, 7);
4905
4906        let join_slots = [
4907            slot(1, &[4], 5, 1, true),
4908            slot(1, &[8], 6, 2, true),
4909            slot(2, &[4, 8], 8, 3, false),
4910        ];
4911        let join_types = [
4912            vec![ScalarType::U32],
4913            vec![ScalarType::U64],
4914            vec![ScalarType::U32, ScalarType::U64],
4915        ];
4916        let invalid_join = [super::ResidentOpDescriptor {
4917            kind: super::ResidentScheduleOpKind::JoinInner,
4918            out: 2,
4919            in0: 0,
4920            in1: 1,
4921            in0_generation: 1,
4922            in1_generation: 2,
4923            out_generation: 3,
4924            left_key: 0,
4925            right_key: 0,
4926            ..Default::default()
4927        }];
4928        assert!(super::validate_schedule_program(
4929            &join_slots,
4930            &join_types,
4931            &invalid_join,
4932            &waves,
4933            &[region],
4934            &[1, 2, 3],
4935            &[],
4936            &[],
4937            &[],
4938        )
4939        .is_err());
4940    }
4941
4942    #[test]
4943    fn cuda_mirrors_flattened_descriptor_validation_with_subtract_bounds() {
4944        let cuda = include_str!("../../kernels/resident_schedule.cu");
4945        for required in [
4946            "op.aux_offset <= header->filter_comparison_count",
4947            "op.aux_count <= header->filter_comparison_count - op.aux_offset",
4948            "comparison.left_kind > 1",
4949            "comparison.right_kind > 1",
4950            "comparison.op > 5",
4951            "comparison.reserved_zero != 0",
4952            "comparison.reserved_one != 0",
4953            "comparison.left_column >= in0.arity",
4954            "comparison.width != in0.widths[comparison.left_column]",
4955            "op.aux_offset <= header->project_expression_count",
4956            "op.aux_count <= header->project_expression_count - op.aux_offset",
4957            "expression.kind > 1",
4958            "expression.reserved != 0",
4959            "expression.column >= in0.arity",
4960            "expression.width != out.widths[column]",
4961        ] {
4962            assert!(
4963                cuda.contains(required),
4964                "missing device validation: {required}"
4965            );
4966        }
4967    }
4968
4969    #[test]
4970    fn generation_baseline_ranges_reject_overflow_and_out_of_bounds() {
4971        let valid = [
4972            super::ResidentRegionDescriptor {
4973                slot_count: 2,
4974                generation_offset: 0,
4975                ..Default::default()
4976            },
4977            super::ResidentRegionDescriptor {
4978                slot_count: 3,
4979                generation_offset: 2,
4980                ..Default::default()
4981            },
4982        ];
4983        super::validate_generation_baseline_ranges(&valid, 5)
4984            .expect("concatenated generation baselines");
4985
4986        let out_of_bounds = [super::ResidentRegionDescriptor {
4987            slot_count: 6,
4988            generation_offset: 0,
4989            ..Default::default()
4990        }];
4991        assert_eq!(
4992            super::validate_generation_baseline_ranges(&out_of_bounds, 5)
4993                .expect_err("range must exceed generation table")
4994                .to_string(),
4995            "Kernel error: resident schedule generation baseline range is invalid"
4996        );
4997
4998        let overflow = [
4999            super::ResidentRegionDescriptor {
5000                slot_count: u32::MAX,
5001                generation_offset: 0,
5002                ..Default::default()
5003            },
5004            super::ResidentRegionDescriptor {
5005                slot_count: 1,
5006                generation_offset: u32::MAX,
5007                ..Default::default()
5008            },
5009        ];
5010        assert_eq!(
5011            super::validate_generation_baseline_ranges(&overflow, u32::MAX)
5012                .expect_err("range arithmetic must be checked")
5013                .to_string(),
5014            "Kernel error: resident schedule generation baseline range overflow"
5015        );
5016    }
5017
5018    #[test]
5019    fn generation_baselines_exactly_concatenate_region_scopes() {
5020        let first = super::ResidentRegionDescriptor {
5021            slot_count: 1,
5022            generation_offset: 0,
5023            ..Default::default()
5024        };
5025        let second = super::ResidentRegionDescriptor {
5026            slot_count: 1,
5027            generation_offset: 1,
5028            ..Default::default()
5029        };
5030        super::validate_generation_baseline_ranges(&[first, second], 2)
5031            .expect("exact concatenation");
5032
5033        assert!(super::validate_generation_baseline_ranges(
5034            &[
5035                first,
5036                super::ResidentRegionDescriptor {
5037                    generation_offset: 2,
5038                    ..second
5039                },
5040            ],
5041            3,
5042        )
5043        .is_err());
5044        assert!(super::validate_generation_baseline_ranges(
5045            &[
5046                first,
5047                super::ResidentRegionDescriptor {
5048                    generation_offset: 0,
5049                    ..second
5050                },
5051            ],
5052            2,
5053        )
5054        .is_err());
5055        assert!(super::validate_generation_baseline_ranges(&[first, second], 3).is_err());
5056    }
5057
5058    #[test]
5059    fn generation_metadata_appends_schema_defaults_and_derives_baseline_count() {
5060        let metadata =
5061            super::build_generation_metadata(&[4, 7, 9], &[101, 202]).expect("generation metadata");
5062        assert_eq!(metadata, vec![4, 7, 9, 101, 202]);
5063        assert_eq!(
5064            super::generation_baseline_count_from_metadata(5, 2)
5065                .expect("three generation baselines"),
5066            3
5067        );
5068        assert_eq!(
5069            super::generation_baseline_count_from_metadata(3, 0).expect("no schema-default tail"),
5070            3
5071        );
5072        assert!(super::generation_baseline_count_from_metadata(1, 2).is_err());
5073    }
5074
5075    #[test]
5076    fn schema_winner_replay_reset_restores_defaults_before_ordered_marks() {
5077        let defaults = [10, 20];
5078        let mut seen = [1, 1];
5079        let mut winners = [99, 98];
5080        super::reset_schema_winner_state(&defaults, &mut seen, &mut winners)
5081            .expect("reset replay state");
5082        assert_eq!(seen, [0, 0]);
5083        assert_eq!(winners, defaults);
5084
5085        super::mark_schema_winner_model(3, 10, &mut seen[0], &mut winners[0]);
5086        super::mark_schema_winner_model(2, 30, &mut seen[0], &mut winners[0]);
5087        assert_eq!(winners[0], 10, "existing nonempty head retains its default");
5088
5089        super::reset_schema_winner_state(&defaults, &mut seen, &mut winners)
5090            .expect("reset second replay");
5091        super::mark_schema_winner_model(0, 20, &mut seen[1], &mut winners[1]);
5092        super::mark_schema_winner_model(2, 40, &mut seen[1], &mut winners[1]);
5093        assert_eq!(
5094            winners[1], 40,
5095            "empty head accepts its first later contribution"
5096        );
5097    }
5098
5099    #[test]
5100    fn generation_baselines_are_concatenated_in_region_scope_order() {
5101        let mut regions = [
5102            super::ResidentRegionDescriptor {
5103                first_slot: 0,
5104                slot_count: 2,
5105                ..Default::default()
5106            },
5107            super::ResidentRegionDescriptor {
5108                first_slot: 1,
5109                slot_count: 2,
5110                ..Default::default()
5111            },
5112        ];
5113        let baselines = super::build_generation_baselines(&mut regions, &[11, 22, 33])
5114            .expect("generation baseline table");
5115        assert_eq!(baselines, vec![11, 22, 22, 33]);
5116        assert_eq!(regions[0].generation_offset, 0);
5117        assert_eq!(regions[1].generation_offset, 2);
5118
5119        let mut invalid = [super::ResidentRegionDescriptor {
5120            first_slot: 2,
5121            slot_count: 2,
5122            ..Default::default()
5123        }];
5124        assert_eq!(
5125            super::build_generation_baselines(&mut invalid, &[11, 22, 33])
5126                .expect_err("slot scope must be bounded")
5127                .to_string(),
5128            "Kernel error: resident schedule generation baseline slot scope is invalid"
5129        );
5130    }
5131
5132    #[test]
5133    fn cuda_checks_generation_baseline_range_before_resetting_slots() {
5134        let source = include_str!("../../kernels/resident_schedule.cu");
5135        let guard = source
5136            .find("const bool generation_range_valid")
5137            .expect("device generation range guard");
5138        let read = source
5139            .find("generation_metadata[region.generation_offset + index]")
5140            .expect("device generation baseline read");
5141        assert!(
5142            guard < read,
5143            "generation baseline read must follow its bounds guard"
5144        );
5145        assert!(source
5146            .contains("region.slot_count <= generation_base_count - region.generation_offset"));
5147    }
5148
5149    #[test]
5150    fn schema_winner_encoding_uses_exact_receipt_shape_and_head_bounds() {
5151        assert_eq!(
5152            super::checked_schedule_head_count(8, 76).expect("two heads"),
5153            2
5154        );
5155        assert_eq!(
5156            super::checked_schedule_winner_count(8, 76, 2).expect("matching winner state"),
5157            2
5158        );
5159        assert!(super::checked_schedule_winner_count(8, 76, 1).is_err());
5160        for (count, bytes) in [(1, 48), (5, 64), (6, 64)] {
5161            assert!(super::checked_schedule_head_count(count, bytes).is_err());
5162        }
5163
5164        let marked = super::ResidentOpDescriptor::default().with_schema_winner(1, 77);
5165        assert_eq!(marked.flags, super::RESIDENT_SCHEDULE_OP_MARK_SCHEMA_WINNER);
5166        super::validate_schema_winner_encoding(&marked, 2).expect("bounded winner mark");
5167
5168        let out_of_bounds = marked.with_schema_winner(2, 88);
5169        assert!(super::validate_schema_winner_encoding(&out_of_bounds, 2).is_err());
5170
5171        let unmarked_payload = super::ResidentOpDescriptor {
5172            schema_winner_id: 77,
5173            ..Default::default()
5174        };
5175        assert!(super::validate_schema_winner_encoding(&unmarked_payload, 2).is_err());
5176    }
5177
5178    #[test]
5179    fn cuda_schema_winner_mark_is_count_gated_and_sticky() {
5180        let source = include_str!("../../kernels/resident_schedule.cu");
5181        for required in [
5182            "const bool receipt_shape_valid",
5183            "*head_count = (header->receipt_count - 4) / 2",
5184            "header->schema_winner_count != *head_count",
5185            "op.schema_winner_head >= head_count",
5186            "*device_ptr<const uint32_t>(output.num_rows) != 0",
5187            "atomicCAS(&schema_seen_nonempty[op.schema_winner_head], 0U, 1U)",
5188            "schema_winner_ids[op.schema_winner_head] = op.schema_winner_id",
5189        ] {
5190            assert!(
5191                source.contains(required),
5192                "missing CUDA winner fragment: {required}"
5193            );
5194        }
5195        let count_gate = source
5196            .find("*device_ptr<const uint32_t>(output.num_rows) != 0")
5197            .expect("winner count gate");
5198        let compare_exchange = source
5199            .find("atomicCAS(&schema_seen_nonempty[op.schema_winner_head], 0U, 1U)")
5200            .expect("sticky winner compare-exchange");
5201        assert!(count_gate < compare_exchange);
5202        let receipt_guard = source
5203            .find("if (!receipt_shape_valid) return false;")
5204            .unwrap();
5205        let head_derivation = source
5206            .find("*head_count = (header->receipt_count - 4) / 2")
5207            .unwrap();
5208        assert!(receipt_guard < head_derivation);
5209    }
5210
5211    #[test]
5212    fn cuda_initialize_resets_schema_winners_from_metadata_tail_before_waves() {
5213        let source = include_str!("../../kernels/resident_schedule.cu");
5214        for required in [
5215            "header->generation_metadata_count < *head_count",
5216            "const uint32_t generation_base_count = generation_metadata_shape_valid",
5217            "? header->generation_metadata_count - head_count : 0;",
5218            "schema_seen_nonempty[head] = 0U;",
5219            "schema_winner_ids[head] =",
5220            "generation_metadata[generation_base_count + head];",
5221        ] {
5222            assert!(
5223                source.contains(required),
5224                "missing CUDA replay-reset fragment: {required}"
5225            );
5226        }
5227        let reset = source
5228            .find("schema_seen_nonempty[head] = 0U;")
5229            .expect("schema seen reset");
5230        let waves = source
5231            .find("for (uint32_t wave_offset = 0; wave_offset < safe_wave_count; ++wave_offset)")
5232            .expect("wave loop");
5233        assert!(
5234            reset < waves,
5235            "schema winners reset before the first operation wave"
5236        );
5237    }
5238
5239    #[test]
5240    fn cuda_validator_enforces_region_scope_and_scan_only_same_slot_aliasing() {
5241        let source = include_str!("../../kernels/resident_schedule.cu");
5242        for required in [
5243            "const ResidentRegionDescriptor &region,",
5244            "const uint32_t region_slot_end = region.first_slot + region.slot_count;",
5245            "op.kind != kOpScan && (op.out == op.in0 ||",
5246            "op.out < region.first_slot || op.out >= region_slot_end",
5247            "op.in0 != 0 || op.in1 != 0",
5248        ] {
5249            assert!(
5250                source.contains(required),
5251                "missing CUDA scope or alias fragment: {required}"
5252            );
5253        }
5254    }
5255
5256    #[test]
5257    fn cuda_validator_mirrors_physical_payload_and_workspace_checks() {
5258        let source = include_str!("../../kernels/resident_schedule.cu");
5259        for required in [
5260            "op.reserved != 0 ||",
5261            "output.relation.capacity > 65536 ||",
5262            "op.in1 != 0 || op.in1_generation != 0 ||",
5263            "op.left_key != 0 || op.right_key != 0",
5264            "static_cast<uint64_t>(in0.capacity) + in1.capacity >",
5265            "header->set_candidate_capacity",
5266            "expected_arity > kMaxArity",
5267        ] {
5268            assert!(
5269                source.contains(required),
5270                "missing CUDA physical-envelope fragment: {required}"
5271            );
5272        }
5273    }
5274
5275    #[test]
5276    fn cuda_region_reset_rejects_unknown_or_conflicting_slot_flags() {
5277        let source = include_str!("../../kernels/resident_schedule.cu");
5278        for required in [
5279            "slot.flags & ~(kSourceSlot | kPermanentSlot | kDefinedSlot)",
5280            "(slot.flags & kSourceSlot) != 0 &&",
5281            "(slot.flags & kPermanentSlot) != 0",
5282        ] {
5283            assert!(
5284                source.contains(required),
5285                "missing CUDA slot-flag validation: {required}"
5286            );
5287        }
5288    }
5289
5290    #[test]
5291    fn test_status_descriptor_round_trips_the_full_terminal_payload() {
5292        let status = super::ResidentTerminalStatus {
5293            code: 3,
5294            op_id: 0x1020_3040,
5295            resource_code: 0x5060_7080,
5296            iterations: 0x90a0_b0c0,
5297            limit: 0xd0e0_f001,
5298            reserved: 0,
5299            required: 0x1122_3344_5566_7788,
5300            capacity: 0x99aa_bbcc_ddee_ff00,
5301        };
5302        let descriptor =
5303            super::ResidentOpDescriptor::test_status(status).expect("test status descriptor");
5304        assert_eq!(descriptor.kind, super::ResidentScheduleOpKind::TestStatus);
5305        assert_eq!(super::decode_test_status(&descriptor).unwrap(), status);
5306
5307        let invalid_unused = super::ResidentOpDescriptor {
5308            right_key: 1,
5309            ..descriptor
5310        };
5311        assert!(super::decode_test_status(&invalid_unused).is_err());
5312
5313        let invalid_reserved = super::ResidentTerminalStatus {
5314            reserved: 1,
5315            ..status
5316        };
5317        assert!(super::ResidentOpDescriptor::test_status(invalid_reserved).is_err());
5318    }
5319
5320    #[test]
5321    fn cuda_test_status_descriptor_publishes_both_u64_fields_without_auxiliary_storage() {
5322        let source = include_str!("../../kernels/resident_schedule.cu");
5323        for required in [
5324            "constexpr uint32_t kOpTestStatus = 8",
5325            "op.kind == kOpTestStatus",
5326            "static_cast<uint64_t>(op.out_generation) |",
5327            "(static_cast<uint64_t>(op.aux_offset) << 32)",
5328            "static_cast<uint64_t>(op.aux_count) |",
5329            "(static_cast<uint64_t>(op.left_key) << 32)",
5330            "status->iterations = op.in1",
5331            "status->limit = op.in0_generation",
5332        ] {
5333            assert!(
5334                source.contains(required),
5335                "missing CUDA TestStatus fragment: {required}"
5336            );
5337        }
5338    }
5339
5340    #[test]
5341    fn trace_delta_descriptor_carries_an_optional_semantic_guard() {
5342        let descriptor = super::ResidentOpDescriptor::trace_delta(2, 3, None);
5343        assert_eq!(descriptor.kind, super::ResidentScheduleOpKind::TraceDelta);
5344        assert_eq!(
5345            super::decode_trace_delta(&descriptor).unwrap(),
5346            (2, 3, None)
5347        );
5348
5349        let guarded = super::ResidentOpDescriptor::trace_delta(5, 7, Some((11, 13)));
5350        assert_eq!(guarded.flags, super::RESIDENT_SCHEDULE_TRACE_SEMANTIC_GUARD);
5351        assert_eq!(guarded.in0, 11);
5352        assert_eq!(guarded.in0_generation, 13);
5353        assert_eq!(
5354            super::decode_trace_delta(&guarded).unwrap(),
5355            (5, 7, Some((11, 13)))
5356        );
5357
5358        let invalid = super::ResidentOpDescriptor {
5359            op_id: 1,
5360            ..guarded
5361        };
5362        assert!(super::decode_trace_delta(&invalid).is_err());
5363    }
5364
5365    #[test]
5366    fn cuda_trace_delta_executes_after_an_earlier_terminal_status() {
5367        let source = include_str!("../../kernels/resident_schedule.cu");
5368        for required in [
5369            "constexpr uint32_t kOpTraceDelta = 9",
5370            "constexpr uint32_t kOpTraceSemanticGuard = 1",
5371            "if (op.kind == kOpTraceDelta) {",
5372            "atomicAdd(device_ptr<uint32_t>(header->scan_trace), op.scan_delta)",
5373            "atomicAdd(device_ptr<uint32_t>(header->filter_trace), op.filter_delta)",
5374            "const bool semantic_active =",
5375            "*device_ptr<const uint32_t>(input_zero.num_rows) != 0",
5376            "header->semantic_scan_trace",
5377            "header->semantic_filter_trace",
5378        ] {
5379            assert!(
5380                source.contains(required),
5381                "missing CUDA TraceDelta fragment: {required}"
5382            );
5383        }
5384        assert!(!source.contains("status->code == kRunning && op.scan_delta"));
5385        assert!(!source.contains("status->code == kRunning && op.filter_delta"));
5386    }
5387
5388    #[test]
5389    fn cuda_set_ordering_compacts_in_parallel_and_uses_bounded_merge_passes() {
5390        let source = include_str!("../../kernels/resident_schedule.cu");
5391        for required in [
5392            "compact_set_winners_by_tile",
5393            "sort_set_reference_tiles",
5394            "merge_set_reference_runs",
5395            "kSetReferenceTileSize = 1024",
5396            "set_workspace_shape_valid",
5397            "set_slot_count >= 2ULL * header->set_candidate_capacity",
5398        ] {
5399            assert!(
5400                source.contains(required),
5401                "missing bounded set-ordering fragment: {required}"
5402            );
5403        }
5404        assert!(
5405            !source.contains("for (uint32_t slot = 0; slot <= header->set_slot_mask; ++slot)"),
5406            "set winners must not be compacted by one thread"
5407        );
5408        assert!(
5409            !source.contains("for (uint32_t width = 2; width <= sort_size; width <<= 1)"),
5410            "set ordering must not use a grid-wide bitonic network"
5411        );
5412    }
5413
5414    #[test]
5415    fn cuda_packs_the_single_receipt_only_in_the_final_region() {
5416        let source = include_str!("../../kernels/resident_schedule.cu");
5417        let guard = source
5418            .find("if (finalizes && global_rank() == 0)")
5419            .expect("final-region receipt guard");
5420        let pack = source
5421            .find("*reinterpret_cast<ResidentTerminalStatus *>(receipt) = *status")
5422            .expect("terminal receipt pack");
5423        assert!(guard < pack);
5424        assert_eq!(
5425            source
5426                .matches("*reinterpret_cast<ResidentTerminalStatus *>(receipt) = *status")
5427                .count(),
5428            1,
5429            "there must be one receipt pack path"
5430        );
5431    }
5432
5433    #[test]
5434    fn slot_definedness_distinguishes_scratch_permanent_and_failed_writes() {
5435        let scratch = super::reset_slot_flags(super::RESIDENT_SCHEDULE_SLOT_DEFINED);
5436        assert_eq!(scratch, 0);
5437        assert!(!super::slot_input_is_ready(scratch, 7, 7));
5438
5439        let permanent = super::reset_slot_flags(super::RESIDENT_SCHEDULE_SLOT_PERMANENT);
5440        assert_eq!(
5441            permanent,
5442            super::RESIDENT_SCHEDULE_SLOT_PERMANENT | super::RESIDENT_SCHEDULE_SLOT_DEFINED
5443        );
5444        assert!(super::slot_input_is_ready(permanent, 7, 7));
5445
5446        let source = super::reset_slot_flags(super::RESIDENT_SCHEDULE_SLOT_SOURCE);
5447        assert!(super::slot_input_is_ready(source, 7, 7));
5448        assert!(!super::slot_output_generation_is_valid(source, 7, 7));
5449
5450        assert!(super::slot_output_generation_is_valid(scratch, 7, 7));
5451        assert!(super::slot_output_generation_is_valid(scratch, 7, 8));
5452        assert!(!super::slot_output_generation_is_valid(scratch, 7, 9));
5453        assert!(!super::slot_output_generation_is_valid(
5454            scratch,
5455            u32::MAX,
5456            0
5457        ));
5458
5459        assert_eq!(super::finish_slot_write(scratch, false), scratch);
5460        assert_eq!(
5461            super::finish_slot_write(scratch, true),
5462            super::RESIDENT_SCHEDULE_SLOT_DEFINED
5463        );
5464    }
5465
5466    #[test]
5467    fn cuda_slot_definedness_is_reset_checked_and_set_after_success() {
5468        let source = include_str!("../../kernels/resident_schedule.cu");
5469        for required in [
5470            "constexpr uint32_t kPermanentSlot = 2",
5471            "constexpr uint32_t kDefinedSlot = 4",
5472            "slot.flags |= kDefinedSlot",
5473            "slot.flags &= ~kDefinedSlot",
5474            "(input.flags & kDefinedSlot) != 0",
5475            "slots[op.out].flags |= kDefinedSlot",
5476            "slots[op.out].generation = op.out_generation",
5477        ] {
5478            assert!(
5479                source.contains(required),
5480                "missing CUDA definedness fragment: {required}"
5481            );
5482        }
5483        let execution = source.find("execute_filter(grid").unwrap();
5484        let define = source.find("slots[op.out].flags |= kDefinedSlot").unwrap();
5485        assert!(
5486            execution < define,
5487            "output must become defined only after execution"
5488        );
5489    }
5490
5491    #[test]
5492    fn schedule_metadata_manifest_uses_exact_flattened_table_bytes() {
5493        assert_eq!(
5494            super::resident_schedule_metadata_device_bytes(0, 0, 0, 0, 0, 0, 0).unwrap(),
5495            724
5496        );
5497        assert_eq!(
5498            super::resident_schedule_metadata_device_bytes(2, 3, 4, 5, 6, 0, 2).unwrap(),
5499            1_328
5500        );
5501        let generation_count = 6;
5502        let schema_default_count = 2;
5503        assert_eq!(
5504            super::resident_schedule_metadata_device_bytes(
5505                2,
5506                3,
5507                4,
5508                5,
5509                generation_count + schema_default_count,
5510                0,
5511                2,
5512            )
5513            .unwrap(),
5514            1_336
5515        );
5516        assert!(
5517            super::resident_schedule_metadata_device_bytes(usize::MAX, 1, 1, 1, 1, 1, 1).is_err()
5518        );
5519    }
5520
5521    #[test]
5522    fn additive_schedule_api_records_one_region_into_the_existing_stream() {
5523        let _record: unsafe fn(
5524            &super::CudaKernelProvider,
5525            &super::ResidentScheduleDeviceProgram,
5526            u32,
5527            Option<&crate::cuda_graph::ConditionalCudaGraphBody>,
5528            &crate::launch::CudaEnqueue<'_>,
5529        ) -> xlog_core::Result<()> =
5530            super::CudaKernelProvider::record_resident_schedule_region_on_stream;
5531    }
5532
5533    #[test]
5534    fn additive_schedule_unsafe_contract_covers_owners_recorder_and_graph_identity() {
5535        let source = include_str!("resident_schedule.rs");
5536        let start = source
5537            .find("/// Record one compact scheduler region into a graph owned by the caller.")
5538            .expect("additive record docs");
5539        let end = source[start..]
5540            .find("pub unsafe fn record_resident_schedule_region_on_stream")
5541            .map(|offset| start + offset)
5542            .expect("additive record signature");
5543        let safety = source[start..end]
5544            .lines()
5545            .map(|line| line.trim_start().trim_start_matches("///").trim())
5546            .collect::<Vec<_>>()
5547            .join(" ");
5548        for required in [
5549            "register the program, every slot and external owner, and every indirect receipt pointee",
5550            "before consuming that recorder through [`ResidentExecutionDomain::enqueue`]",
5551            "through graph destruction and completion of all in-flight work",
5552            "commit or abort the returned owner",
5553            "conditional body passed here must be the one minted for the enclosing graph",
5554        ] {
5555            assert!(
5556                safety.contains(required),
5557                "missing additive safety obligation: {required}"
5558            );
5559        }
5560    }
5561
5562    #[test]
5563    fn allocation_owner_validation_uses_checked_live_block_ranges() {
5564        let block = crate::device_runtime::BlockId {
5565            ptr: 0x1000,
5566            generation: crate::device_runtime::Generation(1),
5567            alloc_stream: crate::device_runtime::StreamId(2),
5568            device_ordinal: 3,
5569        };
5570        assert_eq!(
5571            super::validate_runtime_allocation_fields(
5572                7,
5573                0x1004,
5574                8,
5575                block,
5576                32,
5577                crate::device_runtime::BlockState::Live,
5578                7,
5579                3,
5580            )
5581            .unwrap(),
5582            (0x1004, 0x100c)
5583        );
5584        assert!(super::validate_runtime_allocation_fields(
5585            8,
5586            0x1004,
5587            8,
5588            block,
5589            32,
5590            crate::device_runtime::BlockState::Live,
5591            7,
5592            3,
5593        )
5594        .is_err());
5595        assert!(super::validate_runtime_allocation_fields(
5596            7,
5597            u64::MAX - 1,
5598            4,
5599            block,
5600            32,
5601            crate::device_runtime::BlockState::Live,
5602            7,
5603            3,
5604        )
5605        .is_err());
5606        assert!(super::validate_runtime_allocation_fields(
5607            7,
5608            0x1004,
5609            8,
5610            block,
5611            32,
5612            crate::device_runtime::BlockState::Retired,
5613            7,
5614            3,
5615        )
5616        .is_err());
5617    }
5618
5619    #[test]
5620    fn allocation_inventory_rejects_partial_aliases_but_allows_adjacency() {
5621        let mut ranges = Vec::new();
5622        super::insert_nonoverlapping_allocation_range(&mut ranges, (0x1000, 0x1010))
5623            .expect("first allocation");
5624        super::insert_nonoverlapping_allocation_range(&mut ranges, (0x1010, 0x1020))
5625            .expect("adjacent allocation");
5626        assert!(
5627            super::insert_nonoverlapping_allocation_range(&mut ranges, (0x1008, 0x1018)).is_err()
5628        );
5629    }
5630
5631    #[test]
5632    fn receipt_slot_mapping_requires_exact_unique_permanent_targets() {
5633        let permanent =
5634            super::RESIDENT_SCHEDULE_SLOT_PERMANENT | super::RESIDENT_SCHEDULE_SLOT_DEFINED;
5635        let source = super::RESIDENT_SCHEDULE_SLOT_SOURCE | super::RESIDENT_SCHEDULE_SLOT_DEFINED;
5636        let flags = [source, permanent, permanent, 0];
5637
5638        assert_eq!(
5639            super::validate_receipt_slot_mapping(&[], &flags, 0).unwrap(),
5640            Vec::<usize>::new()
5641        );
5642        assert_eq!(
5643            super::validate_receipt_slot_mapping(&[2], &flags, 1).unwrap(),
5644            vec![2]
5645        );
5646        assert_eq!(
5647            super::validate_receipt_slot_mapping(&[2, 1], &flags, 2).unwrap(),
5648            vec![2, 1]
5649        );
5650        assert!(super::validate_receipt_slot_mapping(&[1], &flags, 2).is_err());
5651        assert!(super::validate_receipt_slot_mapping(&[1, 1], &flags, 2).is_err());
5652        assert!(super::validate_receipt_slot_mapping(&[0], &flags, 1).is_err());
5653        assert!(super::validate_receipt_slot_mapping(&[3], &flags, 1).is_err());
5654        assert!(super::validate_receipt_slot_mapping(&[4], &flags, 1).is_err());
5655    }
5656
5657    #[test]
5658    fn device_program_construction_consumes_the_runtime_reservation_and_external_bindings() {
5659        type PrepareResidentProgram =
5660            for<'a> fn(
5661                &super::CudaKernelProvider,
5662                &super::ResidentExecutionDomain,
5663                &[super::ResidentScheduleSlotBinding<'a>],
5664                &[super::ResidentOpDescriptor],
5665                &[super::ResidentWaveDescriptor],
5666                &[super::ResidentRegionDescriptor],
5667                &[u32],
5668                &[super::ResidentFilterComparisonDescriptor],
5669                &[super::ResidentProjectExpressionDescriptor],
5670                &[u32],
5671                super::ResidentScheduleExternalBindings<'a>,
5672                &mut crate::memory::GpuMemoryReservation,
5673            ) -> xlog_core::Result<super::ResidentScheduleDeviceProgram>;
5674        let _prepare: PrepareResidentProgram =
5675            super::CudaKernelProvider::prepare_resident_schedule_program_in_reservation;
5676    }
5677
5678    #[test]
5679    fn additive_schedule_metadata_and_external_owners_have_strict_recorder_apis() {
5680        fn record_slot(
5681            slot: &super::ResidentScheduleSlotBinding<'_>,
5682            recorder: &mut crate::launch::LaunchRecorder,
5683        ) {
5684            slot.record_uses(recorder)
5685        }
5686        fn record_external(
5687            external: &super::ResidentScheduleExternalBindings<'_>,
5688            recorder: &mut crate::launch::LaunchRecorder,
5689        ) {
5690            external.record_uses(recorder)
5691        }
5692        let _program: fn(
5693            &super::ResidentScheduleDeviceProgram,
5694            &mut crate::launch::LaunchRecorder,
5695        ) = super::ResidentScheduleDeviceProgram::record_uses;
5696        let _slot = record_slot;
5697        let _external = record_external;
5698    }
5699
5700    #[test]
5701    fn slot_reset_preserves_sources_and_clears_permanent_outputs_at_initialization() {
5702        let source =
5703            super::reset_slot_state_for_region(super::RESIDENT_SCHEDULE_SLOT_SOURCE, 9, 4, true);
5704        assert_eq!(
5705            source,
5706            (
5707                super::RESIDENT_SCHEDULE_SLOT_SOURCE | super::RESIDENT_SCHEDULE_SLOT_DEFINED,
5708                9,
5709                4,
5710            )
5711        );
5712        let permanent = super::reset_slot_state_for_region(
5713            super::RESIDENT_SCHEDULE_SLOT_PERMANENT,
5714            7,
5715            3,
5716            false,
5717        );
5718        assert_eq!(
5719            permanent,
5720            (
5721                super::RESIDENT_SCHEDULE_SLOT_PERMANENT | super::RESIDENT_SCHEDULE_SLOT_DEFINED,
5722                7,
5723                3,
5724            )
5725        );
5726        assert_eq!(
5727            super::reset_slot_state_for_region(super::RESIDENT_SCHEDULE_SLOT_PERMANENT, 7, 3, true),
5728            (
5729                super::RESIDENT_SCHEDULE_SLOT_PERMANENT | super::RESIDENT_SCHEDULE_SLOT_DEFINED,
5730                7,
5731                0,
5732            )
5733        );
5734        assert_eq!(
5735            super::reset_slot_state_for_region(0, 11, 8, true),
5736            (0, 11, 0)
5737        );
5738    }
5739
5740    #[test]
5741    fn cuda_reset_and_recorder_keep_source_count_read_only() {
5742        let cuda = include_str!("../../kernels/resident_schedule.cu");
5743        let reset_start = cuda
5744            .find("for (uint32_t index = 0; index < region.slot_count; ++index)")
5745            .expect("slot reset loop");
5746        let reset_end = cuda[reset_start..]
5747            .find("if (status->code == kRunning && recursive)")
5748            .map(|offset| reset_start + offset)
5749            .expect("slot reset end");
5750        let reset = &cuda[reset_start..reset_end];
5751        assert!(!reset.contains("slot.initial_count"));
5752        assert_eq!(
5753            reset
5754                .matches("*device_ptr<uint32_t>(slot.relation.num_rows) = 0")
5755                .count(),
5756            2,
5757            "scratch resets every region; permanent outputs reset only at initialization"
5758        );
5759
5760        let rust = include_str!("resident_schedule.rs");
5761        let source_arm = rust
5762            .find("Self::Source { buffer, .. } => {")
5763            .expect("source recorder arm");
5764        let resident_arm = rust[source_arm..]
5765            .find("Self::Resident { buffer, .. } => {")
5766            .map(|offset| source_arm + offset)
5767            .expect("resident recorder arm");
5768        let source_recorder = &rust[source_arm..resident_arm];
5769        assert!(source_recorder.contains("recorder.read(buffer.num_rows_device())"));
5770        assert!(!source_recorder.contains("read_write(buffer.num_rows_device())"));
5771    }
5772
5773    #[test]
5774    fn operation_kind_api_expresses_typed_unit_and_scan_leaves() {
5775        let unit = super::ResidentOpDescriptor::unit(101, 3, 7);
5776        assert_eq!(unit.kind, super::ResidentScheduleOpKind::Unit);
5777        assert_eq!(unit.op_id, 101);
5778        assert_eq!(unit.out, 3);
5779        assert_eq!(unit.out_generation, 7);
5780
5781        let scan = super::ResidentOpDescriptor::scan(102, 4, 9);
5782        assert_eq!(scan.kind, super::ResidentScheduleOpKind::Scan);
5783        assert_eq!(scan.op_id, 102);
5784        assert_eq!(scan.in0, 4);
5785        assert_eq!(scan.in0_generation, 9);
5786        assert_eq!(scan.out, 4);
5787        assert_eq!(scan.out_generation, 9);
5788    }
5789
5790    #[test]
5791    fn initialization_scope_must_cover_every_relation_slot() {
5792        let full = super::ResidentRegionDescriptor {
5793            flags: super::RESIDENT_SCHEDULE_REGION_INITIALIZE,
5794            first_slot: 0,
5795            slot_count: 3,
5796            ..Default::default()
5797        };
5798        super::validate_initialization_scope(&full, 3).expect("full initialization scope");
5799
5800        let partial = super::ResidentRegionDescriptor {
5801            slot_count: 2,
5802            ..full
5803        };
5804        assert_eq!(
5805            super::validate_initialization_scope(&partial, 3)
5806                .expect_err("partial initialization scope")
5807                .to_string(),
5808            "Kernel error: resident schedule initialization must cover every relation slot"
5809        );
5810    }
5811
5812    #[test]
5813    fn region_control_placement_is_exact_before_materialization() {
5814        let region = |flags, first_wave, iteration_limit| super::ResidentRegionDescriptor {
5815            first_wave,
5816            wave_count: 1,
5817            iteration_limit,
5818            op_id: first_wave,
5819            flags,
5820            first_slot: 0,
5821            slot_count: 2,
5822            generation_offset: first_wave * 2,
5823        };
5824
5825        assert!(super::validate_region_control_and_ranges(
5826            &[region(
5827                super::RESIDENT_SCHEDULE_REGION_INITIALIZE
5828                    | super::RESIDENT_SCHEDULE_REGION_FINALIZE,
5829                0,
5830                1,
5831            )],
5832            1,
5833            2,
5834        )
5835        .is_ok());
5836
5837        let mut valid = [
5838            region(
5839                super::RESIDENT_SCHEDULE_REGION_INITIALIZE
5840                    | super::RESIDENT_SCHEDULE_REGION_SCC_BEGIN,
5841                0,
5842                5,
5843            ),
5844            region(super::RESIDENT_SCHEDULE_REGION_RECURSIVE, 1, 5),
5845            region(super::RESIDENT_SCHEDULE_REGION_FINALIZE, 2, 1),
5846        ];
5847        valid[1].op_id = valid[0].op_id;
5848        assert!(super::validate_region_control_and_ranges(&valid, 3, 2).is_ok());
5849
5850        for invalid in [
5851            vec![region(super::RESIDENT_SCHEDULE_REGION_FINALIZE, 0, 1)],
5852            vec![region(super::RESIDENT_SCHEDULE_REGION_INITIALIZE, 0, 1)],
5853            vec![
5854                region(super::RESIDENT_SCHEDULE_REGION_INITIALIZE, 0, 1),
5855                region(
5856                    super::RESIDENT_SCHEDULE_REGION_INITIALIZE
5857                        | super::RESIDENT_SCHEDULE_REGION_FINALIZE,
5858                    1,
5859                    1,
5860                ),
5861            ],
5862            vec![region(
5863                super::RESIDENT_SCHEDULE_REGION_INITIALIZE
5864                    | super::RESIDENT_SCHEDULE_REGION_RECURSIVE
5865                    | super::RESIDENT_SCHEDULE_REGION_FINALIZE,
5866                0,
5867                1,
5868            )],
5869            vec![
5870                region(
5871                    super::RESIDENT_SCHEDULE_REGION_INITIALIZE
5872                        | super::RESIDENT_SCHEDULE_REGION_SCC_BEGIN,
5873                    0,
5874                    5,
5875                ),
5876                region(
5877                    super::RESIDENT_SCHEDULE_REGION_SCC_BEGIN
5878                        | super::RESIDENT_SCHEDULE_REGION_RECURSIVE,
5879                    1,
5880                    5,
5881                ),
5882                region(super::RESIDENT_SCHEDULE_REGION_FINALIZE, 2, 1),
5883            ],
5884            vec![region(
5885                super::RESIDENT_SCHEDULE_REGION_INITIALIZE
5886                    | super::RESIDENT_SCHEDULE_REGION_FINALIZE,
5887                0,
5888                2,
5889            )],
5890        ] {
5891            assert!(
5892                super::validate_region_control_and_ranges(&invalid, invalid.len() as u32, 2)
5893                    .is_err()
5894            );
5895        }
5896    }
5897
5898    #[test]
5899    fn waves_exactly_partition_operations_before_materialization() {
5900        let wave = |first_op, op_count| super::ResidentWaveDescriptor {
5901            first_op,
5902            op_count,
5903            flags: 0,
5904            reserved: 0,
5905        };
5906        assert!(super::validate_wave_partition(&[], 0).is_ok());
5907        assert!(super::validate_wave_partition(&[wave(0, 2), wave(2, 1)], 3).is_ok());
5908        for invalid in [
5909            vec![wave(1, 2)],
5910            vec![wave(0, 1), wave(2, 1)],
5911            vec![wave(0, 2), wave(1, 1)],
5912            vec![wave(0, 1)],
5913        ] {
5914            assert!(super::validate_wave_partition(&invalid, 3).is_err());
5915        }
5916        assert!(super::validate_wave_partition(
5917            &[super::ResidentWaveDescriptor {
5918                flags: 1,
5919                ..wave(0, 1)
5920            }],
5921            1,
5922        )
5923        .is_err());
5924        assert!(super::validate_wave_partition(
5925            &[super::ResidentWaveDescriptor {
5926                reserved: 1,
5927                ..wave(0, 1)
5928            }],
5929            1,
5930        )
5931        .is_err());
5932    }
5933
5934    #[test]
5935    fn scalar_envelope_is_symbol_u32_and_u64_only() {
5936        assert_eq!(
5937            super::resident_schedule_scalar_width(ScalarType::Symbol).expect("symbol"),
5938            4
5939        );
5940        assert_eq!(
5941            super::resident_schedule_scalar_width(ScalarType::U32).expect("u32"),
5942            4
5943        );
5944        assert_eq!(
5945            super::resident_schedule_scalar_width(ScalarType::U64).expect("u64"),
5946            8
5947        );
5948        for unsupported in [
5949            ScalarType::I32,
5950            ScalarType::I64,
5951            ScalarType::F32,
5952            ScalarType::F64,
5953            ScalarType::Bool,
5954        ] {
5955            assert!(
5956                super::resident_schedule_scalar_width(unsupported).is_err(),
5957                "{unsupported:?} reached the unsigned scheduler kernel"
5958            );
5959        }
5960    }
5961
5962    #[test]
5963    fn device_storage_ranges_reject_partial_overlap() {
5964        assert!(super::device_ranges_overlap(0x1000, 16, 0x1008, 16));
5965        assert!(super::device_ranges_overlap(0x1008, 16, 0x1000, 16));
5966        assert!(!super::device_ranges_overlap(0x1000, 8, 0x1008, 8));
5967        assert!(!super::device_ranges_overlap(0x1000, 0, 0x1000, 8));
5968    }
5969
5970    #[test]
5971    fn preparation_rejects_filter_column_outside_input_schema() {
5972        let Some(provider) = provider() else { return };
5973        let relation_schema = schema("value", &[ScalarType::U32]);
5974        let input = buffer(&provider, relation_schema.clone(), &[vec![7]]);
5975        let mut output = buffer(&provider, relation_schema, &[vec![0]]);
5976        assert_eq!(output.cached_row_count(), Some(1));
5977        let relations = vec![
5978            super::ResidentScheduleRelation::source(&input, 1).expect("source relation"),
5979            super::ResidentScheduleRelation::output(&mut output, 2),
5980        ];
5981        let operations = [super::ResidentOpDescriptor {
5982            kind: super::OP_FILTER,
5983            op_id: 401,
5984            out: 1,
5985            in0: 0,
5986            in1: 0,
5987            in0_generation: 1,
5988            in1_generation: 0,
5989            out_generation: 2,
5990            aux_count: 1,
5991            ..Default::default()
5992        }];
5993        let comparisons = [super::ResidentFilterComparisonDescriptor::column_constant(
5994            1, 0, 4, 7,
5995        )];
5996        let wave = super::ResidentWaveDescriptor {
5997            op_count: 1,
5998            ..Default::default()
5999        };
6000        let region = super::ResidentRegionDescriptor {
6001            wave_count: 1,
6002            iteration_limit: 1,
6003            op_id: 400,
6004            flags: super::RESIDENT_SCHEDULE_REGION_INITIALIZE
6005                | super::RESIDENT_SCHEDULE_REGION_FINALIZE,
6006            slot_count: 2,
6007            ..Default::default()
6008        };
6009
6010        assert_eq!(
6011            schedule_kernel_error(provider.prepare_resident_schedule(
6012                relations,
6013                &operations,
6014                &[wave],
6015                &[region],
6016                &comparisons,
6017                &[],
6018                &[],
6019            )),
6020            "resident schedule descriptor column is invalid"
6021        );
6022        assert_eq!(output.cached_row_count(), Some(1));
6023    }
6024
6025    #[test]
6026    fn preparation_rejects_non_nullary_unit_without_invalidating_output() {
6027        let Some(provider) = provider() else { return };
6028        let relation_schema = schema("not_unit", &[ScalarType::U32]);
6029        let mut output = buffer(&provider, relation_schema, &[vec![17]]);
6030        let relations = vec![super::ResidentScheduleRelation::output(&mut output, 2)];
6031        let operation = super::ResidentOpDescriptor::unit(451, 0, 2);
6032        let wave = super::ResidentWaveDescriptor {
6033            op_count: 1,
6034            ..Default::default()
6035        };
6036        let region = super::ResidentRegionDescriptor {
6037            wave_count: 1,
6038            iteration_limit: 1,
6039            op_id: 450,
6040            flags: super::RESIDENT_SCHEDULE_REGION_INITIALIZE
6041                | super::RESIDENT_SCHEDULE_REGION_FINALIZE,
6042            slot_count: 1,
6043            ..Default::default()
6044        };
6045
6046        assert_eq!(
6047            schedule_kernel_error(provider.prepare_resident_schedule(
6048                relations,
6049                &[operation],
6050                &[wave],
6051                &[region],
6052                &[],
6053                &[],
6054                &[0],
6055            )),
6056            "resident schedule unit 451 has nonzero operands or invalid output"
6057        );
6058        assert_eq!(output.cached_row_count(), Some(1));
6059    }
6060
6061    #[test]
6062    fn real_cuda_unit_and_scan_execute_complete_leaf_semantics() {
6063        let Some(provider) = provider() else { return };
6064        let unit_schema = Schema::new(Vec::new());
6065        let mut unit_output = provider
6066            .prepare_resident_relation(unit_schema.clone(), 1)
6067            .expect("unit output")
6068            .into_buffer();
6069        let unit_relations = vec![super::ResidentScheduleRelation::output(&mut unit_output, 7)];
6070        let unit_op = super::ResidentOpDescriptor::unit(461, 0, 7);
6071        let wave = super::ResidentWaveDescriptor {
6072            op_count: 1,
6073            ..Default::default()
6074        };
6075        let region = super::ResidentRegionDescriptor {
6076            wave_count: 1,
6077            iteration_limit: 1,
6078            op_id: 460,
6079            flags: super::RESIDENT_SCHEDULE_REGION_INITIALIZE
6080                | super::RESIDENT_SCHEDULE_REGION_FINALIZE,
6081            slot_count: 1,
6082            ..Default::default()
6083        };
6084        let unit_schedule = provider
6085            .prepare_resident_schedule(
6086                unit_relations,
6087                &[unit_op],
6088                &[wave],
6089                &[region],
6090                &[],
6091                &[],
6092                &[0],
6093            )
6094            .expect("prepare Unit schedule");
6095        let unit_stream = provider
6096            .device()
6097            .inner()
6098            .stream()
6099            .fork()
6100            .expect("Unit stream");
6101        let mut unit_graph = provider
6102            .capture_resident_schedule(unit_schedule, 0, Arc::clone(&unit_stream))
6103            .expect("capture Unit schedule");
6104        unit_graph.launch().expect("launch Unit schedule");
6105        let unit_receipt = unit_graph
6106            .synchronize_and_observe()
6107            .expect("observe Unit schedule");
6108        assert_eq!(
6109            unit_receipt.status.code,
6110            ResidentTerminalCode::Success as u32
6111        );
6112        assert_eq!(unit_receipt.counts, vec![1]);
6113        drop(unit_graph);
6114        assert_eq!(unit_output.cached_row_count(), Some(1));
6115
6116        let scan_schema = schema("scan", &[ScalarType::U32]);
6117        let scan_source = buffer(&provider, scan_schema, &[vec![3, 5, 8]]);
6118        let scan_relations =
6119            vec![super::ResidentScheduleRelation::source(&scan_source, 9).expect("Scan source")];
6120        let scan_op = super::ResidentOpDescriptor::scan(471, 0, 9);
6121        let scan_schedule = provider
6122            .prepare_resident_schedule(
6123                scan_relations,
6124                &[scan_op],
6125                &[wave],
6126                &[super::ResidentRegionDescriptor {
6127                    op_id: 470,
6128                    ..region
6129                }],
6130                &[],
6131                &[],
6132                &[0],
6133            )
6134            .expect("prepare Scan schedule");
6135        let scan_stream = provider
6136            .device()
6137            .inner()
6138            .stream()
6139            .fork()
6140            .expect("Scan stream");
6141        let mut scan_graph = provider
6142            .capture_resident_schedule(scan_schedule, 0, scan_stream)
6143            .expect("capture Scan schedule");
6144        scan_graph.launch().expect("launch Scan schedule");
6145        let scan_receipt = scan_graph
6146            .synchronize_and_observe()
6147            .expect("observe Scan schedule");
6148        assert_eq!(
6149            scan_receipt.status.code,
6150            ResidentTerminalCode::Success as u32
6151        );
6152        assert_eq!(scan_receipt.counts, vec![3]);
6153        assert_eq!(scan_source.cached_row_count(), Some(3));
6154    }
6155
6156    #[test]
6157    fn real_cuda_unit_capacity_zero_reports_exact_overflow_without_storage() {
6158        let Some(provider) = provider() else { return };
6159        let mut output = provider
6160            .prepare_resident_relation(Schema::new(Vec::new()), 0)
6161            .expect("zero-capacity Unit output")
6162            .into_buffer();
6163        let relations = vec![super::ResidentScheduleRelation::output(&mut output, 3)];
6164        let operation = super::ResidentOpDescriptor::unit(481, 0, 3);
6165        let wave = super::ResidentWaveDescriptor {
6166            op_count: 1,
6167            ..Default::default()
6168        };
6169        let region = super::ResidentRegionDescriptor {
6170            wave_count: 1,
6171            iteration_limit: 1,
6172            op_id: 480,
6173            flags: super::RESIDENT_SCHEDULE_REGION_INITIALIZE
6174                | super::RESIDENT_SCHEDULE_REGION_FINALIZE,
6175            slot_count: 1,
6176            ..Default::default()
6177        };
6178        let schedule = provider
6179            .prepare_resident_schedule(relations, &[operation], &[wave], &[region], &[], &[], &[0])
6180            .expect("prepare zero-capacity Unit schedule");
6181        let stream = provider
6182            .device()
6183            .inner()
6184            .stream()
6185            .fork()
6186            .expect("zero-capacity Unit stream");
6187        let mut graph = provider
6188            .capture_resident_schedule(schedule, 0, stream)
6189            .expect("capture zero-capacity Unit schedule");
6190        graph.launch().expect("launch zero-capacity Unit schedule");
6191        let receipt = graph
6192            .synchronize_and_observe()
6193            .expect("observe zero-capacity Unit schedule");
6194        assert_eq!(
6195            receipt.status.code,
6196            ResidentTerminalCode::CapacityOverflow as u32
6197        );
6198        assert_eq!(receipt.status.op_id, 481);
6199        assert_eq!(
6200            receipt.status.resource_code,
6201            ResidentResourceCode::OutputRows as u32
6202        );
6203        assert_eq!(receipt.status.required, 1);
6204        assert_eq!(receipt.status.capacity, 0);
6205        assert_eq!(receipt.counts, vec![0]);
6206    }
6207
6208    #[test]
6209    fn preparation_rejects_same_slot_input_output_alias() {
6210        let Some(provider) = provider() else { return };
6211        let input = buffer(
6212            &provider,
6213            schema("alias", &[ScalarType::U32]),
6214            &[vec![1, 2]],
6215        );
6216        let relations =
6217            vec![super::ResidentScheduleRelation::source(&input, 7).expect("source relation")];
6218        let operation = super::ResidentOpDescriptor {
6219            kind: super::OP_FILTER,
6220            op_id: 402,
6221            out: 0,
6222            in0: 0,
6223            in1: 0,
6224            in0_generation: 7,
6225            out_generation: 7,
6226            ..Default::default()
6227        };
6228        let wave = super::ResidentWaveDescriptor {
6229            first_op: 0,
6230            op_count: 1,
6231            ..Default::default()
6232        };
6233        let region = super::ResidentRegionDescriptor {
6234            first_wave: 0,
6235            wave_count: 1,
6236            iteration_limit: 1,
6237            op_id: 402,
6238            flags: super::RESIDENT_SCHEDULE_REGION_INITIALIZE
6239                | super::RESIDENT_SCHEDULE_REGION_FINALIZE,
6240            first_slot: 0,
6241            slot_count: 1,
6242            generation_offset: 0,
6243        };
6244
6245        let error = match provider.prepare_resident_schedule(
6246            relations,
6247            &[operation],
6248            &[wave],
6249            &[region],
6250            &[],
6251            &[],
6252            &[],
6253        ) {
6254            Err(error) => error,
6255            Ok(_) => panic!("same-slot input/output alias reached device preparation"),
6256        };
6257        assert!(error.to_string().contains("aliases"));
6258        assert_eq!(input.cached_row_count(), Some(2));
6259    }
6260
6261    #[test]
6262    fn preparation_rejects_cross_slot_shared_runtime_allocation_alias() {
6263        let Some(provider) = provider() else {
6264            return;
6265        };
6266        let relation_schema = schema("shared_storage", &[ScalarType::U32]);
6267        let mut source = buffer(&provider, relation_schema.clone(), &[vec![7]]);
6268        let mut output = buffer(&provider, relation_schema, &[vec![9]]);
6269        let shared = Arc::new(
6270            provider
6271                .memory
6272                .alloc::<u8>(4)
6273                .expect("shared runtime allocation"),
6274        );
6275        assert!(
6276            shared.runtime_block().is_some(),
6277            "alias witness requires runtime block identity and generation"
6278        );
6279        let stream = Arc::clone(provider.device().inner().stream());
6280        let source_tensor = unsafe { DlpackManagedTensor::from_raw(std::ptr::null_mut()) };
6281        let output_tensor = unsafe { DlpackManagedTensor::from_raw(std::ptr::null_mut()) };
6282        source.columns[0] =
6283            CudaColumn::dlpack_xlog_owned(Arc::clone(&shared), Arc::clone(&stream), source_tensor);
6284        output.columns[0] = CudaColumn::dlpack_xlog_owned(shared, stream, output_tensor);
6285        let relations = vec![
6286            super::ResidentScheduleRelation::source(&source, 1).expect("shared source"),
6287            super::ResidentScheduleRelation::output(&mut output, 2),
6288        ];
6289        let wave = super::ResidentWaveDescriptor {
6290            first_op: 0,
6291            op_count: 0,
6292            ..Default::default()
6293        };
6294        let region = super::ResidentRegionDescriptor {
6295            first_wave: 0,
6296            wave_count: 1,
6297            iteration_limit: 1,
6298            op_id: 405,
6299            flags: super::RESIDENT_SCHEDULE_REGION_INITIALIZE
6300                | super::RESIDENT_SCHEDULE_REGION_FINALIZE,
6301            first_slot: 0,
6302            slot_count: 2,
6303            generation_offset: 0,
6304        };
6305        let error = match provider.prepare_resident_schedule(
6306            relations,
6307            &[],
6308            &[wave],
6309            &[region],
6310            &[],
6311            &[],
6312            &[],
6313        ) {
6314            Err(error) => error,
6315            Ok(_) => panic!("shared runtime allocation reached scheduler allocation"),
6316        };
6317        assert!(error.to_string().contains("aliases storage"));
6318        assert_eq!(output.cached_row_count(), Some(1));
6319    }
6320
6321    #[test]
6322    fn preparation_rejects_cross_slot_overlapping_raw_views() {
6323        let Some(provider) = provider() else { return };
6324        let relation_schema = schema("overlap", &[ScalarType::U32]);
6325        let mut source = buffer(&provider, relation_schema.clone(), &[vec![7]]);
6326        let mut output = buffer(&provider, relation_schema, &[vec![9]]);
6327        let backing = Arc::new(
6328            provider
6329                .memory
6330                .alloc::<u8>(8)
6331                .expect("overlap backing allocation"),
6332        );
6333        let base = backing.device_ptr_value();
6334        let stream = Arc::clone(provider.device().inner().stream());
6335        let dtype = crate::dlpack::DLDataType {
6336            code: crate::dlpack::K_DLUINT,
6337            bits: 8,
6338            lanes: 1,
6339        };
6340        let source_tensor = crate::dlpack::export_slice_managed_tensor(
6341            Arc::clone(&backing),
6342            provider.device().ordinal() as i32,
6343            dtype,
6344            1,
6345            8,
6346        )
6347        .expect("source ownership token");
6348        let output_tensor = crate::dlpack::export_slice_managed_tensor(
6349            Arc::clone(&backing),
6350            provider.device().ordinal() as i32,
6351            dtype,
6352            1,
6353            8,
6354        )
6355        .expect("output ownership token");
6356        stream.synchronize().expect("producer ready");
6357        // SAFETY: each real export token retains the full allocation on this
6358        // context; both byte ranges are in bounds and producer work is complete.
6359        source.columns[0] =
6360            unsafe { CudaColumn::dlpack(base, 4, Arc::clone(&stream), source_tensor) };
6361        output.columns[0] = unsafe { CudaColumn::dlpack(base + 2, 4, stream, output_tensor) };
6362        let retained = Arc::downgrade(&backing);
6363        drop(backing);
6364        assert!(retained.upgrade().is_some());
6365        let relations = vec![
6366            super::ResidentScheduleRelation::source(&source, 1).expect("overlap source"),
6367            super::ResidentScheduleRelation::output(&mut output, 2),
6368        ];
6369        let region = super::ResidentRegionDescriptor {
6370            iteration_limit: 1,
6371            op_id: 406,
6372            flags: super::RESIDENT_SCHEDULE_REGION_INITIALIZE
6373                | super::RESIDENT_SCHEDULE_REGION_FINALIZE,
6374            first_slot: 0,
6375            slot_count: 2,
6376            ..Default::default()
6377        };
6378        let error =
6379            match provider.prepare_resident_schedule(relations, &[], &[], &[region], &[], &[], &[])
6380            {
6381                Err(error) => error,
6382                Ok(_) => panic!("overlapping raw views reached scheduler allocation"),
6383            };
6384        assert!(error.to_string().contains("aliases storage"));
6385        assert_eq!(output.cached_row_count(), Some(1));
6386    }
6387
6388    #[test]
6389    fn output_count_finalization_is_all_or_nothing() {
6390        let Some(provider) = provider() else { return };
6391        let relation_schema = schema("receipt", &[ScalarType::U32]);
6392        let mut first = buffer(&provider, relation_schema.clone(), &[vec![1]]);
6393        let mut second = buffer(&provider, relation_schema, &[vec![2]]);
6394        let mut relations = vec![
6395            super::ResidentScheduleRelation::output(&mut first, 1),
6396            super::ResidentScheduleRelation::output(&mut second, 2),
6397        ];
6398        for relation in &mut relations {
6399            relation.invalidate_output_metadata();
6400        }
6401        let error = super::finalize_schedule_output_counts(&provider, &relations, &[0, 1], &[1, 2])
6402            .expect_err("second count exceeds capacity");
6403        assert!(error.to_string().contains("exceeds buffer capacity"));
6404        drop(relations);
6405        assert_eq!(first.cached_row_count(), None);
6406        assert_eq!(second.cached_row_count(), None);
6407    }
6408
6409    #[test]
6410    fn preparation_rejects_relation_from_foreign_provider() {
6411        let Some(foreign_provider) = provider() else {
6412            return;
6413        };
6414        let Some(provider) = provider() else { return };
6415        let relation_schema = schema("context", &[ScalarType::U32]);
6416        let input = buffer(&foreign_provider, relation_schema.clone(), &[vec![9]]);
6417        let mut output = buffer(&provider, relation_schema, &[vec![0]]);
6418        let relations = vec![
6419            super::ResidentScheduleRelation::source(&input, 1).expect("foreign source"),
6420            super::ResidentScheduleRelation::output(&mut output, 2),
6421        ];
6422        let operation = super::ResidentOpDescriptor {
6423            kind: super::OP_FILTER,
6424            op_id: 403,
6425            out: 1,
6426            in0: 0,
6427            in0_generation: 1,
6428            out_generation: 2,
6429            ..Default::default()
6430        };
6431
6432        let error = match provider.prepare_resident_schedule(
6433            relations,
6434            &[operation],
6435            &[],
6436            &[],
6437            &[],
6438            &[],
6439            &[],
6440        ) {
6441            Err(error) => error,
6442            Ok(_) => panic!("foreign relation reached scheduler allocation"),
6443        };
6444        assert!(error.to_string().contains("foreign"));
6445        assert_eq!(output.cached_row_count(), Some(1));
6446    }
6447
6448    #[test]
6449    fn preparation_rejects_ignored_flags_iteration_limits_and_slot_scopes() {
6450        let Some(provider) = provider() else { return };
6451        let base_wave = super::ResidentWaveDescriptor {
6452            first_op: 0,
6453            op_count: 0,
6454            ..Default::default()
6455        };
6456        let base_region = super::ResidentRegionDescriptor {
6457            first_wave: 0,
6458            wave_count: 1,
6459            iteration_limit: 1,
6460            op_id: 410,
6461            flags: super::RESIDENT_SCHEDULE_REGION_INITIALIZE
6462                | super::RESIDENT_SCHEDULE_REGION_FINALIZE,
6463            ..Default::default()
6464        };
6465        let invalid_wave = super::ResidentWaveDescriptor {
6466            flags: 1,
6467            ..base_wave
6468        };
6469        assert_eq!(
6470            schedule_kernel_error(provider.prepare_resident_schedule(
6471                Vec::new(),
6472                &[],
6473                &[invalid_wave],
6474                &[base_region],
6475                &[],
6476                &[],
6477                &[],
6478            )),
6479            "resident schedule waves must exactly partition operations"
6480        );
6481        let invalid_wave_reserved = super::ResidentWaveDescriptor {
6482            reserved: 1,
6483            ..base_wave
6484        };
6485        assert_eq!(
6486            schedule_kernel_error(provider.prepare_resident_schedule(
6487                Vec::new(),
6488                &[],
6489                &[invalid_wave_reserved],
6490                &[base_region],
6491                &[],
6492                &[],
6493                &[],
6494            )),
6495            "resident schedule waves must exactly partition operations"
6496        );
6497        let invalid_region = super::ResidentRegionDescriptor {
6498            flags: base_region.flags | (1 << 31),
6499            ..base_region
6500        };
6501        assert_eq!(
6502            schedule_kernel_error(provider.prepare_resident_schedule(
6503                Vec::new(),
6504                &[],
6505                &[base_wave],
6506                &[invalid_region],
6507                &[],
6508                &[],
6509                &[],
6510            )),
6511            "resident schedule region range or reserved field is invalid"
6512        );
6513        let invalid_region_reserved = super::ResidentRegionDescriptor {
6514            generation_offset: 1,
6515            ..base_region
6516        };
6517        assert_eq!(
6518            schedule_kernel_error(provider.prepare_resident_schedule(
6519                Vec::new(),
6520                &[],
6521                &[base_wave],
6522                &[invalid_region_reserved],
6523                &[],
6524                &[],
6525                &[],
6526            )),
6527            "resident schedule generation baselines are not contiguous"
6528        );
6529        let invalid_limit = super::ResidentRegionDescriptor {
6530            iteration_limit: 2,
6531            ..base_region
6532        };
6533        assert_eq!(
6534            schedule_kernel_error(provider.prepare_resident_schedule(
6535                Vec::new(),
6536                &[],
6537                &[base_wave],
6538                &[invalid_limit],
6539                &[],
6540                &[],
6541                &[],
6542            )),
6543            "resident schedule region control flags are invalid"
6544        );
6545        let zero_limit = super::ResidentRegionDescriptor {
6546            iteration_limit: 0,
6547            ..base_region
6548        };
6549        assert_eq!(
6550            schedule_kernel_error(provider.prepare_resident_schedule(
6551                Vec::new(),
6552                &[],
6553                &[base_wave],
6554                &[zero_limit],
6555                &[],
6556                &[],
6557                &[],
6558            )),
6559            "resident schedule region control flags are invalid"
6560        );
6561        let mismatched_limits = [
6562            super::ResidentRegionDescriptor {
6563                iteration_limit: 2,
6564                op_id: 420,
6565                flags: super::RESIDENT_SCHEDULE_REGION_INITIALIZE
6566                    | super::RESIDENT_SCHEDULE_REGION_SCC_BEGIN,
6567                ..Default::default()
6568            },
6569            super::ResidentRegionDescriptor {
6570                iteration_limit: 3,
6571                op_id: 420,
6572                flags: super::RESIDENT_SCHEDULE_REGION_RECURSIVE,
6573                ..Default::default()
6574            },
6575            super::ResidentRegionDescriptor {
6576                iteration_limit: 1,
6577                op_id: 421,
6578                flags: super::RESIDENT_SCHEDULE_REGION_FINALIZE,
6579                ..Default::default()
6580            },
6581        ];
6582        assert_eq!(
6583            schedule_kernel_error(provider.prepare_resident_schedule(
6584                Vec::new(),
6585                &[],
6586                &[],
6587                &mismatched_limits,
6588                &[],
6589                &[],
6590                &[],
6591            )),
6592            "resident schedule SCC begin does not match its recursive body"
6593        );
6594
6595        let relation_schema = schema("scope", &[ScalarType::U32]);
6596        let input = buffer(&provider, relation_schema.clone(), &[vec![1]]);
6597        let mut output = buffer(&provider, relation_schema, &[vec![0]]);
6598        let relations = vec![
6599            super::ResidentScheduleRelation::source(&input, 1).expect("scope source"),
6600            super::ResidentScheduleRelation::output(&mut output, 2),
6601        ];
6602        let operation = super::ResidentOpDescriptor {
6603            kind: super::OP_FILTER,
6604            op_id: 411,
6605            out: 1,
6606            in0: 0,
6607            in0_generation: 1,
6608            out_generation: 2,
6609            ..Default::default()
6610        };
6611        let scoped_wave = super::ResidentWaveDescriptor {
6612            op_count: 1,
6613            ..base_wave
6614        };
6615        let too_narrow = super::ResidentRegionDescriptor {
6616            first_slot: 0,
6617            slot_count: 1,
6618            ..base_region
6619        };
6620        assert_eq!(
6621            schedule_kernel_error(provider.prepare_resident_schedule(
6622                relations,
6623                &[operation],
6624                &[scoped_wave],
6625                &[too_narrow],
6626                &[],
6627                &[],
6628                &[],
6629            )),
6630            "resident schedule initialization must cover every relation slot"
6631        );
6632        assert_eq!(output.cached_row_count(), Some(1));
6633
6634        let relations = vec![
6635            super::ResidentScheduleRelation::source(&input, 1).expect("flag source"),
6636            super::ResidentScheduleRelation::output(&mut output, 2),
6637        ];
6638        let invalid_operation_flags = super::ResidentOpDescriptor {
6639            flags: 4,
6640            ..operation
6641        };
6642        assert_eq!(
6643            schedule_kernel_error(provider.prepare_resident_schedule(
6644                relations,
6645                &[invalid_operation_flags],
6646                &[scoped_wave],
6647                &[super::ResidentRegionDescriptor {
6648                    first_slot: 0,
6649                    slot_count: 2,
6650                    ..base_region
6651                }],
6652                &[],
6653                &[],
6654                &[],
6655            )),
6656            "resident schedule operation 411 has an unsupported kind, flag, or payload"
6657        );
6658        assert_eq!(output.cached_row_count(), Some(1));
6659
6660        let relations = vec![
6661            super::ResidentScheduleRelation::source(&input, 1).expect("reserved source"),
6662            super::ResidentScheduleRelation::output(&mut output, 2),
6663        ];
6664        let invalid_operation_reserved = super::ResidentOpDescriptor {
6665            reserved: 1,
6666            ..operation
6667        };
6668        assert_eq!(
6669            schedule_kernel_error(provider.prepare_resident_schedule(
6670                relations,
6671                &[invalid_operation_reserved],
6672                &[scoped_wave],
6673                &[super::ResidentRegionDescriptor {
6674                    first_slot: 0,
6675                    slot_count: 2,
6676                    ..base_region
6677                }],
6678                &[],
6679                &[],
6680                &[],
6681            )),
6682            "resident schedule operation 411 has an unsupported kind, flag, or payload"
6683        );
6684        assert_eq!(output.cached_row_count(), Some(1));
6685
6686        let relations = vec![
6687            super::ResidentScheduleRelation::source(&input, 1).expect("overflowing scope source"),
6688            super::ResidentScheduleRelation::output(&mut output, 2),
6689        ];
6690        let overflowing_scope = super::ResidentRegionDescriptor {
6691            first_slot: u32::MAX,
6692            slot_count: 2,
6693            ..base_region
6694        };
6695        assert_eq!(
6696            schedule_kernel_error(provider.prepare_resident_schedule(
6697                relations,
6698                &[operation],
6699                &[scoped_wave],
6700                &[overflowing_scope],
6701                &[],
6702                &[],
6703                &[],
6704            )),
6705            "resident schedule generation baseline slot scope is invalid"
6706        );
6707        assert_eq!(output.cached_row_count(), Some(1));
6708    }
6709
6710    #[test]
6711    fn preparation_accepts_explicit_multihead_recursive_novelty_contract() {
6712        let Some(provider) = provider() else { return };
6713        let relation_schema = schema("recursive", &[ScalarType::U32]);
6714        let changed = buffer(&provider, relation_schema.clone(), &[vec![1]]);
6715        let empty = buffer(&provider, relation_schema.clone(), &[Vec::new()]);
6716        let stable_left = buffer(&provider, relation_schema.clone(), &[vec![7]]);
6717        let stable_right = buffer(&provider, relation_schema.clone(), &[vec![7]]);
6718        let mut first_novel = provider
6719            .prepare_resident_relation(relation_schema.clone(), 1)
6720            .expect("first novelty output")
6721            .into_buffer();
6722        let mut second_novel = provider
6723            .prepare_resident_relation(relation_schema, 1)
6724            .expect("second novelty output")
6725            .into_buffer();
6726        let relations = vec![
6727            super::ResidentScheduleRelation::source(&changed, 1).expect("changed source"),
6728            super::ResidentScheduleRelation::source(&empty, 2).expect("empty source"),
6729            super::ResidentScheduleRelation::source(&stable_left, 3).expect("stable source"),
6730            super::ResidentScheduleRelation::source(&stable_right, 4).expect("stable source"),
6731            super::ResidentScheduleRelation::output(&mut first_novel, 5),
6732            super::ResidentScheduleRelation::output(&mut second_novel, 6),
6733        ];
6734        let operations = [
6735            super::ResidentOpDescriptor {
6736                kind: super::OP_DIFF,
6737                flags: super::RESIDENT_SCHEDULE_OP_MARK_NOVELTY,
6738                op_id: 501,
6739                out: 4,
6740                in0: 0,
6741                in1: 1,
6742                in0_generation: 1,
6743                in1_generation: 2,
6744                out_generation: 5,
6745                ..Default::default()
6746            },
6747            super::ResidentOpDescriptor {
6748                kind: super::OP_DIFF,
6749                flags: super::RESIDENT_SCHEDULE_OP_MARK_NOVELTY,
6750                op_id: 502,
6751                out: 5,
6752                in0: 2,
6753                in1: 3,
6754                in0_generation: 3,
6755                in1_generation: 4,
6756                out_generation: 6,
6757                ..Default::default()
6758            },
6759        ];
6760        let wave = super::ResidentWaveDescriptor {
6761            first_op: 0,
6762            op_count: 2,
6763            ..Default::default()
6764        };
6765        let regions = [
6766            super::ResidentRegionDescriptor {
6767                first_wave: 0,
6768                wave_count: 0,
6769                iteration_limit: 1,
6770                op_id: 500,
6771                flags: super::RESIDENT_SCHEDULE_REGION_INITIALIZE
6772                    | super::RESIDENT_SCHEDULE_REGION_SCC_BEGIN,
6773                first_slot: 0,
6774                slot_count: 6,
6775                generation_offset: 0,
6776            },
6777            super::ResidentRegionDescriptor {
6778                first_wave: 0,
6779                wave_count: 1,
6780                iteration_limit: 1,
6781                op_id: 500,
6782                flags: super::RESIDENT_SCHEDULE_REGION_RECURSIVE,
6783                first_slot: 0,
6784                slot_count: 6,
6785                generation_offset: 0,
6786            },
6787            super::ResidentRegionDescriptor {
6788                first_wave: 1,
6789                wave_count: 0,
6790                iteration_limit: 1,
6791                op_id: 503,
6792                flags: super::RESIDENT_SCHEDULE_REGION_FINALIZE,
6793                first_slot: 0,
6794                slot_count: 6,
6795                generation_offset: 0,
6796            },
6797        ];
6798
6799        let schedule = provider
6800            .prepare_resident_schedule(relations, &operations, &[wave], &regions, &[], &[], &[4, 5])
6801            .expect("explicit recursive schedule contract");
6802        let stream = provider
6803            .device()
6804            .inner()
6805            .stream()
6806            .fork()
6807            .expect("recursive schedule stream");
6808        let mut graph = provider
6809            .capture_resident_schedule(schedule, 0, Arc::clone(&stream))
6810            .expect("capture recursive schedule");
6811        let nodes = graph.nodes().expect("recursive parent inventory");
6812        assert_eq!(nodes.len(), 3);
6813        assert_eq!(nodes[0].kind, CudaGraphNodeKind::Kernel);
6814        assert_eq!(nodes[1].kind, CudaGraphNodeKind::Conditional);
6815        assert_eq!(nodes[2].kind, CudaGraphNodeKind::Kernel);
6816        graph.launch().expect("launch recursive schedule");
6817        let receipt = graph
6818            .synchronize_and_observe()
6819            .expect("recursive schedule receipt");
6820        assert_eq!(
6821            receipt.status.code,
6822            ResidentTerminalCode::IterationLimit as u32
6823        );
6824        assert_eq!(receipt.status.op_id, 500);
6825        assert_eq!(receipt.status.iterations, 1);
6826        assert_eq!(receipt.status.limit, 1);
6827        assert_eq!(receipt.changed, 1);
6828        assert_eq!(receipt.counts, vec![0, 0]);
6829    }
6830
6831    #[test]
6832    fn real_cuda_recursive_zero_convergence_and_iteration_limit_are_exact() {
6833        let Some(provider) = provider() else { return };
6834        let expected_inventory = vec![
6835            CudaGraphNodeKind::Kernel,
6836            CudaGraphNodeKind::Conditional,
6837            CudaGraphNodeKind::Kernel,
6838        ];
6839
6840        let (zero_limit, zero_limit_nodes) = run_single_recursive_diff(&provider, &[1], &[], 0);
6841        assert_eq!(zero_limit_nodes, expected_inventory);
6842        assert_eq!(
6843            zero_limit.status.code,
6844            ResidentTerminalCode::IterationLimit as u32
6845        );
6846        assert_eq!(zero_limit.status.op_id, 600);
6847        assert_eq!(zero_limit.status.iterations, 0);
6848        assert_eq!(zero_limit.status.limit, 0);
6849        assert_eq!(zero_limit.changed, 0);
6850        assert_eq!(zero_limit.counts, vec![0]);
6851
6852        let (converged, converged_nodes) = run_single_recursive_diff(&provider, &[7], &[7], 3);
6853        assert_eq!(converged_nodes, expected_inventory);
6854        assert_eq!(converged.status.code, ResidentTerminalCode::Success as u32);
6855        assert_eq!(converged.status.op_id, 602);
6856        assert_eq!(converged.status.iterations, 1);
6857        assert_eq!(converged.status.limit, 0);
6858        assert_eq!(converged.changed, 0);
6859        assert_eq!(converged.counts, vec![0]);
6860
6861        let (limited, limited_nodes) = run_single_recursive_diff(&provider, &[9], &[], 3);
6862        assert_eq!(limited_nodes, expected_inventory);
6863        assert_eq!(
6864            limited.status.code,
6865            ResidentTerminalCode::IterationLimit as u32
6866        );
6867        assert_eq!(limited.status.op_id, 600);
6868        assert_eq!(limited.status.iterations, 3);
6869        assert_eq!(limited.status.limit, 3);
6870        assert_eq!(limited.changed, 1);
6871        assert_eq!(limited.counts, vec![0]);
6872    }
6873
6874    #[test]
6875    fn real_cuda_two_serial_sccs_preserve_sticky_status_and_aggregate_iterations() {
6876        let Some(provider) = provider() else { return };
6877        let expected_inventory = vec![
6878            CudaGraphNodeKind::Kernel,
6879            CudaGraphNodeKind::Conditional,
6880            CudaGraphNodeKind::Kernel,
6881            CudaGraphNodeKind::Conditional,
6882            CudaGraphNodeKind::Kernel,
6883        ];
6884
6885        let (success, success_nodes, _) = run_two_scc_diff(&provider, 4, 4, false, false);
6886        assert_eq!(success_nodes, expected_inventory);
6887        assert_eq!(success.status.code, ResidentTerminalCode::Success as u32);
6888        assert_eq!(success.status.op_id, 703);
6889        assert_eq!(success.status.iterations, 2);
6890        assert_eq!(success.status.limit, 0);
6891        assert_eq!(success.counts, vec![0, 0]);
6892
6893        let (first_zero, first_zero_nodes, first_zero_storage) =
6894            run_two_scc_diff(&provider, 0, 4, true, true);
6895        assert_eq!(first_zero_nodes, expected_inventory);
6896        assert_eq!(
6897            first_zero.status.code,
6898            ResidentTerminalCode::IterationLimit as u32
6899        );
6900        assert_eq!(first_zero.status.op_id, 701);
6901        assert_eq!(first_zero.status.iterations, 0);
6902        assert_eq!(first_zero.status.limit, 0);
6903        assert_eq!(first_zero.counts, vec![0, 0]);
6904        assert_eq!(first_zero_storage, [0x1111_1111, 0x2222_2222]);
6905
6906        let (second_zero, second_zero_nodes, second_zero_storage) =
6907            run_two_scc_diff(&provider, 4, 0, false, true);
6908        assert_eq!(second_zero_nodes, expected_inventory);
6909        assert_eq!(
6910            second_zero.status.code,
6911            ResidentTerminalCode::IterationLimit as u32
6912        );
6913        assert_eq!(second_zero.status.op_id, 702);
6914        assert_eq!(second_zero.status.iterations, 1);
6915        assert_eq!(second_zero.status.limit, 0);
6916        assert_eq!(second_zero.counts, vec![0, 0]);
6917        assert_eq!(second_zero_storage, [0x1111_1111, 0x2222_2222]);
6918    }
6919
6920    #[test]
6921    fn real_cuda_recursive_overflow_is_sticky_and_stops_downstream_writes() {
6922        let Some(provider) = provider() else { return };
6923        let relation_schema = schema("recursive_overflow", &[ScalarType::U32]);
6924        let left = buffer(&provider, relation_schema.clone(), &[vec![1, 2]]);
6925        let right = buffer(&provider, relation_schema.clone(), &[Vec::new()]);
6926        let mut novelty = buffer(&provider, relation_schema.clone(), &[vec![0xaaaa_aaaa]]);
6927        let mut downstream = buffer(&provider, relation_schema, &[vec![0xbbbb_bbbb]]);
6928        let relations = vec![
6929            super::ResidentScheduleRelation::source(&left, 1).expect("left source"),
6930            super::ResidentScheduleRelation::source(&right, 2).expect("right source"),
6931            super::ResidentScheduleRelation::output(&mut novelty, 3),
6932            super::ResidentScheduleRelation::output(&mut downstream, 4),
6933        ];
6934        let operations = [
6935            super::ResidentOpDescriptor {
6936                kind: super::OP_DIFF,
6937                flags: super::RESIDENT_SCHEDULE_OP_MARK_NOVELTY,
6938                op_id: 731,
6939                out: 2,
6940                in0: 0,
6941                in1: 1,
6942                in0_generation: 1,
6943                in1_generation: 2,
6944                out_generation: 3,
6945                ..Default::default()
6946            },
6947            super::ResidentOpDescriptor {
6948                kind: super::OP_PROJECT,
6949                op_id: 732,
6950                out: 3,
6951                in0: 2,
6952                in0_generation: 3,
6953                out_generation: 4,
6954                aux_count: 1,
6955                ..Default::default()
6956            },
6957        ];
6958        let expression = super::ResidentProjectExpressionDescriptor::column(0, 4);
6959        let wave = super::ResidentWaveDescriptor {
6960            first_op: 0,
6961            op_count: 2,
6962            ..Default::default()
6963        };
6964        let regions = [
6965            super::ResidentRegionDescriptor {
6966                first_wave: 0,
6967                wave_count: 0,
6968                iteration_limit: 4,
6969                op_id: 730,
6970                flags: super::RESIDENT_SCHEDULE_REGION_INITIALIZE
6971                    | super::RESIDENT_SCHEDULE_REGION_SCC_BEGIN,
6972                first_slot: 0,
6973                slot_count: 4,
6974                generation_offset: 0,
6975            },
6976            super::ResidentRegionDescriptor {
6977                first_wave: 0,
6978                wave_count: 1,
6979                iteration_limit: 4,
6980                op_id: 730,
6981                flags: super::RESIDENT_SCHEDULE_REGION_RECURSIVE,
6982                first_slot: 0,
6983                slot_count: 4,
6984                generation_offset: 0,
6985            },
6986            super::ResidentRegionDescriptor {
6987                first_wave: 1,
6988                wave_count: 0,
6989                iteration_limit: 1,
6990                op_id: 733,
6991                flags: super::RESIDENT_SCHEDULE_REGION_FINALIZE,
6992                first_slot: 0,
6993                slot_count: 4,
6994                generation_offset: 0,
6995            },
6996        ];
6997        let schedule = provider
6998            .prepare_resident_schedule(
6999                relations,
7000                &operations,
7001                &[wave],
7002                &regions,
7003                &[],
7004                &[expression],
7005                &[2, 3],
7006            )
7007            .expect("prepare recursive overflow schedule");
7008        let stream = provider
7009            .device()
7010            .inner()
7011            .stream()
7012            .fork()
7013            .expect("recursive overflow stream");
7014        let mut graph = provider
7015            .capture_resident_schedule(schedule, 0, Arc::clone(&stream))
7016            .expect("capture recursive overflow schedule");
7017        graph.launch().expect("launch recursive overflow schedule");
7018        let receipt = graph
7019            .synchronize_and_observe()
7020            .expect("recursive overflow receipt");
7021        assert_eq!(
7022            receipt.status.code,
7023            ResidentTerminalCode::CapacityOverflow as u32
7024        );
7025        assert_eq!(receipt.status.op_id, 731);
7026        assert_eq!(receipt.status.iterations, 0);
7027        assert_eq!(receipt.status.limit, 4);
7028        assert_eq!(receipt.status.required, 2);
7029        assert_eq!(receipt.status.capacity, 1);
7030        assert_eq!(receipt.changed, 0);
7031        assert_eq!(receipt.counts, vec![0, 0]);
7032        for (slot, expected) in [(2_usize, 0xaaaa_aaaa_u32), (3, 0xbbbb_bbbb)] {
7033            let raw: Vec<u8> = provider
7034                .device()
7035                .inner()
7036                .dtoh_sync_copy(
7037                    graph
7038                        .relation(slot)
7039                        .expect("recursive output")
7040                        .column(0)
7041                        .expect("recursive output column"),
7042                )
7043                .expect("recursive output storage");
7044            assert_eq!(&raw[..4], &expected.to_le_bytes());
7045        }
7046    }
7047
7048    #[test]
7049    fn capture_rejects_stream_from_independent_device_context_owner() {
7050        let Some(provider) = provider() else { return };
7051        let foreign_device = crate::CudaDevice::new(0).expect("independent CUDA device owner");
7052        assert!(!Arc::ptr_eq(
7053            foreign_device.inner().stream().context(),
7054            provider.device().inner().stream().context(),
7055        ));
7056        let wave = super::ResidentWaveDescriptor {
7057            first_op: 0,
7058            op_count: 0,
7059            ..Default::default()
7060        };
7061        let region = super::ResidentRegionDescriptor {
7062            first_wave: 0,
7063            wave_count: 1,
7064            iteration_limit: 1,
7065            op_id: 420,
7066            flags: super::RESIDENT_SCHEDULE_REGION_INITIALIZE
7067                | super::RESIDENT_SCHEDULE_REGION_FINALIZE,
7068            ..Default::default()
7069        };
7070        let schedule = provider
7071            .prepare_resident_schedule(Vec::new(), &[], &[wave], &[region], &[], &[], &[])
7072            .expect("empty local schedule");
7073        let foreign_stream = foreign_device
7074            .inner()
7075            .stream()
7076            .fork()
7077            .expect("independent context-owner stream");
7078
7079        let error = match provider.capture_resident_schedule(schedule, 0, foreign_stream) {
7080            Err(error) => error,
7081            Ok(_) => panic!("independent context-owner stream captured a local schedule"),
7082        };
7083        assert!(error.to_string().contains("foreign CUDA context"));
7084    }
7085
7086    #[test]
7087    fn real_cuda_selected_stream_cooperative_capture_has_one_kernel_node() {
7088        let Some(provider) = provider() else { return };
7089        let wave = super::ResidentWaveDescriptor {
7090            first_op: 0,
7091            op_count: 0,
7092            flags: 0,
7093            reserved: 0,
7094        };
7095        let region = super::ResidentRegionDescriptor {
7096            first_wave: 0,
7097            wave_count: 1,
7098            iteration_limit: 1,
7099            op_id: 91,
7100            flags: super::RESIDENT_SCHEDULE_REGION_INITIALIZE
7101                | super::RESIDENT_SCHEDULE_REGION_FINALIZE,
7102            first_slot: 0,
7103            slot_count: 0,
7104            generation_offset: 0,
7105        };
7106        let schedule = provider
7107            .prepare_resident_schedule(Vec::new(), &[], &[wave], &[region], &[], &[], &[])
7108            .expect("prepare empty resident schedule");
7109        let stream = provider
7110            .device()
7111            .inner()
7112            .stream()
7113            .fork()
7114            .expect("non-default stream");
7115        assert_ne!(
7116            stream.cu_stream(),
7117            provider.device().inner().stream().cu_stream(),
7118            "feasibility gate must capture on a selected non-default stream"
7119        );
7120
7121        let mut graph = provider
7122            .capture_resident_schedule(schedule, 0, Arc::clone(&stream))
7123            .expect("capture cooperative resident schedule");
7124        assert_eq!(graph.node_count().expect("node count"), 1);
7125        let nodes = graph.nodes().expect("node inventory");
7126        assert_eq!(nodes.len(), 1);
7127        assert_eq!(nodes[0].kind, CudaGraphNodeKind::Kernel);
7128
7129        graph.launch().expect("launch resident schedule");
7130        let receipt = graph
7131            .synchronize_and_observe()
7132            .expect("resident schedule receipt");
7133        assert_eq!(receipt.status.code, ResidentTerminalCode::Success as u32);
7134        assert_eq!(receipt.status.op_id, 91);
7135    }
7136
7137    #[test]
7138    fn real_cuda_graph_lease_rejects_overlap_allows_replay_and_synchronizes_drop() {
7139        let Some(provider) = provider() else { return };
7140        let relation_schema = schema("graph_lease", &[ScalarType::U32]);
7141        let input = buffer(&provider, relation_schema.clone(), &[vec![1, 2]]);
7142        let mut output = buffer(&provider, relation_schema.clone(), &[vec![0, 0]]);
7143        let schedule = passthrough_schedule(&provider, &input, &mut output, 901);
7144        let stream = provider
7145            .device()
7146            .inner()
7147            .stream()
7148            .fork()
7149            .expect("graph lease stream");
7150        let mut graph = provider
7151            .capture_resident_schedule(schedule, 0, Arc::clone(&stream))
7152            .expect("capture graph lease schedule");
7153
7154        assert_eq!(
7155            graph
7156                .relation(1)
7157                .expect("leased output before launch")
7158                .cached_row_count(),
7159            None
7160        );
7161        match graph.synchronize_and_observe() {
7162            Err(XlogError::Kernel(message)) => assert_eq!(
7163                message,
7164                "resident schedule has no in-flight launch to observe"
7165            ),
7166            Err(error) => panic!("unexpected pre-launch observation error: {error}"),
7167            Ok(_) => panic!("pre-launch observation unexpectedly succeeded"),
7168        }
7169
7170        graph.launch().expect("first graph lease launch");
7171        match graph.relation(1) {
7172            Err(XlogError::Kernel(message)) => assert_eq!(
7173                message,
7174                "resident schedule relation is unavailable while launch is in flight"
7175            ),
7176            Err(error) => panic!("unexpected in-flight relation error: {error}"),
7177            Ok(_) => panic!("in-flight relation access unexpectedly succeeded"),
7178        }
7179        match graph.launch() {
7180            Err(XlogError::Kernel(message)) => {
7181                assert_eq!(message, "resident schedule launch is already in flight")
7182            }
7183            Err(error) => panic!("unexpected overlapping launch error: {error}"),
7184            Ok(()) => panic!("overlapping graph launch unexpectedly succeeded"),
7185        }
7186        let first = graph
7187            .synchronize_and_observe()
7188            .expect("first graph lease receipt");
7189        assert_eq!(first.status.code, ResidentTerminalCode::Success as u32);
7190        assert_eq!(first.status.op_id, 902);
7191        assert_eq!(first.counts, vec![2]);
7192        assert_eq!(
7193            normalized_rows(&provider, graph.relation(1).expect("first replay output")),
7194            vec![vec![1], vec![2]]
7195        );
7196        match graph.synchronize_and_observe() {
7197            Err(XlogError::Kernel(message)) => assert_eq!(
7198                message,
7199                "resident schedule has no in-flight launch to observe"
7200            ),
7201            Err(error) => panic!("unexpected duplicate observation error: {error}"),
7202            Ok(_) => panic!("duplicate observation unexpectedly succeeded"),
7203        }
7204
7205        graph.launch().expect("replayed graph lease launch");
7206        let replay = graph
7207            .synchronize_and_observe()
7208            .expect("replayed graph lease receipt");
7209        assert_eq!(replay, first);
7210        drop(graph);
7211        assert_eq!(output.cached_row_count(), Some(2));
7212        assert!(!output.canonical_full_row_set_certified());
7213        assert_eq!(normalized_rows(&provider, &output), vec![vec![1], vec![2]]);
7214
7215        let mut dropped_output = buffer(&provider, relation_schema, &[vec![0, 0]]);
7216        let dropped_schedule = passthrough_schedule(&provider, &input, &mut dropped_output, 911);
7217        let dropped_stream = provider
7218            .device()
7219            .inner()
7220            .stream()
7221            .fork()
7222            .expect("drop synchronization stream");
7223        let mut dropped_graph = provider
7224            .capture_resident_schedule(dropped_schedule, 0, dropped_stream)
7225            .expect("capture drop synchronization schedule");
7226        dropped_graph
7227            .launch()
7228            .expect("launch drop synchronization schedule");
7229        drop(dropped_graph);
7230        assert_eq!(dropped_output.cached_row_count(), None);
7231        assert!(!dropped_output.canonical_full_row_set_certified());
7232        assert_eq!(
7233            normalized_rows(&provider, &dropped_output),
7234            vec![vec![1], vec![2]]
7235        );
7236    }
7237
7238    #[test]
7239    fn capture_rejects_sibling_provider_on_the_same_cuda_context() {
7240        let Some(provider) = provider() else { return };
7241        let relation_schema = schema("provider_identity", &[ScalarType::U32]);
7242        let input = buffer(&provider, relation_schema.clone(), &[vec![1]]);
7243        let mut output = buffer(&provider, relation_schema, &[vec![0]]);
7244        let schedule = passthrough_schedule(&provider, &input, &mut output, 921);
7245        let sibling_memory = Arc::new(GpuMemoryManager::new(
7246            Arc::clone(provider.device()),
7247            MemoryBudget::with_limit(512 * 1024 * 1024),
7248        ));
7249        let sibling = CudaKernelProvider::from_loaded_device(
7250            Arc::clone(provider.device()),
7251            sibling_memory,
7252            None,
7253        );
7254        let stream = provider
7255            .device()
7256            .inner()
7257            .stream()
7258            .fork()
7259            .expect("same-context identity stream");
7260
7261        match sibling.capture_resident_schedule(schedule, 0, stream) {
7262            Err(XlogError::Kernel(message)) => assert_eq!(
7263                message,
7264                "resident schedule belongs to a different CUDA kernel provider"
7265            ),
7266            Err(error) => panic!("unexpected provider identity error: {error}"),
7267            Ok(_) => panic!("sibling provider captured a foreign resident schedule"),
7268        }
7269        assert_eq!(output.cached_row_count(), None);
7270    }
7271
7272    #[test]
7273    fn real_cuda_schedule_receipt_uses_one_pinned_final_dtoh_per_observation() {
7274        let Some(provider) = provider() else { return };
7275        let relation_schema = schema("receipt_accounting", &[ScalarType::U32]);
7276        let input = buffer(&provider, relation_schema.clone(), &[vec![1, 2]]);
7277        let mut output = buffer(&provider, relation_schema, &[vec![0, 0]]);
7278        let schedule = passthrough_schedule(&provider, &input, &mut output, 931);
7279        let expected_bytes =
7280            size_of::<crate::provider::resident_relational::ResidentTerminalStatus>()
7281                + 2 * size_of::<u32>();
7282        let stream = provider
7283            .device()
7284            .inner()
7285            .stream()
7286            .fork()
7287            .expect("receipt accounting stream");
7288        let mut graph = provider
7289            .capture_resident_schedule(schedule, 0, stream)
7290            .expect("capture receipt accounting schedule");
7291        provider.reset_host_transfer_stats();
7292        provider.reset_untracked_metadata_dtoh_count();
7293        provider.reset_final_observation_transfer_stats();
7294
7295        graph.launch().expect("launch receipt accounting schedule");
7296        assert_eq!(provider.host_transfer_stats().dtoh_calls, 0);
7297        assert_eq!(provider.untracked_metadata_dtoh_count(), 0);
7298        assert_eq!(provider.final_observation_transfer_stats().dtoh_calls, 0);
7299        graph
7300            .synchronize_and_observe()
7301            .expect("first receipt accounting observation");
7302        assert_eq!(provider.host_transfer_stats().dtoh_calls, 0);
7303        assert_eq!(provider.untracked_metadata_dtoh_count(), 0);
7304        let first = provider.final_observation_transfer_stats();
7305        assert_eq!(first.dtoh_calls, 1);
7306        assert_eq!(first.dtoh_bytes, expected_bytes as u64);
7307        assert_eq!(first.pinned_receipts, 1);
7308
7309        graph.launch().expect("replay receipt accounting schedule");
7310        graph
7311            .synchronize_and_observe()
7312            .expect("replay receipt accounting observation");
7313        assert_eq!(provider.host_transfer_stats().dtoh_calls, 0);
7314        assert_eq!(provider.untracked_metadata_dtoh_count(), 0);
7315        let replay = provider.final_observation_transfer_stats();
7316        assert_eq!(replay.dtoh_calls, 2);
7317        assert_eq!(replay.dtoh_bytes, 2 * expected_bytes as u64);
7318        assert_eq!(replay.pinned_receipts, 2);
7319    }
7320
7321    #[test]
7322    fn real_cuda_compact_union_orders_non_power_of_two_rows_across_merge_tiles() {
7323        let Some(provider) = provider() else { return };
7324        let relation_schema = schema("ordered_union", &[ScalarType::U32]);
7325        let mut left: Vec<u64> = (0..1_537).rev().collect();
7326        left.extend([0, 512, 1_536]);
7327        let mut right: Vec<u64> = (768..2_305).rev().collect();
7328        right.extend([768, 1_536, 2_304]);
7329        let (receipt, rows) = compact_set_rows(
7330            &provider,
7331            relation_schema,
7332            &[left],
7333            &[right],
7334            super::OP_UNION,
7335            2_305,
7336        );
7337        assert_eq!(receipt.status.code, ResidentTerminalCode::Success as u32);
7338        assert_eq!(receipt.counts, vec![2_305]);
7339        assert_eq!(
7340            rows,
7341            (0..2_305).map(|value| vec![value]).collect::<Vec<_>>()
7342        );
7343    }
7344
7345    #[test]
7346    fn real_cuda_compact_diff_orders_high_u64_values_across_merge_tiles() {
7347        let Some(provider) = provider() else { return };
7348        let relation_schema = schema("ordered_diff", &[ScalarType::U64]);
7349        let base = 1_u64 << 40;
7350        let mut left: Vec<u64> = (0..4_093).rev().map(|value| base + value).collect();
7351        left.extend([base, base + 2_047, base + 4_092]);
7352        let mut right: Vec<u64> = (0..4_093)
7353            .rev()
7354            .filter(|value| value % 3 == 0)
7355            .map(|value| base + value)
7356            .collect();
7357        right.extend([base, base + 3, base + 4_092]);
7358        let expected: Vec<Vec<u64>> = (0..4_093)
7359            .filter(|value| value % 3 != 0)
7360            .map(|value| vec![base + value])
7361            .collect();
7362        let (receipt, rows) = compact_set_rows(
7363            &provider,
7364            relation_schema,
7365            &[left],
7366            &[right],
7367            super::OP_DIFF,
7368            expected.len() as u64,
7369        );
7370        assert_eq!(receipt.status.code, ResidentTerminalCode::Success as u32);
7371        assert_eq!(receipt.counts, vec![expected.len() as u32]);
7372        assert_eq!(rows, expected);
7373    }
7374
7375    #[test]
7376    fn real_cuda_compact_zero_arity_set_truth_table() {
7377        let Some(provider) = provider() else { return };
7378        for (left, right, union_count, diff_count) in [
7379            (false, false, 0, 0),
7380            (false, true, 1, 0),
7381            (true, false, 1, 1),
7382            (true, true, 1, 0),
7383        ] {
7384            assert_eq!(
7385                compact_nullary_set_count(&provider, left, right, super::OP_UNION),
7386                union_count
7387            );
7388            assert_eq!(
7389                compact_nullary_set_count(&provider, left, right, super::OP_DIFF),
7390                diff_count
7391            );
7392        }
7393    }
7394
7395    #[test]
7396    fn real_cuda_compact_set_max_workspace_is_canonical_and_bounded() {
7397        let Some(provider) = provider() else { return };
7398        let relation_schema = schema("max_ordered_union", &[ScalarType::U32]);
7399        let left_values: Vec<u64> = (0..65_536).rev().collect();
7400        let right_values: Vec<u64> = (0..65_536).map(|index| (index * 40_009) % 65_536).collect();
7401        let left = buffer(&provider, relation_schema.clone(), &[left_values]);
7402        let right = buffer(&provider, relation_schema.clone(), &[right_values]);
7403        let mut output = provider
7404            .prepare_resident_relation(relation_schema, 65_536)
7405            .expect("maximum compact set output")
7406            .into_buffer();
7407        let relations = vec![
7408            super::ResidentScheduleRelation::source(&left, 1).expect("maximum left"),
7409            super::ResidentScheduleRelation::source(&right, 2).expect("maximum right"),
7410            super::ResidentScheduleRelation::output(&mut output, 3),
7411        ];
7412        let operation = super::ResidentOpDescriptor {
7413            kind: super::OP_UNION,
7414            op_id: 982,
7415            out: 2,
7416            in0: 0,
7417            in1: 1,
7418            in0_generation: 1,
7419            in1_generation: 2,
7420            out_generation: 3,
7421            ..Default::default()
7422        };
7423        let wave = super::ResidentWaveDescriptor {
7424            op_count: 1,
7425            ..Default::default()
7426        };
7427        let region = super::ResidentRegionDescriptor {
7428            wave_count: 1,
7429            iteration_limit: 1,
7430            op_id: 983,
7431            flags: super::RESIDENT_SCHEDULE_REGION_INITIALIZE
7432                | super::RESIDENT_SCHEDULE_REGION_FINALIZE,
7433            slot_count: 3,
7434            ..Default::default()
7435        };
7436        let schedule = provider
7437            .prepare_resident_schedule(relations, &[operation], &[wave], &[region], &[], &[], &[2])
7438            .expect("prepare maximum compact set schedule");
7439        let stream = provider
7440            .device()
7441            .inner()
7442            .stream()
7443            .fork()
7444            .expect("maximum compact set stream");
7445        let mut graph = provider
7446            .capture_resident_schedule(schedule, 0, Arc::clone(&stream))
7447            .expect("capture maximum compact set schedule");
7448
7449        for _ in 0..20 {
7450            graph.launch().expect("maximum compact set warmup launch");
7451            let receipt = graph
7452                .synchronize_and_observe()
7453                .expect("maximum compact set warmup receipt");
7454            assert_eq!(receipt.status.code, ResidentTerminalCode::Success as u32);
7455        }
7456        provider.reset_host_transfer_stats();
7457        provider.reset_d2h_transfer_count();
7458        provider.reset_untracked_metadata_dtoh_count();
7459        let mut durations = Vec::with_capacity(100);
7460        for _ in 0..100 {
7461            let started = Instant::now();
7462            graph.launch().expect("maximum compact set measured launch");
7463            let receipt = graph
7464                .synchronize_and_observe()
7465                .expect("maximum compact set measured receipt");
7466            durations.push(started.elapsed());
7467            assert_eq!(receipt.status.code, ResidentTerminalCode::Success as u32);
7468            assert_eq!(receipt.counts, vec![65_536]);
7469        }
7470        durations.sort_unstable();
7471        let median: Duration = durations[durations.len() / 2];
7472        let p95: Duration = durations[durations.len() * 95 / 100];
7473        eprintln!(
7474            "maximum compact set launch median_us={} p95_us={}",
7475            median.as_micros(),
7476            p95.as_micros()
7477        );
7478        let transfers = provider.host_transfer_stats();
7479        assert_eq!(transfers.htod_calls, 0);
7480        assert_eq!(transfers.htod_bytes, 0);
7481        assert_eq!(transfers.dtoh_calls, 0);
7482        assert_eq!(transfers.dtoh_bytes, 0);
7483        assert_eq!(provider.d2h_transfer_count(), 0);
7484        assert_eq!(provider.untracked_metadata_dtoh_count(), 0);
7485
7486        let ordered = rows_in_device_order(
7487            &provider,
7488            graph.relation(2).expect("maximum compact set relation"),
7489        );
7490        assert_eq!(ordered.len(), 65_536);
7491        assert!(ordered
7492            .iter()
7493            .enumerate()
7494            .all(|(index, row)| row == &[index as u64]));
7495    }
7496
7497    #[test]
7498    fn real_cuda_compact_schedule_matches_primitive_chain_at_arity_seventeen() {
7499        let Some(provider) = provider() else { return };
7500        let left_types = [
7501            ScalarType::Symbol,
7502            ScalarType::U32,
7503            ScalarType::U64,
7504            ScalarType::U32,
7505            ScalarType::U64,
7506            ScalarType::U32,
7507            ScalarType::U64,
7508            ScalarType::U32,
7509            ScalarType::U64,
7510        ];
7511        let projected_types = &left_types[..8];
7512        let right_types = left_types;
7513        let left_columns = vec![
7514            vec![5, 2, 5, 4],
7515            vec![9, 7, 11, 12],
7516            vec![100, 200, 300, 400],
7517            vec![13, 23, 33, 43],
7518            vec![1_000, 2_000, 3_000, 4_000],
7519            vec![15, 25, 35, 45],
7520            vec![6_000, 7_000, 8_000, 9_000],
7521            vec![17, 27, 37, 47],
7522            vec![10_000, 11_000, 12_000, 13_000],
7523        ];
7524        let right_columns = vec![
7525            vec![5, 5, 8],
7526            vec![50, 60, 80],
7527            vec![500, 600, 800],
7528            vec![53, 63, 83],
7529            vec![5_000, 6_000, 8_000],
7530            vec![55, 65, 85],
7531            vec![6_000, 7_000, 9_000],
7532            vec![57, 67, 87],
7533            vec![7_000, 8_000, 10_000],
7534        ];
7535        let left = buffer(&provider, schema("left", &left_types), &left_columns);
7536        let right = buffer(&provider, schema("right", &right_types), &right_columns);
7537        let projected_schema = schema("projected", projected_types);
7538        let mut joined_columns = projected_schema.columns.clone();
7539        joined_columns.extend(right.schema().columns.iter().cloned());
7540        let joined_schema = Schema::new(joined_columns);
7541        assert_eq!(joined_schema.arity(), 17);
7542
7543        let left_row_zero: Vec<u64> = left_columns[..8].iter().map(|column| column[0]).collect();
7544        let left_row_two: Vec<u64> = left_columns[..8].iter().map(|column| column[2]).collect();
7545        let right_row_zero: Vec<u64> = right_columns.iter().map(|column| column[0]).collect();
7546        let right_row_one: Vec<u64> = right_columns.iter().map(|column| column[1]).collect();
7547        let mut duplicate = left_row_zero.clone();
7548        duplicate.extend(right_row_zero);
7549        let new_row: Vec<u64> = (0..17).map(|column| 90_000 + column as u64).collect();
7550        let union_extra = buffer(
7551            &provider,
7552            joined_schema.clone(),
7553            &columns_from_rows(&[duplicate, new_row]),
7554        );
7555        let mut removed = left_row_two;
7556        removed.extend(right_row_one);
7557        let diff_right = buffer(
7558            &provider,
7559            joined_schema.clone(),
7560            &columns_from_rows(&[removed]),
7561        );
7562
7563        let comparisons = [
7564            ResidentFilterComparison::new(
7565                ResidentFilterOperand::Column(0),
7566                CompareOp::Eq,
7567                ResidentFilterOperand::Constant(ResidentScalar::Symbol(5)),
7568            ),
7569            ResidentFilterComparison::new(
7570                ResidentFilterOperand::Column(1),
7571                CompareOp::Gt,
7572                ResidentFilterOperand::Constant(ResidentScalar::U32(8)),
7573            ),
7574            ResidentFilterComparison::new(
7575                ResidentFilterOperand::Column(2),
7576                CompareOp::Le,
7577                ResidentFilterOperand::Constant(ResidentScalar::U64(300)),
7578            ),
7579        ];
7580        let project_expressions: Vec<_> = (0..8).map(ResidentProjectExpr::Column).collect();
7581        let primitive_filter = provider
7582            .prepare_resident_relation(left.schema().clone(), 4)
7583            .expect("primitive filter output");
7584        let primitive_project = provider
7585            .prepare_resident_relation(projected_schema.clone(), 4)
7586            .expect("primitive project output");
7587        let primitive_join = provider
7588            .prepare_resident_relation(joined_schema.clone(), 4)
7589            .expect("primitive join output");
7590        let primitive_union = provider
7591            .prepare_resident_relation(joined_schema.clone(), 5)
7592            .expect("primitive union output");
7593        let primitive_final = provider
7594            .prepare_resident_relation(joined_schema.clone(), 5)
7595            .expect("primitive diff output");
7596        let filter_workspace = provider
7597            .prepare_resident_filter_workspace(&left, &comparisons)
7598            .expect("primitive filter workspace");
7599        let project_workspace = provider
7600            .prepare_resident_project_workspace(
7601                primitive_filter.buffer(),
7602                &projected_schema,
7603                &project_expressions,
7604            )
7605            .expect("primitive project workspace");
7606        let join_workspace = provider
7607            .prepare_resident_join_workspace(3)
7608            .expect("primitive join workspace");
7609        let union_workspace = provider
7610            .prepare_resident_set_workspace(6)
7611            .expect("primitive union workspace");
7612        let diff_workspace = provider
7613            .prepare_resident_set_workspace(6)
7614            .expect("primitive diff workspace");
7615        let control = provider
7616            .prepare_resident_convergence_control()
7617            .expect("primitive control");
7618        let primitive_stream = provider
7619            .device()
7620            .inner()
7621            .stream()
7622            .fork()
7623            .expect("primitive stream");
7624        let primitive_graph = CapturedCudaGraph::capture_on_stream(&primitive_stream, || {
7625            provider.record_resident_control_initialize_on_stream(&control, &primitive_stream)?;
7626            provider.record_resident_filter_on_stream(
7627                &left,
7628                &primitive_filter,
7629                &filter_workspace,
7630                &control,
7631                101,
7632                &primitive_stream,
7633            )?;
7634            provider.record_resident_project_on_stream(
7635                primitive_filter.buffer(),
7636                &primitive_project,
7637                &project_workspace,
7638                &control,
7639                102,
7640                &primitive_stream,
7641            )?;
7642            provider.record_resident_join_on_stream(
7643                ResidentJoinKind::Inner,
7644                primitive_project.buffer(),
7645                0,
7646                &right,
7647                0,
7648                &primitive_join,
7649                &join_workspace,
7650                &control,
7651                103,
7652                &primitive_stream,
7653            )?;
7654            provider.record_resident_union_on_stream(
7655                primitive_join.buffer(),
7656                &union_extra,
7657                &primitive_union,
7658                &union_workspace,
7659                &control,
7660                104,
7661                &primitive_stream,
7662            )?;
7663            provider.record_resident_diff_on_stream(
7664                primitive_union.buffer(),
7665                &diff_right,
7666                &primitive_final,
7667                &diff_workspace,
7668                &control,
7669                105,
7670                &primitive_stream,
7671            )
7672        })
7673        .expect("primitive chain capture");
7674        primitive_graph
7675            .launch(&primitive_stream)
7676            .expect("primitive chain launch");
7677        primitive_stream
7678            .synchronize()
7679            .expect("primitive chain synchronization");
7680        let expected = normalized_rows(&provider, primitive_final.buffer());
7681
7682        let mut scheduled_filter = provider
7683            .prepare_resident_relation(left.schema().clone(), 4)
7684            .expect("scheduled filter output")
7685            .into_buffer();
7686        let mut scheduled_project = provider
7687            .prepare_resident_relation(projected_schema.clone(), 4)
7688            .expect("scheduled project output")
7689            .into_buffer();
7690        let mut scheduled_join = provider
7691            .prepare_resident_relation(joined_schema.clone(), 4)
7692            .expect("scheduled join output")
7693            .into_buffer();
7694        let mut scheduled_union = provider
7695            .prepare_resident_relation(joined_schema.clone(), 5)
7696            .expect("scheduled union output")
7697            .into_buffer();
7698        let mut scheduled_final = provider
7699            .prepare_resident_relation(joined_schema, 5)
7700            .expect("scheduled diff output")
7701            .into_buffer();
7702        let relations = vec![
7703            super::ResidentScheduleRelation::source(&left, 10).expect("left source"),
7704            super::ResidentScheduleRelation::source(&right, 11).expect("right source"),
7705            super::ResidentScheduleRelation::source(&union_extra, 12).expect("union source"),
7706            super::ResidentScheduleRelation::source(&diff_right, 13).expect("diff source"),
7707            super::ResidentScheduleRelation::output(&mut scheduled_filter, 14),
7708            super::ResidentScheduleRelation::output(&mut scheduled_project, 15),
7709            super::ResidentScheduleRelation::output(&mut scheduled_join, 16),
7710            super::ResidentScheduleRelation::output(&mut scheduled_union, 17),
7711            super::ResidentScheduleRelation::output(&mut scheduled_final, 18),
7712        ];
7713        let ops = [
7714            super::ResidentOpDescriptor {
7715                kind: super::OP_FILTER,
7716                flags: 0,
7717                op_id: 101,
7718                out: 4,
7719                in0: 0,
7720                in1: 0,
7721                in0_generation: 10,
7722                in1_generation: 0,
7723                out_generation: 14,
7724                aux_offset: 0,
7725                aux_count: 3,
7726                left_key: 0,
7727                right_key: 0,
7728                scan_delta: 0,
7729                filter_delta: 0,
7730                schema_winner_head: 0,
7731                schema_winner_id: 0,
7732                reserved: 0,
7733            },
7734            super::ResidentOpDescriptor {
7735                kind: super::OP_PROJECT,
7736                flags: 0,
7737                op_id: 102,
7738                out: 5,
7739                in0: 4,
7740                in1: 0,
7741                in0_generation: 14,
7742                in1_generation: 0,
7743                out_generation: 15,
7744                aux_offset: 0,
7745                aux_count: 8,
7746                left_key: 0,
7747                right_key: 0,
7748                scan_delta: 0,
7749                filter_delta: 0,
7750                schema_winner_head: 0,
7751                schema_winner_id: 0,
7752                reserved: 0,
7753            },
7754            super::ResidentOpDescriptor {
7755                kind: super::OP_JOIN_INNER,
7756                flags: 0,
7757                op_id: 103,
7758                out: 6,
7759                in0: 5,
7760                in1: 1,
7761                in0_generation: 15,
7762                in1_generation: 11,
7763                out_generation: 16,
7764                aux_offset: 0,
7765                aux_count: 0,
7766                left_key: 0,
7767                right_key: 0,
7768                scan_delta: 0,
7769                filter_delta: 0,
7770                schema_winner_head: 0,
7771                schema_winner_id: 0,
7772                reserved: 0,
7773            },
7774            super::ResidentOpDescriptor {
7775                kind: super::OP_UNION,
7776                flags: 0,
7777                op_id: 104,
7778                out: 7,
7779                in0: 6,
7780                in1: 2,
7781                in0_generation: 16,
7782                in1_generation: 12,
7783                out_generation: 17,
7784                aux_offset: 0,
7785                aux_count: 0,
7786                left_key: 0,
7787                right_key: 0,
7788                scan_delta: 0,
7789                filter_delta: 0,
7790                schema_winner_head: 0,
7791                schema_winner_id: 0,
7792                reserved: 0,
7793            },
7794            super::ResidentOpDescriptor {
7795                kind: super::OP_DIFF,
7796                flags: 0,
7797                op_id: 105,
7798                out: 8,
7799                in0: 7,
7800                in1: 3,
7801                in0_generation: 17,
7802                in1_generation: 13,
7803                out_generation: 18,
7804                aux_offset: 0,
7805                aux_count: 0,
7806                left_key: 0,
7807                right_key: 0,
7808                scan_delta: 0,
7809                filter_delta: 0,
7810                schema_winner_head: 0,
7811                schema_winner_id: 0,
7812                reserved: 0,
7813            },
7814        ];
7815        let filter_descriptors = [
7816            super::ResidentFilterComparisonDescriptor::column_constant(0, 0, 4, 5),
7817            super::ResidentFilterComparisonDescriptor::column_constant(1, 4, 4, 8),
7818            super::ResidentFilterComparisonDescriptor::column_constant(2, 3, 8, 300),
7819        ];
7820        let project_descriptors: Vec<_> = projected_types
7821            .iter()
7822            .enumerate()
7823            .map(|(column, scalar)| {
7824                super::ResidentProjectExpressionDescriptor::column(
7825                    column as u32,
7826                    scalar.size_bytes() as u32,
7827                )
7828            })
7829            .collect();
7830        let wave = super::ResidentWaveDescriptor {
7831            first_op: 0,
7832            op_count: 5,
7833            flags: 0,
7834            reserved: 0,
7835        };
7836        let region = super::ResidentRegionDescriptor {
7837            first_wave: 0,
7838            wave_count: 1,
7839            iteration_limit: 1,
7840            op_id: 199,
7841            flags: super::RESIDENT_SCHEDULE_REGION_INITIALIZE
7842                | super::RESIDENT_SCHEDULE_REGION_FINALIZE,
7843            first_slot: 0,
7844            slot_count: 9,
7845            generation_offset: 0,
7846        };
7847        let schedule = provider
7848            .prepare_resident_schedule(
7849                relations,
7850                &ops,
7851                &[wave],
7852                &[region],
7853                &filter_descriptors,
7854                &project_descriptors,
7855                &[8],
7856            )
7857            .expect("prepare compact resident schedule");
7858        let stream = provider
7859            .device()
7860            .inner()
7861            .stream()
7862            .fork()
7863            .expect("compact schedule stream");
7864        provider.reset_host_transfer_stats();
7865        provider.reset_d2h_transfer_count();
7866        provider.reset_untracked_metadata_dtoh_count();
7867        let mut graph = provider
7868            .capture_resident_schedule(schedule, 0, Arc::clone(&stream))
7869            .expect("compact schedule capture");
7870        assert_eq!(graph.node_count().expect("node count"), 1);
7871        assert_eq!(
7872            graph.nodes().expect("nodes")[0].kind,
7873            CudaGraphNodeKind::Kernel
7874        );
7875        graph.launch().expect("compact schedule launch");
7876        let receipt = graph
7877            .synchronize_and_observe()
7878            .expect("compact schedule receipt");
7879        let transfers = provider.host_transfer_stats();
7880        let launch_metadata = provider.host_launch_metadata_transfer_stats();
7881        assert_eq!(transfers.htod_calls, 0);
7882        assert_eq!(transfers.htod_bytes, 0);
7883        assert_eq!(transfers.dtoh_calls, 0);
7884        assert_eq!(transfers.dtoh_bytes, 0);
7885        assert_eq!(launch_metadata.htod_calls, 0);
7886        assert_eq!(launch_metadata.htod_bytes, 0);
7887        assert_eq!(provider.d2h_transfer_count(), 0);
7888        assert_eq!(provider.untracked_metadata_dtoh_count(), 0);
7889
7890        assert_eq!(receipt.status.code, ResidentTerminalCode::Success as u32);
7891        assert_eq!(receipt.status.op_id, 199);
7892        assert_eq!(receipt.counts, vec![4]);
7893        let scheduled_final = graph.relation(8).expect("scheduled final relation");
7894        assert_eq!(scheduled_final.arity(), 17);
7895        assert_eq!(scheduled_final.cached_row_count(), Some(4));
7896        assert!(!scheduled_final.canonical_full_row_set_certified());
7897        assert_eq!(rows_in_device_order(&provider, scheduled_final), expected);
7898    }
7899
7900    #[test]
7901    fn real_cuda_compact_set_overflow_is_exact_and_preserves_output_storage() {
7902        let Some(provider) = provider() else { return };
7903        let relation_schema = schema("set_overflow", &[ScalarType::U32]);
7904        let left = buffer(&provider, relation_schema.clone(), &[vec![1, 2]]);
7905        let right = buffer(&provider, relation_schema.clone(), &[vec![3, 4]]);
7906        let sentinels = [0xdead_beef_u64, 0xcafe_babe];
7907        let mut output = buffer(&provider, relation_schema, &[sentinels.to_vec()]);
7908        let relations = vec![
7909            super::ResidentScheduleRelation::source(&left, 1).expect("left source"),
7910            super::ResidentScheduleRelation::source(&right, 2).expect("right source"),
7911            super::ResidentScheduleRelation::output(&mut output, 3),
7912        ];
7913        let operation = super::ResidentOpDescriptor {
7914            kind: super::OP_UNION,
7915            op_id: 801,
7916            out: 2,
7917            in0: 0,
7918            in1: 1,
7919            in0_generation: 1,
7920            in1_generation: 2,
7921            out_generation: 3,
7922            ..Default::default()
7923        };
7924        let wave = super::ResidentWaveDescriptor {
7925            first_op: 0,
7926            op_count: 1,
7927            ..Default::default()
7928        };
7929        let region = super::ResidentRegionDescriptor {
7930            first_wave: 0,
7931            wave_count: 1,
7932            iteration_limit: 1,
7933            op_id: 802,
7934            flags: super::RESIDENT_SCHEDULE_REGION_INITIALIZE
7935                | super::RESIDENT_SCHEDULE_REGION_FINALIZE,
7936            first_slot: 0,
7937            slot_count: 3,
7938            generation_offset: 0,
7939        };
7940        let schedule = provider
7941            .prepare_resident_schedule(relations, &[operation], &[wave], &[region], &[], &[], &[2])
7942            .expect("prepare set overflow schedule");
7943        let stream = provider
7944            .device()
7945            .inner()
7946            .stream()
7947            .fork()
7948            .expect("set overflow stream");
7949        let mut graph = provider
7950            .capture_resident_schedule(schedule, 0, Arc::clone(&stream))
7951            .expect("capture set overflow schedule");
7952        graph.launch().expect("launch set overflow schedule");
7953        let receipt = graph
7954            .synchronize_and_observe()
7955            .expect("set overflow receipt");
7956        assert_eq!(
7957            receipt.status.code,
7958            ResidentTerminalCode::CapacityOverflow as u32
7959        );
7960        assert_eq!(receipt.status.op_id, 801);
7961        assert_eq!(receipt.status.required, 4);
7962        assert_eq!(receipt.status.capacity, 2);
7963        assert_eq!(receipt.counts, vec![0]);
7964        let raw: Vec<u8> = provider
7965            .device()
7966            .inner()
7967            .dtoh_sync_copy(
7968                graph
7969                    .relation(2)
7970                    .expect("set overflow output")
7971                    .column(0)
7972                    .expect("set overflow column"),
7973            )
7974            .expect("set overflow storage");
7975        let expected: Vec<u8> = sentinels
7976            .iter()
7977            .flat_map(|value| (*value as u32).to_le_bytes())
7978            .collect();
7979        assert_eq!(raw, expected);
7980    }
7981
7982    #[test]
7983    fn real_cuda_compact_join_overflow_is_exact_and_preserves_output_storage() {
7984        let Some(provider) = provider() else { return };
7985        let left_schema = schema("join_left", &[ScalarType::U32]);
7986        let right_schema = schema("join_right", &[ScalarType::U32]);
7987        let mut output_columns = left_schema.columns.clone();
7988        output_columns.extend(right_schema.columns.iter().cloned());
7989        let output_schema = Schema::new(output_columns);
7990        let left = buffer(&provider, left_schema, &[vec![1, 1]]);
7991        let right = buffer(&provider, right_schema, &[vec![1, 1]]);
7992        let sentinels = [
7993            vec![0x1111_1111_u64, 0x2222_2222],
7994            vec![0x3333_3333_u64, 0x4444_4444],
7995        ];
7996        let mut output = buffer(&provider, output_schema, &sentinels);
7997        let relations = vec![
7998            super::ResidentScheduleRelation::source(&left, 1).expect("left source"),
7999            super::ResidentScheduleRelation::source(&right, 2).expect("right source"),
8000            super::ResidentScheduleRelation::output(&mut output, 3),
8001        ];
8002        let operation = super::ResidentOpDescriptor {
8003            kind: super::OP_JOIN_INNER,
8004            op_id: 811,
8005            out: 2,
8006            in0: 0,
8007            in1: 1,
8008            in0_generation: 1,
8009            in1_generation: 2,
8010            out_generation: 3,
8011            left_key: 0,
8012            right_key: 0,
8013            ..Default::default()
8014        };
8015        let wave = super::ResidentWaveDescriptor {
8016            first_op: 0,
8017            op_count: 1,
8018            ..Default::default()
8019        };
8020        let region = super::ResidentRegionDescriptor {
8021            first_wave: 0,
8022            wave_count: 1,
8023            iteration_limit: 1,
8024            op_id: 812,
8025            flags: super::RESIDENT_SCHEDULE_REGION_INITIALIZE
8026                | super::RESIDENT_SCHEDULE_REGION_FINALIZE,
8027            first_slot: 0,
8028            slot_count: 3,
8029            generation_offset: 0,
8030        };
8031        let schedule = provider
8032            .prepare_resident_schedule(relations, &[operation], &[wave], &[region], &[], &[], &[2])
8033            .expect("prepare join overflow schedule");
8034        let stream = provider
8035            .device()
8036            .inner()
8037            .stream()
8038            .fork()
8039            .expect("join overflow stream");
8040        let mut graph = provider
8041            .capture_resident_schedule(schedule, 0, Arc::clone(&stream))
8042            .expect("capture join overflow schedule");
8043        graph.launch().expect("launch join overflow schedule");
8044        let receipt = graph
8045            .synchronize_and_observe()
8046            .expect("join overflow receipt");
8047        assert_eq!(
8048            receipt.status.code,
8049            ResidentTerminalCode::CapacityOverflow as u32
8050        );
8051        assert_eq!(receipt.status.op_id, 811);
8052        assert_eq!(receipt.status.required, 4);
8053        assert_eq!(receipt.status.capacity, 2);
8054        assert_eq!(receipt.counts, vec![0]);
8055        for (column, expected) in sentinels.iter().enumerate() {
8056            let raw: Vec<u8> = provider
8057                .device()
8058                .inner()
8059                .dtoh_sync_copy(
8060                    graph
8061                        .relation(2)
8062                        .expect("join overflow output")
8063                        .column(column)
8064                        .expect("join overflow column"),
8065                )
8066                .expect("join overflow storage");
8067            let expected: Vec<u8> = expected
8068                .iter()
8069                .flat_map(|value| (*value as u32).to_le_bytes())
8070                .collect();
8071            assert_eq!(raw, expected, "column {column} was written on overflow");
8072        }
8073    }
8074
8075    #[test]
8076    fn real_cuda_compact_project_overflow_is_sticky_and_preserves_storage() {
8077        let Some(provider) = provider() else { return };
8078        let relation_schema = schema("project_overflow", &[ScalarType::U32]);
8079        let input = buffer(&provider, relation_schema.clone(), &[vec![1, 2, 3, 4]]);
8080        let sentinels = [0xaaaa_aaaa_u64, 0xbbbb_bbbb];
8081        let downstream_sentinels = [0xcccc_cccc_u64, 0xdddd_dddd];
8082        let mut overflow_output = buffer(&provider, relation_schema.clone(), &[sentinels.to_vec()]);
8083        let mut downstream = buffer(&provider, relation_schema, &[downstream_sentinels.to_vec()]);
8084        let relations = vec![
8085            super::ResidentScheduleRelation::source(&input, 1).expect("project source"),
8086            super::ResidentScheduleRelation::output(&mut overflow_output, 2),
8087            super::ResidentScheduleRelation::output(&mut downstream, 3),
8088        ];
8089        let operations = [
8090            super::ResidentOpDescriptor {
8091                kind: super::OP_PROJECT,
8092                op_id: 821,
8093                out: 1,
8094                in0: 0,
8095                in0_generation: 1,
8096                out_generation: 2,
8097                aux_offset: 0,
8098                aux_count: 1,
8099                ..Default::default()
8100            },
8101            super::ResidentOpDescriptor {
8102                kind: super::OP_PROJECT,
8103                op_id: 822,
8104                out: 2,
8105                in0: 1,
8106                in0_generation: 2,
8107                out_generation: 3,
8108                aux_offset: 1,
8109                aux_count: 1,
8110                ..Default::default()
8111            },
8112        ];
8113        let expression = super::ResidentProjectExpressionDescriptor::column(0, 4);
8114        let wave = super::ResidentWaveDescriptor {
8115            first_op: 0,
8116            op_count: 2,
8117            ..Default::default()
8118        };
8119        let region = super::ResidentRegionDescriptor {
8120            first_wave: 0,
8121            wave_count: 1,
8122            iteration_limit: 1,
8123            op_id: 823,
8124            flags: super::RESIDENT_SCHEDULE_REGION_INITIALIZE
8125                | super::RESIDENT_SCHEDULE_REGION_FINALIZE,
8126            first_slot: 0,
8127            slot_count: 3,
8128            generation_offset: 0,
8129        };
8130        let schedule = provider
8131            .prepare_resident_schedule(
8132                relations,
8133                &operations,
8134                &[wave],
8135                &[region],
8136                &[],
8137                &[expression, expression],
8138                &[1, 2],
8139            )
8140            .expect("prepare project overflow schedule");
8141        let stream = provider
8142            .device()
8143            .inner()
8144            .stream()
8145            .fork()
8146            .expect("project overflow stream");
8147        let mut graph = provider
8148            .capture_resident_schedule(schedule, 0, Arc::clone(&stream))
8149            .expect("capture project overflow schedule");
8150        graph.launch().expect("launch project overflow schedule");
8151        let receipt = graph
8152            .synchronize_and_observe()
8153            .expect("project overflow receipt");
8154        assert_eq!(
8155            receipt.status.code,
8156            ResidentTerminalCode::CapacityOverflow as u32
8157        );
8158        assert_eq!(receipt.status.op_id, 821);
8159        assert_eq!(receipt.status.required, 4);
8160        assert_eq!(receipt.status.capacity, 2);
8161        assert_eq!(receipt.counts, vec![0, 0]);
8162        for (slot, expected) in [(1_usize, sentinels), (2, downstream_sentinels)] {
8163            let raw: Vec<u8> = provider
8164                .device()
8165                .inner()
8166                .dtoh_sync_copy(
8167                    graph
8168                        .relation(slot)
8169                        .expect("project output")
8170                        .column(0)
8171                        .expect("project column"),
8172                )
8173                .expect("project storage");
8174            let expected: Vec<u8> = expected
8175                .iter()
8176                .flat_map(|value| (*value as u32).to_le_bytes())
8177                .collect();
8178            assert_eq!(raw, expected, "slot {slot} was written after overflow");
8179        }
8180    }
8181
8182    #[test]
8183    fn real_cuda_compact_filter_overflow_is_exact_and_preserves_output_storage() {
8184        let Some(provider) = provider() else { return };
8185        let types = [ScalarType::Symbol, ScalarType::U32, ScalarType::U64];
8186        let relation_schema = schema("overflow", &types);
8187        let input = buffer(
8188            &provider,
8189            relation_schema.clone(),
8190            &[
8191                vec![1, 2, 3, 4],
8192                vec![10, 20, 30, 40],
8193                vec![100, 200, 300, 400],
8194            ],
8195        );
8196        let sentinel_columns = [
8197            vec![0xdead_beef, 0xcafe_babe],
8198            vec![0x1234_5678, 0x8765_4321],
8199            vec![0x0123_4567_89ab_cdef, 0xfedc_ba98_7654_3210],
8200        ];
8201        let mut output = buffer(&provider, relation_schema, &sentinel_columns);
8202        let relations = vec![
8203            super::ResidentScheduleRelation::source(&input, 1).expect("input source"),
8204            super::ResidentScheduleRelation::output(&mut output, 2),
8205        ];
8206        let op = super::ResidentOpDescriptor {
8207            kind: super::OP_FILTER,
8208            flags: 0,
8209            op_id: 301,
8210            out: 1,
8211            in0: 0,
8212            in1: 0,
8213            in0_generation: 1,
8214            in1_generation: 0,
8215            out_generation: 2,
8216            aux_offset: 0,
8217            aux_count: 1,
8218            left_key: 0,
8219            right_key: 0,
8220            scan_delta: 0,
8221            filter_delta: 0,
8222            schema_winner_head: 0,
8223            schema_winner_id: 0,
8224            reserved: 0,
8225        };
8226        let wave = super::ResidentWaveDescriptor {
8227            first_op: 0,
8228            op_count: 1,
8229            flags: 0,
8230            reserved: 0,
8231        };
8232        let region = super::ResidentRegionDescriptor {
8233            first_wave: 0,
8234            wave_count: 1,
8235            iteration_limit: 1,
8236            op_id: 399,
8237            flags: super::RESIDENT_SCHEDULE_REGION_INITIALIZE
8238                | super::RESIDENT_SCHEDULE_REGION_FINALIZE,
8239            first_slot: 0,
8240            slot_count: 2,
8241            generation_offset: 0,
8242        };
8243        let comparisons = [super::ResidentFilterComparisonDescriptor::column_constant(
8244            0, 5, 4, 0,
8245        )];
8246        let schedule = provider
8247            .prepare_resident_schedule(
8248                relations,
8249                &[op],
8250                &[wave],
8251                &[region],
8252                &comparisons,
8253                &[],
8254                &[1],
8255            )
8256            .expect("prepare overflow schedule");
8257        let stream = provider
8258            .device()
8259            .inner()
8260            .stream()
8261            .fork()
8262            .expect("overflow stream");
8263        provider.reset_host_transfer_stats();
8264        provider.reset_d2h_transfer_count();
8265        provider.reset_untracked_metadata_dtoh_count();
8266        let mut graph = provider
8267            .capture_resident_schedule(schedule, 0, Arc::clone(&stream))
8268            .expect("overflow capture");
8269        assert_eq!(graph.node_count().expect("overflow node count"), 1);
8270        graph.launch().expect("overflow launch");
8271        let receipt = graph.synchronize_and_observe().expect("overflow receipt");
8272        let transfers = provider.host_transfer_stats();
8273        let launch_metadata = provider.host_launch_metadata_transfer_stats();
8274        assert_eq!(transfers.htod_calls + transfers.dtoh_calls, 0);
8275        assert_eq!(transfers.htod_bytes + transfers.dtoh_bytes, 0);
8276        assert_eq!(launch_metadata.htod_calls, 0);
8277        assert_eq!(launch_metadata.htod_bytes, 0);
8278        assert_eq!(provider.d2h_transfer_count(), 0);
8279        assert_eq!(provider.untracked_metadata_dtoh_count(), 0);
8280
8281        assert_eq!(
8282            receipt.status.code,
8283            ResidentTerminalCode::CapacityOverflow as u32
8284        );
8285        assert_eq!(receipt.status.op_id, 301);
8286        assert_eq!(
8287            receipt.status.resource_code,
8288            ResidentResourceCode::OutputRows as u32
8289        );
8290        assert_eq!(receipt.status.required, 4);
8291        assert_eq!(receipt.status.capacity, 2);
8292        assert_eq!(receipt.counts, vec![0]);
8293
8294        let output = graph.relation(1).expect("overflow output relation");
8295        for (column, expected) in sentinel_columns.iter().enumerate() {
8296            let raw: Vec<u8> = provider
8297                .device()
8298                .inner()
8299                .dtoh_sync_copy(output.column(column).expect("output column"))
8300                .expect("raw output storage");
8301            let expected: Vec<u8> = if types[column].size_bytes() == 4 {
8302                expected
8303                    .iter()
8304                    .flat_map(|value| (*value as u32).to_le_bytes())
8305                    .collect()
8306            } else {
8307                expected
8308                    .iter()
8309                    .flat_map(|value| value.to_le_bytes())
8310                    .collect()
8311            };
8312            assert_eq!(raw, expected, "column {column} was written on overflow");
8313        }
8314    }
8315}