//! Process identity is minted from a kernel owned process ID. //! User requests may inspect an assigned identity, but cannot replace it. #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct Principal(u64); impl Principal { pub const fn id(self) -> u64 { self.0 } } #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum Error { Full, Duplicate, Unknown, Access, Limit, Exhausted, } #[derive(Clone, Copy, Debug, PartialEq, Eq)] struct Binding
{
process: P,
principal: Principal,
}
pub struct Registry {
pub fn new() -> Self {
Self { next: 1, bindings: [None; N] }
}
/// Called only after the kernel has obtained a genuine ProcessId.
pub fn bind_kernel(&mut self, process: P) -> Result {
fn default() -> Self { Self::new() }
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Handle(u64);
impl Handle {
pub const fn id(self) -> u64 { self.0 }
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Capability {
ReadOnlyFile { object: u64, allow_child: bool },
KernelDevice { object: u64 },
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
struct Grant {
handle: Handle,
owner: P,
capability: Capability,
}
pub struct HandleSet {
pub fn new() -> Self {
Self { next: 1, grants: [None; M] }
}
pub fn issue_kernel , owner: P, capability: Capability,
) -> Result , parent: P, child: P,
actual_parent: Option , requested: u64,
) -> Result {
fn default() -> Self { Self::new() }
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct InspectHandle(u64);
impl InspectHandle {
pub const fn id(self) -> u64 { self.0 }
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct MapMetadata {
pub resource_owner: u64,
pub pages: u64,
pub published: bool,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
struct InspectGrant {
handle: InspectHandle,
observer: P,
target: P,
}
pub struct InspectSet {
pub fn new() -> Self { Self { next: 1, grants: [None; M] } }
/// Only the kernel binds a permit to two live process identities.
pub fn issue_kernel , observer: P, target: P,
) -> Result , observer: P,
actual_target: P, requested: u64,
) -> Result<(), Error> {
identities.principal(observer)?;
identities.principal(actual_target)?;
let grant = self.grants.iter().flatten()
.find(|grant| grant.handle.id() == requested && grant.observer == observer)
.ok_or(Error::Unknown)?;
if grant.target != actual_target { return Err(Error::Access); }
Ok(())
}
/// `actual_target` and `metadata` come from one live ProcessTable record.
pub fn inspect_metadata , observer: P,
actual_target: P, requested: u64, metadata: MapMetadata,
) -> Result , observer: P,
actual_target: P, requested: u64,
) -> Result<(), Error> {
self.authorize(identities, observer, actual_target, requested)?;
Err(Error::Access)
}
pub fn close_observer(&mut self, observer: P) -> usize {
let mut closed = 0;
for slot in &mut self.grants {
if slot.is_some_and(|grant| grant.observer == observer) {
*slot = None;
closed += 1;
}
}
closed
}
pub fn snapshot(&self) -> (u64, [Option<(u64, P, P)>; M]) {
(self.next, self.grants.map(|grant| grant.map(|grant|
(grant.handle.id(), grant.observer, grant.target))))
}
}
impl {
fn default() -> Self { Self::new() }
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct Budget {
pub pages: u64,
pub threads: u64,
pub handles: u64,
}
impl Budget {
fn checked_add(self, request: Self) -> Result {
owner: P,
limit: Budget,
used: Budget,
}
pub struct QuotaSet {
pub fn new() -> Self { Self { quotas: [None; N] } }
/// Kernel supplies usage from live process records before publishing limits.
pub fn adopt_kernel , owner: P,
used: Budget, limit: Budget,
) -> Result<(), Error> {
identities.principal(owner)?;
if used.threads == 0 || !used.within(limit) { return Err(Error::Limit); }
if self.quotas.iter().flatten().any(|quota| quota.owner == owner) {
return Err(Error::Duplicate);
}
let slot = self.quotas.iter_mut().find(|slot| slot.is_none())
.ok_or(Error::Full)?;
*slot = Some(Quota { owner, used, limit });
Ok(())
}
pub fn usage(&self, owner: P) -> Result<(Budget, Budget), Error> {
self.quotas.iter().flatten().find(|quota| quota.owner == owner)
.map(|quota| (quota.used, quota.limit)).ok_or(Error::Unknown)
}
/// All three additions are validated before any quota state changes.
pub fn try_reserve , owner: P, request: Budget,
) -> Result {
fn default() -> Self { Self::new() }
}