feat(kernel): WatchDeath + SetTimer events as notification signals; adapter wakes at earliest deadline
This commit is contained in:
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user