kernel/object/handle/
mod.rs

1use alloc::vec::Vec;
2
3use crate::object::{introspection, KernelObject};
4
5pub mod syscall;
6
7#[cfg(test)]
8mod tests;
9
10/// Handle type for referencing kernel objects
11pub type Handle = u32;
12
13#[derive(Clone)]
14pub struct HandleTable {
15    /// Fixed-size handle table
16    handles: [Option<KernelObject>; Self::MAX_HANDLES],
17    /// Metadata for each handle
18    metadata: [Option<HandleMetadata>; Self::MAX_HANDLES],
19    /// Stack of available handle numbers for O(1) allocation
20    free_handles: Vec<Handle>,
21}
22
23impl HandleTable {
24    const MAX_HANDLES: usize = 1024; // POSIX standard limit (fd)
25    
26    pub fn new() -> Self {
27        // Initialize free handle stack in forward order (0 will be allocated first)
28        let mut free_handles = Vec::with_capacity(Self::MAX_HANDLES);
29        for handle in (0..Self::MAX_HANDLES as Handle).rev() {
30            free_handles.push(handle);
31        }
32        
33        Self {
34            handles: [const { None }; Self::MAX_HANDLES],
35            metadata: [const { None }; Self::MAX_HANDLES],
36            free_handles,
37        }
38    }
39    
40    /// O(1) allocation with automatic metadata inference
41    pub fn insert(&mut self, obj: KernelObject) -> Result<Handle, &'static str> {
42        let metadata = Self::infer_metadata_from_object(&obj);
43        self.insert_with_metadata(obj, metadata)
44    }
45    
46    /// O(1) allocation with explicit metadata
47    pub fn insert_with_metadata(&mut self, obj: KernelObject, metadata: HandleMetadata) -> Result<Handle, &'static str> {
48        if let Some(handle) = self.free_handles.pop() {
49            self.handles[handle as usize] = Some(obj);
50            self.metadata[handle as usize] = Some(metadata);
51            Ok(handle)
52        } else {
53            Err("Too many open KernelObjects, limit reached")
54        }
55    }
56    
57    /// Infer metadata from KernelObject type and usage context
58    /// 
59    /// This function provides reasonable defaults for handle roles based on the KernelObject type.
60    /// Applications can override this by using insert_with_metadata() to specify exact roles.
61    fn infer_metadata_from_object(object: &KernelObject) -> HandleMetadata {
62        let handle_type = match object {
63            KernelObject::Pipe(_) => {
64                // Pipes are typically used for IPC, but could also be used for
65                // logging, temp storage, etc. We default to IPC as the most common case.
66                HandleType::IpcChannel
67            }
68            KernelObject::File(_file_obj) => {
69                // Files can serve many roles. Without additional context,
70                // we default to Regular usage. Applications should use
71                // insert_with_metadata() to specify specific roles like
72                // ConfigFile, LogOutput, etc.
73                HandleType::Regular
74            }
75        };
76
77        HandleMetadata {
78            handle_type,
79            access_mode: AccessMode::ReadWrite,  // Default value
80            special_semantics: None,             // Normal behavior (inherit on exec, etc.)
81        }
82    }
83    
84    /// O(1) access
85    pub fn get(&self, handle: Handle) -> Option<&KernelObject> {
86        if handle as usize >= Self::MAX_HANDLES {
87            return None;
88        }
89        self.handles[handle as usize].as_ref()
90    }
91    
92    /// O(1) removal
93    pub fn remove(&mut self, handle: Handle) -> Option<KernelObject> {
94        if handle as usize >= Self::MAX_HANDLES {
95            return None;
96        }
97
98        if let Some(obj) = self.handles[handle as usize].take() {
99            self.metadata[handle as usize] = None; // Clear metadata too
100            self.free_handles.push(handle); // Return to free pool
101            Some(obj)
102        } else {
103            None
104        }
105    }
106    
107    /// Update metadata for an existing handle
108    pub fn update_metadata(&mut self, handle: Handle, new_metadata: HandleMetadata) -> Result<(), &'static str> {
109        if handle as usize >= Self::MAX_HANDLES {
110            return Err("Invalid handle");
111        }
112        
113        if self.handles[handle as usize].is_some() {
114            self.metadata[handle as usize] = Some(new_metadata);
115            Ok(())
116        } else {
117            Err("Handle does not exist")
118        }
119    }
120    
121    /// Get the number of open handles
122    pub fn open_count(&self) -> usize {
123        Self::MAX_HANDLES - self.free_handles.len()
124    }
125    
126    /// Get all active handles
127    pub fn active_handles(&self) -> Vec<Handle> {
128        self.handles
129            .iter()
130            .enumerate()
131            .filter_map(|(i, handle)| {
132                if handle.is_some() {
133                    Some(i as Handle)
134                } else {
135                    None
136                }
137            })
138            .collect()
139    }
140    
141    /// Close all handles (for process termination)
142    pub fn close_all(&mut self) {
143        for (i, handle) in self.handles.iter_mut().enumerate() {
144            if let Some(_obj) = handle.take() {
145                // obj is automatically dropped, calling its Drop implementation
146                self.metadata[i] = None; // Clear metadata too
147                self.free_handles.push(i as Handle);
148            }
149        }
150    }
151    
152    /// Check if a handle is valid
153    pub fn is_valid_handle(&self, handle: Handle) -> bool {
154        if handle as usize >= Self::MAX_HANDLES {
155            return false;
156        }
157        self.handles[handle as usize].is_some()
158    }
159    
160    /// Get metadata for a handle
161    pub fn get_metadata(&self, handle: Handle) -> Option<&HandleMetadata> {
162        if handle as usize >= Self::MAX_HANDLES {
163            return None;
164        }
165        self.metadata[handle as usize].as_ref()
166    }
167    
168    /// Iterator over handles with their objects and metadata
169    pub fn iter_with_metadata(&self) -> impl Iterator<Item = (Handle, &KernelObject, &HandleMetadata)> {
170        self.handles.iter().enumerate()
171            .filter_map(|(i, obj)| {
172                obj.as_ref().and_then(|o| {
173                    self.metadata[i].as_ref().map(|m| (i as Handle, o, m))
174                })
175            })
176    }
177    
178    /// Get detailed information about a KernelObject for user space introspection
179    pub fn get_object_info(&self, handle: Handle) -> Option<introspection::KernelObjectInfo> {
180        if let Some(kernel_obj) = self.get(handle) {
181            let metadata = self.get_metadata(handle)?;
182            let handle_role = introspection::HandleRole::from(metadata.handle_type.clone());
183            let (readable, writable) = metadata.access_mode.into();
184            
185            match kernel_obj {
186                KernelObject::File(_) => {
187                    Some(introspection::KernelObjectInfo::for_file(handle_role, readable, writable))
188                }
189                KernelObject::Pipe(_) => {
190                    Some(introspection::KernelObjectInfo::for_pipe(handle_role, readable, writable))
191                }
192            }
193        } else {
194            None
195        }
196    }
197}
198
199impl Default for HandleTable {
200    fn default() -> Self {
201        Self::new()
202    }
203}
204
205/// Handle metadata for managing special semantics and ABI conversion
206/// 
207/// This metadata describes HOW a handle is being used, not WHAT the underlying KernelObject is.
208/// This enables proper ABI conversion, security policies, and resource management.
209/// 
210/// ## Examples of Role-based Usage
211/// 
212/// ```rust
213/// // Same file object used in different roles
214/// let config_file = file_obj.clone();
215/// let log_file = file_obj.clone();
216/// 
217/// // Handle for reading configuration
218/// let config_handle = task.handle_table.insert_with_metadata(
219///     KernelObject::File(config_file),
220///     HandleMetadata {
221///         handle_type: HandleType::ConfigFile,
222///         access_mode: AccessMode::ReadOnly,
223///         special_semantics: Some(SpecialSemantics::CloseOnExec),
224///     }
225/// )?;
226/// 
227/// // Handle for writing logs
228/// let log_handle = task.handle_table.insert_with_metadata(
229///     KernelObject::File(log_file),
230///     HandleMetadata {
231///         handle_type: HandleType::LogOutput,
232///         access_mode: AccessMode::WriteOnly,
233///         special_semantics: Some(SpecialSemantics::Append),
234///     }
235/// )?;
236/// ```
237#[derive(Clone, Debug)]
238pub struct HandleMetadata {
239    pub handle_type: HandleType,
240    pub access_mode: AccessMode,
241    pub special_semantics: Option<SpecialSemantics>,
242}
243
244/// Role-based handle classification
245/// 
246/// This enum describes HOW a handle is being used, not WHAT the underlying KernelObject is.
247/// The same KernelObject (e.g., a File) could be used in different roles by different handles.
248#[derive(Clone, Debug, PartialEq)]
249pub enum HandleType {
250    /// Standard input/output/error streams
251    StandardInputOutput(StandardInputOutput),
252    /// Inter-process communication channel
253    IpcChannel,
254    /// Default/generic usage
255    Regular,
256}
257
258#[derive(Clone, Debug, PartialEq)]
259pub enum StandardInputOutput {
260    Stdin,
261    Stdout,
262    Stderr,
263}
264
265#[derive(Clone, Debug, PartialEq, Copy)]
266pub enum AccessMode {
267    ReadOnly,
268    WriteOnly,
269    ReadWrite,
270}
271
272/// Special behaviors that differ from default Unix semantics
273#[derive(Clone, Debug, PartialEq)]
274pub enum SpecialSemantics {
275    CloseOnExec,        // Close on exec (O_CLOEXEC)
276    NonBlocking,        // Non-blocking mode (O_NONBLOCK)
277    Append,             // Append mode (O_APPEND)
278    Sync,               // Synchronous writes (O_SYNC)
279}
280
281impl Default for HandleMetadata {
282    fn default() -> Self {
283        Self {
284            handle_type: HandleType::Regular,
285            access_mode: AccessMode::ReadWrite,
286            special_semantics: None,
287        }
288    }
289}