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:
2026-10-26 19:54:23 +01:00
parent 8d2c40cb1e
commit d43421e33e
32 changed files with 790 additions and 207 deletions

View File

@@ -0,0 +1,36 @@
use super::SlotGenerations;
use types::generation::Generation;
#[test]
fn slots_start_at_the_initial_generation() {
let g: SlotGenerations<2> = SlotGenerations::new();
assert_eq!(g.current(0), Some(Generation::initial()));
assert!(g.is_usable(1));
}
#[test]
fn advance_changes_the_generation() {
let mut g: SlotGenerations<2> = SlotGenerations::new();
let before = g.current(0);
g.advance(0);
assert_ne!(g.current(0), before);
assert_eq!(g.current(1), before, "other slots untouched");
}
#[test]
fn out_of_range_slots_are_never_usable() {
let mut g: SlotGenerations<2> = SlotGenerations::new();
assert_eq!(g.current(2), None);
g.advance(2); // no panic
}
#[test]
fn exhausted_counter_retires_the_slot() {
let mut g: SlotGenerations<1> = SlotGenerations::new();
g.gens[0] = Some(Generation::from_raw(u32::MAX));
g.advance(0);
assert_eq!(g.current(0), None);
assert!(!g.is_usable(0));
g.advance(0);
assert_eq!(g.current(0), None, "retired slots stay retired");
}