Skip to main content

tensor_wasm_mem/
isolation.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2026 Craton Software Company
3
4//! Memory isolation policy for TensorWasm Wasm instances.
5//!
6//! Three levels are exposed; the active level for an instance is fixed at
7//! spawn time and stored on the executor's instance metadata (set up in S7).
8//! The level shapes both how the memory creator allocates the buffer and
9//! how the WASI-CUDA host functions in `tensor-wasm-wasi-gpu` (S8) wire kernels
10//! up to streams/contexts.
11
12use std::fmt;
13
14/// How aggressively to isolate one tenant's memory and GPU operations from
15/// another's.
16#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
17pub enum IsolationLevel {
18    /// All instances share the default CUDA context and stream.
19    ///
20    /// Cheap to spawn (no context creation) and good for fully trusted
21    /// workloads (e.g. a single-tenant deployment). Not safe for multi-tenant
22    /// untrusted code.
23    Shared,
24    /// Each instance gets its own CUDA stream but contexts are shared.
25    ///
26    /// Prevents cross-instance kernel ordering accidents and gives per-stream
27    /// scheduling. Default for multi-tenant deployments.
28    #[default]
29    StreamIsolated,
30    /// Each tenant gets its own CUDA context (via MPS when available, or
31    /// `cuCtxCreate` otherwise). Enabled in S16.
32    ContextIsolated,
33}
34
35impl IsolationLevel {
36    /// Stable, human-readable name (used in span attributes and metrics).
37    pub fn name(&self) -> &'static str {
38        match self {
39            IsolationLevel::Shared => "shared",
40            IsolationLevel::StreamIsolated => "stream_isolated",
41            IsolationLevel::ContextIsolated => "context_isolated",
42        }
43    }
44}
45
46impl fmt::Display for IsolationLevel {
47    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48        f.write_str(self.name())
49    }
50}
51
52#[cfg(test)]
53mod tests {
54    use super::*;
55
56    #[test]
57    fn default_is_stream_isolated() {
58        assert_eq!(IsolationLevel::default(), IsolationLevel::StreamIsolated);
59    }
60
61    #[test]
62    fn names_are_stable() {
63        assert_eq!(IsolationLevel::Shared.name(), "shared");
64        assert_eq!(IsolationLevel::StreamIsolated.name(), "stream_isolated");
65        assert_eq!(IsolationLevel::ContextIsolated.name(), "context_isolated");
66    }
67
68    #[test]
69    fn display_matches_name() {
70        assert_eq!(IsolationLevel::Shared.to_string(), "shared");
71        assert_eq!(
72            IsolationLevel::ContextIsolated.to_string(),
73            "context_isolated"
74        );
75    }
76
77    #[test]
78    fn levels_are_ord_independent_but_distinct() {
79        assert_ne!(IsolationLevel::Shared, IsolationLevel::StreamIsolated);
80        assert_ne!(
81            IsolationLevel::StreamIsolated,
82            IsolationLevel::ContextIsolated
83        );
84    }
85}