feat(kernel): WatchDeath + SetTimer events as notification signals; adapter wakes at earliest deadline

This commit is contained in:
2026-10-27 16:06:04 +01:00
parent a4f467f45d
commit 817a38993b
25 changed files with 517 additions and 21 deletions

View File

@@ -71,8 +71,12 @@ fn run_phases(storage: &mut Storage, scratch: &mut [u8]) -> Result<(), &'static
syscall::map_region(page, VirtualAddress::from_raw(OBSERVE_VA), PagePerms::ReadWrite)
.map_err(|_| "cannot map the counter page")?;
let events = syscall::create_notification().map_err(|_| "no notification")?;
timer_is_on_time(events)?;
// Revoke must unmap the page on every hart; the spinner then faults and dies.
let spinner = start_spinner(storage, scratch, page)?;
syscall::watch_death(spinner, events).map_err(|_| "cannot watch the spinner")?;
if !syscall::revoke(page) {
return Err("revoke failed");
}
@@ -80,18 +84,43 @@ fn run_phases(storage: &mut Storage, scratch: &mut [u8]) -> Result<(), &'static
if syscall::kill(spinner) {
return Err("the spinner survived losing its page");
}
if syscall::poll(events) != Ok(1) {
return Err("nobody heard the spinner fault");
}
libkos::println!("smptest: revoke stops every hart: ok");
// Kill must stop threads running on other harts before it returns.
let spinner = start_spinner(storage, scratch, page)?;
syscall::watch_death(spinner, events).map_err(|_| "cannot watch the spinner")?;
if !syscall::kill(spinner) {
return Err("kill failed");
}
check_stopped("a counter moved after its process was killed")?;
if syscall::poll(events) != Ok(1) {
return Err("nobody heard the spinner killed");
}
libkos::println!("smptest: kill stops every hart: ok");
Ok(())
}
/// A timer must wake its waiter at the deadline, not at the next scheduling
/// tick (a second away).
fn timer_is_on_time(events: CapSlot) -> Result<(), &'static str> {
let start = syscall::get_time().raw();
let deadline = start + 50 * TICKS_PER_MS;
syscall::set_timer(events, types::time::Ticks::from_raw(deadline)).map_err(|_| "set_timer failed")?;
syscall::wait(events).map_err(|_| "wait failed")?;
let woke = syscall::get_time().raw();
if woke < deadline {
return Err("the timer fired early");
}
if woke - deadline > 20 * TICKS_PER_MS {
return Err("the timer fired late");
}
libkos::println!("smptest: timer wakes on time: ok");
Ok(())
}
/// Runs the test, reports, and halts the machine.
pub fn run(storage: &mut Storage, scratch: &mut [u8]) -> ! {
match run_phases(storage, scratch) {