cleaning up simulation -- more tests pass

Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
2023-12-31 23:39:28 +08:00
parent 62452373ac
commit f13d476a9f
7 changed files with 659 additions and 134 deletions

View File

@@ -59,6 +59,8 @@ pub enum Syscall {
i64, /* argument 3 */
i64, /* argument 4 */
),
JoinThread(i64 /* thread ID */),
UnmapMemory(i64, /* address */ i64 /* size */),
}
#[derive(Debug)]
@@ -88,6 +90,7 @@ impl From<[i64; 8]> for Syscall {
match value[0].into() {
SyscallNumber::IncreaseHeap => Syscall::IncreaseHeap(value[1], value[2]),
SyscallNumber::MapMemory => Syscall::MapMemory(value[1], value[2], value[3], value[4]),
SyscallNumber::UnmapMemory => Syscall::UnmapMemory(value[1], value[2]),
SyscallNumber::Connect => Syscall::Connect([
value[1] as u32,
value[2] as u32,
@@ -112,6 +115,7 @@ impl From<[i64; 8]> for Syscall {
value[1], value[2], value[3], value[4], value[5], value[6], value[7],
),
SyscallNumber::Yield => Syscall::Yield,
SyscallNumber::JoinThread => Syscall::JoinThread(value[1]),
_ => Syscall::Unknown(value),
}
}

View File

@@ -1,3 +1,4 @@
use std::sync::mpsc::Receiver;
pub mod log;
pub mod ticktimer;
@@ -5,6 +6,12 @@ pub enum ScalarResult {
Scalar1(u32),
Scalar2([u32; 2]),
Scalar5([u32; 5]),
WaitForResponse(Receiver<([i64; 8], Option<(Vec<u8>, u64)>)>),
}
pub enum LendResult {
MemoryReturned([u32; 2]),
WaitForResponse(Receiver<([i64; 8], Option<(Vec<u8>, u64)>)>),
}
pub trait Service {
@@ -14,14 +21,33 @@ pub trait Service {
fn blocking_scalar(&mut self, sender: u32, opcode: u32, _args: [u32; 4]) -> ScalarResult {
panic!("Unknown scalar to service {}: {}", sender, opcode);
}
fn lend(&mut self, sender: u32, opcode: u32, _buf: &[u8], extra: [u32; 2]) -> [u32; 2] {
panic!("Unknown lend to service {}: {} ({:?})", sender, opcode, extra);
fn lend(&mut self, sender: u32, opcode: u32, _buf: &[u8], extra: [u32; 2]) -> LendResult {
panic!(
"Unknown lend to service {}: {} ({:?})",
sender, opcode, extra
);
}
fn lend_mut(&mut self, sender: u32, opcode: u32, _buf: &mut [u8], extra: [u32; 2]) -> [u32; 2] {
panic!("Unknown lend_mut to service {}: {} ({:?})", sender, opcode, extra);
/// Mutable lend messages may block
fn lend_mut(
&mut self,
sender: u32,
opcode: u32,
_buf: &mut [u8],
extra: [u32; 2],
) -> LendResult {
panic!(
"Unknown lend_mut to service {}: {} ({:?})",
sender, opcode, extra
);
}
/// Send-type messages return immediately, and memory is detached from the host process.
fn send(&mut self, sender: u32, opcode: u32, _buf: &[u8], extra: [u32; 2]) {
panic!("Unknown send to service {}: {} ({:?})", sender, opcode, extra);
panic!(
"Unknown send to service {}: {} ({:?})",
sender, opcode, extra
);
}
}

View File

@@ -1,4 +1,4 @@
use super::{ScalarResult, Service};
use super::{LendResult, ScalarResult, Service};
use std::io::Write;
enum LogLendOpcode {
@@ -28,11 +28,13 @@ impl Service for Log {
fn scalar(&mut self, sender: u32, opcode: u32, args: [u32; 4]) {
println!("Log scalar {}: {} {:x?}", sender, opcode, args);
}
fn blocking_scalar(&mut self, sender: u32, opcode: u32, args: [u32; 4]) -> ScalarResult {
println!("Log blocking_scalar {}: {} {:x?}", sender, opcode, args);
ScalarResult::Scalar1(0)
}
fn lend(&mut self, sender: u32, opcode: u32, buf: &[u8], extra: [u32; 2]) -> [u32; 2] {
fn lend(&mut self, sender: u32, opcode: u32, buf: &[u8], extra: [u32; 2]) -> LendResult {
if opcode == LogLendOpcode::StandardOutput as u32 {
let print_buffer = &buf[0..extra[1] as usize];
// println!("Log stdout:");
@@ -44,12 +46,20 @@ impl Service for Log {
} else {
panic!("Log lend {}: {} {:x?}", sender, opcode, buf);
}
[0, 0]
LendResult::MemoryReturned([0, 0])
}
fn lend_mut(&mut self, sender: u32, opcode: u32, _buf: &mut [u8], extra: [u32; 2]) -> [u32; 2] {
fn lend_mut(
&mut self,
sender: u32,
opcode: u32,
_buf: &mut [u8],
extra: [u32; 2],
) -> LendResult {
println!("Log lend_mut {}: {} {:x?}", sender, opcode, extra);
[0, 0]
LendResult::MemoryReturned([0, 0])
}
fn send(&mut self, sender: u32, opcode: u32, _buf: &[u8], extra: [u32; 2]) {
println!("Log send {}: {} {:x?}", sender, opcode, extra);
}

View File

@@ -1,10 +1,21 @@
use std::{
collections::HashMap,
sync::{atomic::AtomicUsize, Arc, Condvar, Mutex},
thread,
};
use super::LendResult;
pub struct Ticktimer {
start: std::time::SystemTime,
condvars: HashMap<usize, Arc<(Condvar, AtomicUsize)>>,
}
enum ScalarOpcode {
ElapsedMs = 0,
WaitForCondition = 8
WaitForCondition = 8,
NotifyCondition = 9,
FreeCondition = 11,
}
impl Ticktimer {
@@ -12,6 +23,7 @@ impl Ticktimer {
// println!("Constructing a ticktimer");
Ticktimer {
start: std::time::SystemTime::now(),
condvars: HashMap::new(),
}
}
}
@@ -23,9 +35,15 @@ impl Default for Ticktimer {
}
impl super::Service for Ticktimer {
fn scalar(&mut self, sender: u32, opcode: u32, args: [u32; 4]) {
println!("Ticktimer scalar {}: {} {:x?}", sender, opcode, args);
fn scalar(&mut self, _sender: u32, opcode: u32, args: [u32; 4]) {
if opcode == ScalarOpcode::FreeCondition as u32 {
let condition_index = args[0] as usize;
if let Some(condvar) = self.condvars.remove(&condition_index) {
assert!(condvar.1.load(std::sync::atomic::Ordering::Relaxed) == 0);
}
}
}
fn blocking_scalar(&mut self, sender: u32, opcode: u32, args: [u32; 4]) -> super::ScalarResult {
if opcode == ScalarOpcode::ElapsedMs as u32 {
let elapsed_ms = std::time::SystemTime::now()
@@ -34,21 +52,70 @@ impl super::Service for Ticktimer {
.as_millis() as u64;
super::ScalarResult::Scalar2([elapsed_ms as u32, (elapsed_ms >> 32) as u32])
} else if opcode == ScalarOpcode::WaitForCondition as u32 {
let start = std::time::SystemTime::now();
let mut elapsed_ms = start
.duration_since(self.start)
.unwrap()
.as_millis() as u64;
let mut condition = args[0];
while condition != 0 {
std::thread::sleep(std::time::Duration::from_millis(1));
elapsed_ms = start
.duration_since(self.start)
let condition_index = args[0] as usize;
let wait_count = args[1] as u64;
let (tx, rx) = std::sync::mpsc::channel();
let condvar = self
.condvars
.entry(condition_index)
.or_insert_with(|| Arc::new((Condvar::new(), AtomicUsize::new(0))))
.clone();
condvar.1.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
thread::spawn(move || {
let dummy_mutex = Mutex::new(());
let guard = dummy_mutex.lock().unwrap();
let timeout_value = if wait_count == 0 {
let _ignored = condvar.0.wait(guard).unwrap();
0
} else if condvar
.0
.wait_timeout(guard, std::time::Duration::from_millis(wait_count))
.unwrap()
.as_millis() as u64;
condition = args[0];
.1
.timed_out()
{
1
} else {
0
};
condvar.1.fetch_sub(1, std::sync::atomic::Ordering::Relaxed);
tx.send((
[
super::super::definitions::SyscallResultNumber::Scalar1 as i64,
timeout_value,
0,
0,
0,
0,
0,
0,
],
None,
))
.unwrap();
});
super::ScalarResult::WaitForResponse(rx)
} else if opcode == ScalarOpcode::NotifyCondition as u32 {
let condition_index = args[0] as usize;
let condition_count = args[1] as usize;
if condition_count == 0 || !self.condvars.contains_key(&condition_index) {
return super::ScalarResult::Scalar5([0, 0, 0, 0, 0]);
}
super::ScalarResult::Scalar2([elapsed_ms as u32, (elapsed_ms >> 32) as u32])
let mut notify_count = 0;
if let Some(condvar) = self.condvars.get(&condition_index) {
if condition_count == 0 {
notify_count = condvar.1.load(std::sync::atomic::Ordering::Relaxed);
condvar.0.notify_all();
} else {
for _ in 0..condition_count {
notify_count += 1;
condvar.0.notify_one();
}
}
}
super::ScalarResult::Scalar1(notify_count as u32)
} else {
panic!(
"Ticktimer blocking_scalar {}: {} {:x?}",
@@ -56,14 +123,23 @@ impl super::Service for Ticktimer {
);
}
}
fn lend(&mut self, sender: u32, opcode: u32, _buf: &[u8], extra: [u32; 2]) -> [u32; 2] {
fn lend(&mut self, sender: u32, opcode: u32, _buf: &[u8], extra: [u32; 2]) -> LendResult {
println!("Ticktimer lend {}: {} {:x?}", sender, opcode, extra);
[0, 0]
LendResult::MemoryReturned([0, 0])
}
fn lend_mut(&mut self, sender: u32, opcode: u32, _buf: &mut [u8], extra: [u32; 2]) -> [u32; 2] {
fn lend_mut(
&mut self,
sender: u32,
opcode: u32,
_buf: &mut [u8],
extra: [u32; 2],
) -> LendResult {
println!("Ticktimer lend_mut {}: {} {:x?}", sender, opcode, extra);
[0, 0]
LendResult::MemoryReturned([0, 0])
}
fn send(&mut self, sender: u32, opcode: u32, _buf: &[u8], extra: [u32; 2]) {
println!("Ticktimer send {}: {} {:x?}", sender, opcode, extra);
}