feat(kernel): object lifetimes via slot generations
- SlotGenerations per table, never wraps, retires exhausted slots - caps to dead/reused process, endpoint, region rejected - endpoints owned, die w/ owner, waiters woken w/ error - DropCap syscall + libkos wrapper - irq table bounds-checked, routes dropped w/ thread - self-kill terminates caller, exit_thread full cleanup - sched run_now: switch to named thread, not queue head - lifetime tests, fuzz kills/recreates, kani gen proofs
This commit is contained in:
@@ -20,20 +20,35 @@ impl IrqRoutingTable {
|
||||
}
|
||||
|
||||
pub fn register(&mut self, irq: IrqId, thread: ThreadId) -> Result<(), KernelError> {
|
||||
let idx = irq.raw() as usize;
|
||||
if self.owners[idx].is_some() {
|
||||
let slot = self
|
||||
.owners
|
||||
.get_mut(irq.raw() as usize)
|
||||
.ok_or(KernelError::InvalidIrq(irq))?;
|
||||
if slot.is_some() {
|
||||
return Err(KernelError::IrqAlreadyOwned(irq));
|
||||
}
|
||||
self.owners[idx] = Some(thread);
|
||||
*slot = Some(thread);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn unregister(&mut self, irq: IrqId) {
|
||||
self.owners[irq.raw() as usize] = None;
|
||||
if let Some(slot) = self.owners.get_mut(irq.raw() as usize) {
|
||||
*slot = None;
|
||||
}
|
||||
}
|
||||
|
||||
/// Drops every route to `thread`, e.g. when it dies.
|
||||
pub fn unregister_thread(&mut self, thread: ThreadId) {
|
||||
for slot in &mut self.owners {
|
||||
if *slot == Some(thread) {
|
||||
*slot = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The thread an interrupt is routed to; `None` for unknown lines.
|
||||
pub fn owner(&self, irq: IrqId) -> Option<ThreadId> {
|
||||
self.owners[irq.raw() as usize]
|
||||
*self.owners.get(irq.raw() as usize)?
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user