fix: pm running apps grow (death-bit bound 60); spawntest stress: 30 files open, apps until BUSY then room comes back; docs: limits and why
This commit is contained in:
@@ -27,6 +27,9 @@ const STORAGE_BUF_VA: types::address::VirtualAddress = types::address::VirtualAd
|
||||
const NARROW_BUF_VA: types::address::VirtualAddress = types::address::VirtualAddress::from_raw(0x0190_0000);
|
||||
const REQUEST_PAGE_VA: types::address::VirtualAddress = types::address::VirtualAddress::from_raw(0x01C0_0000);
|
||||
const HOME_BUF_VA: types::address::VirtualAddress = types::address::VirtualAddress::from_raw(0x01B0_0000);
|
||||
const CROWD_PAGE_VA: types::address::VirtualAddress = types::address::VirtualAddress::from_raw(0x01E0_0000);
|
||||
/// Apps the old tables held beside Home; the test wants more than this.
|
||||
const OLD_APP_ROOM: usize = 7;
|
||||
/// Read back from the disk image by scripts/test-qemu.sh.
|
||||
const NOTE: &[u8] = b"written by k-os on ext4\n";
|
||||
|
||||
@@ -267,6 +270,89 @@ fn restarted_after_hanging() -> Result<(), &'static str> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Waits about `ms` on `alarm` (woken early by anything else it carries).
|
||||
fn nap(alarm: CapSlot, ms: u64) {
|
||||
let at = syscall::get_time().raw() + ms * types::time::TICKS_PER_MS;
|
||||
if syscall::set_timer(alarm, types::time::Ticks::from_raw(at)).is_ok() {
|
||||
let _ = syscall::wait(alarm);
|
||||
}
|
||||
}
|
||||
|
||||
/// Apps run until the permission manager says there is no room (busy, not
|
||||
/// a failure), well past what the old tables held; once they are stopped,
|
||||
/// the room comes back, all of it.
|
||||
fn many_apps_and_their_room_comes_back(alarm: CapSlot) -> Result<usize, &'static str> {
|
||||
use types::apps::reply;
|
||||
let apps = libkos::apps::Apps::connect(PERMISSION, CROWD_PAGE_VA).ok_or("no permission manager")?;
|
||||
let mut running = [None; 32];
|
||||
let mut n = 0;
|
||||
let refusal = loop {
|
||||
match apps.launch(&["sleep", "300"], None, None) {
|
||||
Ok((p, _)) if n < running.len() => {
|
||||
running[n] = Some(p);
|
||||
n += 1;
|
||||
}
|
||||
Ok(_) => return Err("more room than the test can hold"),
|
||||
Err(r) => break r.code,
|
||||
}
|
||||
};
|
||||
let stop = |running: &mut [Option<CapSlot>]| {
|
||||
for p in running.iter_mut().filter_map(Option::take) {
|
||||
let _ = syscall::kill(p);
|
||||
syscall::drop_cap(p);
|
||||
}
|
||||
};
|
||||
stop(&mut running);
|
||||
if refusal != reply::BUSY {
|
||||
return Err("a full permission manager did not say it was busy");
|
||||
}
|
||||
if n <= OLD_APP_ROOM {
|
||||
return Err("no more apps ran than the old tables held");
|
||||
}
|
||||
// The deaths are its to hear; give it a moment, then all of it again.
|
||||
let mut again = 0;
|
||||
for _ in 0..100 {
|
||||
match apps.launch(&["sleep", "300"], None, None) {
|
||||
Ok((p, _)) => {
|
||||
running[again] = Some(p);
|
||||
again += 1;
|
||||
if again == n {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Err(r) if r.code == reply::BUSY => nap(alarm, 50),
|
||||
Err(_) => {
|
||||
stop(&mut running);
|
||||
return Err("launching again failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
stop(&mut running);
|
||||
if again < n {
|
||||
return Err("the room did not all come back");
|
||||
}
|
||||
Ok(n)
|
||||
}
|
||||
|
||||
/// More files open at once than the old tables held (8 in ext4).
|
||||
fn many_files_open_at_once(fs: &mut Storage) -> Result<(), &'static str> {
|
||||
let mut open = [None; 30];
|
||||
let mut result = Ok(());
|
||||
for slot in open.iter_mut() {
|
||||
match fs.open(b"selftest.txt") {
|
||||
Ok(h) => *slot = Some(h),
|
||||
Err(_) => {
|
||||
result = Err("cannot hold 30 files open");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
for h in open.into_iter().flatten() {
|
||||
let _ = fs.close(h);
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
/// A server that runs off its stack faults on the guard below it, and is
|
||||
/// restarted like any other that died.
|
||||
fn restarted_after_overflowing() -> Result<(), &'static str> {
|
||||
@@ -316,6 +402,12 @@ fn check() -> Result<(), &'static str> {
|
||||
restarted_after_hanging()?;
|
||||
libkos::println!("spawntest: a hung server is noticed, stopped and restarted: ok");
|
||||
|
||||
many_files_open_at_once(&mut fs)?;
|
||||
libkos::println!("spawntest: 30 files open at once: ok");
|
||||
|
||||
let crowd = many_apps_and_their_room_comes_back(died)?;
|
||||
libkos::println!("spawntest: {} apps at once, then busy, and the room comes back: ok", crowd);
|
||||
|
||||
restarted_after_overflowing()?;
|
||||
libkos::println!("spawntest: a server that overflows its stack is caught and restarted: ok");
|
||||
Ok(())
|
||||
|
||||
Reference in New Issue
Block a user