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}