Skip to main content

strat9_kernel/ipc/
lifecycle.rs

1use crate::process::TaskId;
2
3use super::{
4    channel::{self, ChanId},
5    port::{self, PortId},
6    semaphore::{self, SemId},
7    shared_ring::{self, RingId},
8};
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum MultiHandleDestroyError {
12    NotFound,
13}
14
15/// Shared finalization path for IPC resources that remain live until their
16/// last handle disappears from the global capability set.
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18pub enum MultiHandleResource {
19    Channel(ChanId),
20    Semaphore(SemId),
21    SharedRing(RingId),
22    IpcPort { id: PortId, owner: Option<TaskId> },
23}
24
25impl MultiHandleResource {
26    /// Destroy the underlying resource once the last handle is gone.
27    // TODO(migration): This API currently serves both "last handle dropped"
28    // and admin-side destroy paths such as ipcfs::unlink. Decide whether those
29    // semantics should stay identical. If admin unlink is meant to force
30    // teardown even while capabilities still exist, split this into explicit
31    // final-release vs force-destroy entry points and make the caller choose
32    // intentionally instead of sharing one ambiguous destroy() path.
33    pub fn destroy(self) -> Result<(), MultiHandleDestroyError> {
34        match self {
35            Self::Channel(id) => {
36                channel::destroy_channel(id).map_err(|_| MultiHandleDestroyError::NotFound)
37            }
38            Self::Semaphore(id) => {
39                semaphore::destroy_semaphore(id).map_err(|_| MultiHandleDestroyError::NotFound)
40            }
41            Self::SharedRing(id) => {
42                shared_ring::destroy_ring(id).map_err(|_| MultiHandleDestroyError::NotFound)
43            }
44            Self::IpcPort { id, owner } => {
45                let owner = owner.or_else(|| port::get_port(id).map(|port| port.owner));
46                let task_id = owner.ok_or(MultiHandleDestroyError::NotFound)?;
47                port::destroy_port(id, task_id).map_err(|_| MultiHandleDestroyError::NotFound)
48            }
49        }
50    }
51}