289 lines
9.3 KiB
Rust
289 lines
9.3 KiB
Rust
use std::rc::Rc;
|
|
|
|
use crate::simulator::{machine::{ExceptionType, Machine}, error::{MachineOk, MachineError}};
|
|
|
|
use super::system::System;
|
|
|
|
/// The halt system call. Stops Burritos.
|
|
pub const SC_SHUTDOWN: u8 = 0;
|
|
/// The exit system call
|
|
///
|
|
/// Ends the calling thread
|
|
pub const SC_EXIT: u8 = 1;
|
|
/// The exec system call
|
|
///
|
|
/// Creates a new process (thread+address space)
|
|
pub const SC_EXEC: u8 = 2;
|
|
/// The join system call
|
|
///
|
|
/// Wait for the thread idThread to finish
|
|
pub const SC_JOIN: u8 = 3;
|
|
/// The create system call
|
|
///
|
|
/// Create a new file in nachos file system
|
|
pub const SC_CREATE: u8 = 4;
|
|
/// The open system call
|
|
///
|
|
/// Opens a file and returns an openfile identifier
|
|
pub const SC_OPEN: u8 = 5;
|
|
/// The read system call
|
|
///
|
|
/// Read in a file or the console
|
|
pub const SC_READ: u8 = 6;
|
|
/// The write system call
|
|
///
|
|
/// Write in a file or at the console
|
|
pub const SC_WRITE: u8 = 7;
|
|
/// Seek to a given position in an opened file
|
|
pub const SC_SEEK: u8 = 8;
|
|
/// The close system call
|
|
///
|
|
/// Close a file
|
|
pub const SC_CLOSE: u8 = 9;
|
|
/// The newThread system call
|
|
///
|
|
/// Create a new thread in the same address space
|
|
pub const SC_NEW_THREAD: u8 = 10;
|
|
/// The Yield System call
|
|
///
|
|
/// Relinquish the CPU if any other thread is runnable
|
|
pub const SC_YIELD: u8 = 11;
|
|
/// the PError system call
|
|
///
|
|
/// print the last error message
|
|
pub const SC_PERROR: u8 = 12;
|
|
/// carry out P() on the semaphore
|
|
pub const SC_P: u8 = 13;
|
|
/// carry out V() on the semaphore
|
|
pub const SC_V: u8 = 14;
|
|
/// create a semaphore and add it in g_objects_addrs
|
|
pub const SC_SEM_CREATE: u8 = 15;
|
|
/// destroy the semaphore corresponding to the id
|
|
pub const SC_SEM_DESTROY: u8 = 16;
|
|
/// create a lock and add it to g_object_addrs
|
|
pub const SC_LOCK_CREATE: u8 = 17;
|
|
/// destroy the lock corresponding to the id
|
|
pub const SC_LOCK_DESTROY: u8 = 18;
|
|
/// carry out acquire() on the lock
|
|
pub const SC_LOCK_ACQUIRE: u8 = 19;
|
|
/// carry out release() on the lock
|
|
pub const SC_LOCK_RELEASE: u8 = 20;
|
|
/// create a condition variable and add it to g_object_addrs
|
|
pub const SC_COND_CREATE: u8 = 21;
|
|
/// destroy the condition variable corresponding to the id
|
|
pub const SC_COND_DESTROY: u8 = 22;
|
|
/// carry out wait() on the condition
|
|
pub const SC_COND_WAIT: u8 = 23;
|
|
/// carry out signal() on the condition
|
|
pub const SC_COND_SIGNAL: u8 = 24;
|
|
/// carry out broadcast() on the condition
|
|
pub const SC_COND_BROADCAST: u8 = 25;
|
|
/// the TtySend system call
|
|
///
|
|
/// Sends some char by the serial line emulated
|
|
pub const SC_TTY_SEND: u8 = 26;
|
|
/// the TtyReceive system call
|
|
///
|
|
/// read some char on the serial line
|
|
pub const SC_TTY_RECEIVE: u8 = 27;
|
|
/// the Mkdir system call
|
|
///
|
|
/// make a new directory in the file system
|
|
pub const SC_MKDIR: u8 = 28;
|
|
/// the Rmdir system call
|
|
///
|
|
/// remove a directory from the file system
|
|
pub const SC_RMDIR: u8 = 29;
|
|
/// The Remove system call
|
|
///
|
|
/// Remove a file from the file system
|
|
pub const SC_REMOVE: u8 = 30;
|
|
/// The FSList system call
|
|
///
|
|
/// Lists all the file and directories in the filesystem
|
|
pub const SC_FSLIST: u8 = 31;
|
|
// The systime system call. Gets the system time
|
|
pub const SC_SYS_TIME: u8 = 32;
|
|
/// Map a file in memory
|
|
pub const SC_MMAP: u8 = 33;
|
|
/// Behaviour undefined and currently unused
|
|
pub const SC_DEBUG: u8 = 34;
|
|
|
|
pub const CONSOLE_OUTPUT: u8 = 1;
|
|
|
|
// todo : returns new types, not just machine errors and machine ok
|
|
pub fn call(exception: &ExceptionType, machine: &mut Machine, system: &mut System) -> Result<MachineOk, MachineError> {
|
|
|
|
match exception {
|
|
ExceptionType::NoException => Err("No Exception no yet implemented")?,
|
|
ExceptionType::SyscallException => syscall(machine, system),
|
|
ExceptionType::PagefaultException => Err("Page Fault Exception not yet implemented")?,
|
|
ExceptionType::ReadOnlyException => Err("Read Only Exception not yet implemented")?,
|
|
ExceptionType::BusErrorException => Err("Bus Error Exception not yet implemented")?,
|
|
ExceptionType::AddressErrorException => Err("AddressErrorException not yet implemented")?,
|
|
ExceptionType::OverflowException => Err("OverflowException not yet implemented")?,
|
|
ExceptionType::IllegalInstrException => Err("IllegalInstrException not yet implemented")?,
|
|
ExceptionType::NumExceptionTypes => Err("NumExceptionTypes not yet implemented")?,
|
|
}
|
|
}
|
|
|
|
fn syscall(machine: &mut Machine, system: &mut System) -> Result<MachineOk, MachineError> {
|
|
let call_type = machine.read_int_register(17) as u8;
|
|
|
|
match call_type {
|
|
SC_SHUTDOWN => Ok(MachineOk::Shutdown),
|
|
SC_EXIT => {
|
|
let th = match &system.get_thread_manager().g_current_thread {
|
|
Some(th) => th.clone(),
|
|
None => Err("Current thread is None")?
|
|
};
|
|
system.get_thread_manager().thread_finish(machine, th);
|
|
Ok(MachineOk::Ok)
|
|
},
|
|
SC_EXEC => todo!(),
|
|
SC_JOIN => todo!(),
|
|
SC_CREATE => todo!(),
|
|
SC_OPEN => todo!(),
|
|
SC_READ => todo!(),
|
|
SC_WRITE => {
|
|
|
|
let address = machine.read_int_register(10);
|
|
let size = machine.read_int_register(11);
|
|
// openfileid or 1 (console)
|
|
let f = machine.read_int_register(12);
|
|
|
|
// load buffer
|
|
let mut buffer = "".to_string();
|
|
for i in 0..size {
|
|
buffer.push((machine.read_memory(1, (address + i) as usize)) as u8 as char);
|
|
}
|
|
|
|
if f as u8 == CONSOLE_OUTPUT {
|
|
println!("{}", buffer); // todo replace with console driver in the future
|
|
Ok(MachineOk::Ok)
|
|
} else {
|
|
Err("SC_WRITE to file is not yet implemented")?
|
|
}
|
|
},
|
|
SC_SEEK => todo!(),
|
|
SC_CLOSE => todo!(),
|
|
SC_NEW_THREAD => todo!(),
|
|
SC_YIELD => todo!(),
|
|
SC_PERROR => todo!(),
|
|
SC_P => todo!(),
|
|
SC_V => todo!(),
|
|
SC_SEM_CREATE => {
|
|
let addr_name = machine.read_int_register(10);
|
|
let initial_count = machine.read_int_register((11));
|
|
let size = get_length_param(addr_name as usize, machine);
|
|
let name = get_string_param(addr_name, size, machine);
|
|
|
|
if initial_count <0{
|
|
|
|
}
|
|
Ok(MachineOk::Ok)
|
|
|
|
},
|
|
SC_SEM_DESTROY => todo!(),
|
|
SC_LOCK_CREATE => todo!(),
|
|
SC_LOCK_DESTROY => todo!(),
|
|
SC_LOCK_ACQUIRE => todo!(),
|
|
SC_LOCK_RELEASE => todo!(),
|
|
SC_COND_CREATE => todo!(),
|
|
SC_COND_DESTROY => todo!(),
|
|
SC_COND_WAIT => todo!(),
|
|
SC_COND_SIGNAL => todo!(),
|
|
SC_COND_BROADCAST => todo!(),
|
|
SC_TTY_SEND => todo!(),
|
|
SC_TTY_RECEIVE => todo!(),
|
|
SC_MKDIR => todo!(),
|
|
SC_RMDIR => todo!(),
|
|
SC_REMOVE => todo!(),
|
|
SC_FSLIST => todo!(),
|
|
SC_SYS_TIME => todo!(),
|
|
SC_MMAP => todo!(),
|
|
SC_DEBUG => todo!(),
|
|
_ => todo!()
|
|
}
|
|
}
|
|
|
|
fn get_length_param(addr: usize, machine: & Machine) -> usize{
|
|
let mut i = 0;
|
|
let mut c = 1;
|
|
while c!= 0 {
|
|
c = machine.read_memory(1, addr + i);
|
|
i+=1;
|
|
|
|
}
|
|
i + 1
|
|
}
|
|
|
|
fn get_string_param(addr: i64, maxlen: usize, machine: &Machine) -> Vec<char>{
|
|
let mut dest = Vec::with_capacity(maxlen);
|
|
|
|
let mut i: usize = 0;
|
|
let mut c = 1;
|
|
|
|
while c != 0 && i < maxlen {
|
|
c = machine.read_memory(1, addr as usize + i) as u8;
|
|
//dest.push(c as char);
|
|
dest[i] = c as char;
|
|
i += 1;
|
|
}
|
|
|
|
dest[maxlen - 1] = '\0';
|
|
|
|
dest
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod test {
|
|
use crate::kernel::exception::{SC_SHUTDOWN, SC_WRITE};
|
|
use crate::kernel::system::System;
|
|
use crate::simulator::instruction::Instruction;
|
|
use crate::simulator::machine::Machine;
|
|
|
|
#[test]
|
|
fn test_sc_shutdown() {
|
|
let mut machine = Machine::init_machine();
|
|
machine.write_int_register(17, SC_SHUTDOWN as i64); // Set type to shutdown
|
|
let ecall = Instruction::new(0b000000000000_00000_000_00000_1110011);
|
|
|
|
machine.write_memory(4, 0, 0b000000000000_00000_000_00000_1110011); // ecall
|
|
machine.write_memory(4, 4, 0b000000001010_00000_000_00001_0010011); // r1 <- 10
|
|
let mut system = System::default();
|
|
machine.run(&mut system);
|
|
// If the machine was stopped with no error, the shutdown worked
|
|
assert_ne!(machine.read_int_register(1), 10); // Check if the next instruction was executed
|
|
}
|
|
|
|
// This test print HELLO in the console
|
|
#[test]
|
|
#[ignore]
|
|
fn test_sc_print() {
|
|
let mut machine = Machine::init_machine();
|
|
|
|
let address = machine.read_int_register(10);
|
|
// Write string 'HELLO' in memory
|
|
machine.write_memory(1, 4000, 72);
|
|
machine.write_memory(1, 4001, 69);
|
|
machine.write_memory(1, 4002, 76);
|
|
machine.write_memory(1, 4003, 76);
|
|
machine.write_memory(1, 4004, 79);
|
|
|
|
|
|
machine.write_int_register(10, 4000); // String address
|
|
machine.write_int_register(11, 5); // String size
|
|
machine.write_int_register(12, 1); // Console output
|
|
|
|
machine.write_memory(4, 0, 0b000000000000_00000_000_00000_1110011); // ecall
|
|
machine.write_int_register(17, SC_WRITE as i64); // Set type to write
|
|
|
|
machine.write_memory(4, 4, 0b000000000000_00000_000_10001_0010011); // r17 <- SC_SHUTDOWN
|
|
machine.write_memory(4, 8, 0b000000000000_00000_000_00000_1110011); // ecall
|
|
|
|
let mut system = System::default();
|
|
machine.run(&mut system);
|
|
}
|
|
|
|
} |