Skip to main content

xlog_cuda/provider/
resident_schedule.rs

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