metrale_model_layers/layers/
kernel_probe.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3//! 2026-09-25: Optional kernel lookups that return `KernelHandle(0)` instead of an error.
4//!
5//! Every lookup goes through `GpuBackend::kernel`, which records it in the
6//! kernel audit (`metrale_telemetry::kernel_audit::record`). At boot,
7//! `serve_phases/kernel_gate.rs` refuses to serve when a failed lookup is not
8//! declared in the target's MODEL.toml `[expected_absent]`, unless
9//! `--dangerously-allow-unresolved-kernel-lookups` is passed.
10//!
11//! Owner: model-layers (kernel lookup).
12//! Invariants: `try_target_kernel` issues no lookup for a module the backend
13//! does not carry (`GpuBackend::has_module`).
14
15use metrale_gpu_runtime::gpu::{GpuBackend, KernelHandle};
16
17/// 2026-09-25: Look up a kernel from a module only some targets compile.
18/// Returns `KernelHandle(0)` without a lookup, and so without an audit row,
19/// when the backend does not carry `module`; otherwise it is [`try_kernel`].
20#[track_caller]
21pub fn try_target_kernel(gpu: &dyn GpuBackend, module: &str, func: &str) -> KernelHandle {
22    if !gpu.has_module(module) {
23        return KernelHandle(0);
24    }
25    try_kernel(gpu, module, func)
26}
27
28/// 2026-09-25: Look up `module::func`, returning `KernelHandle(0)` (and a
29/// debug log) when the lookup fails. A zero handle is a slower path or a
30/// missing feature, so a caller must check it before launching.
31///
32/// `#[track_caller]` here and on `GpuBackend::kernel` makes the audit record
33/// the caller's `file:line` rather than this function's.
34#[track_caller]
35pub fn try_kernel(gpu: &dyn GpuBackend, module: &str, func: &str) -> KernelHandle {
36    match gpu.kernel(module, func) {
37        Ok(h) => h,
38        Err(_) => {
39            tracing::debug!("Optional kernel '{module}::{func}' not loaded");
40            KernelHandle(0)
41        }
42    }
43}
44
45#[cfg(test)]
46#[path = "kernel_probe_tests.rs"]
47mod kernel_probe_tests;