Fix bugs. Pass test 'spin'

- Fix ACK IRQ on x86.
- Add process exit handler.
master
WangRunji 6 years ago
parent ed20aa45fd
commit b7d6b2989d

@ -39,23 +39,17 @@ pub struct ProcessManager {
scheduler: Mutex<Box<Scheduler>>,
wait_queue: Vec<Mutex<Vec<Pid>>>,
event_hub: Mutex<EventHub<Event>>,
exit_handler: fn(Pid),
}
impl ProcessManager {
pub fn new(scheduler: Box<Scheduler>, max_proc_num: usize) -> Self {
pub fn new(scheduler: Box<Scheduler>, max_proc_num: usize, exit_handler: fn(Pid)) -> Self {
ProcessManager {
procs: {
let mut vec = Vec::new();
vec.resize_default(max_proc_num);
vec
},
procs: new_vec_default(max_proc_num),
scheduler: Mutex::new(scheduler),
wait_queue: {
let mut vec = Vec::new();
vec.resize_default(max_proc_num);
vec
},
wait_queue: new_vec_default(max_proc_num),
event_hub: Mutex::new(EventHub::new()),
exit_handler,
}
}
@ -124,7 +118,7 @@ impl ProcessManager {
proc.context = Some(context);
match proc.status {
Status::Ready => self.scheduler.lock().insert(pid),
Status::Exited(_) => proc.context = None,
Status::Exited(_) => self.exit_handler(pid, proc),
_ => {}
}
}
@ -152,7 +146,7 @@ impl ProcessManager {
_ => proc.status = status,
}
match proc.status {
Status::Exited(_) => proc.context = None,
Status::Exited(_) => self.exit_handler(pid, proc),
_ => {}
}
}
@ -189,8 +183,20 @@ impl ProcessManager {
pub fn exit(&self, pid: Pid, code: ExitCode) {
self.set_status(pid, Status::Exited(code));
}
/// Called when a process exit
fn exit_handler(&self, pid: Pid, proc: &mut Process) {
for waiter in self.wait_queue[pid].lock().drain(..) {
self.wakeup(waiter);
}
proc.context = None;
(self.exit_handler)(pid);
}
}
fn new_vec_default<T: Default>(size: usize) -> Vec<T> {
let mut vec = Vec::new();
vec.resize_default(size);
vec
}

@ -80,6 +80,7 @@ pub extern fn rust_trap(tf: &mut TrapFrame) {
T_PGFLT => page_fault(tf),
T_IRQ0...63 => {
let irq = tf.trap_num as u8 - T_IRQ0;
super::ack(irq); // must ack before switching
match irq {
IRQ_TIMER => ::trap::timer(),
IRQ_KBD => keyboard(),
@ -88,7 +89,6 @@ pub extern fn rust_trap(tf: &mut TrapFrame) {
IRQ_IDE => ide(),
_ => panic!("Invalid IRQ number: {}", irq),
}
super::ack(irq);
}
T_SWITCH_TOK => to_kernel(tf),
T_SWITCH_TOU => to_user(tf),

@ -12,7 +12,7 @@ mod context;
pub fn init() {
// NOTE: max_time_slice <= 5 to ensure 'priority' test pass
let scheduler = Box::new(scheduler::RRScheduler::new(5));
let manager = Arc::new(ProcessManager::new(scheduler, MAX_PROCESS_NUM));
let manager = Arc::new(ProcessManager::new(scheduler, MAX_PROCESS_NUM, Process::proc_exit));
extern fn idle(_arg: usize) -> ! {
loop { cpu::halt(); }

@ -91,6 +91,7 @@ fn sys_wait(pid: usize, code: *mut i32) -> i32 {
_ => {}
}
}
info!("wait: {} -> {}, sleep", thread::current().id(), pid);
if pid == 0 {
Process::wait_child();
} else {
@ -107,8 +108,8 @@ fn sys_yield() -> i32 {
/// Kill the process
fn sys_kill(pid: usize) -> i32 {
info!("kill: {}", pid);
processor().manager().exit(pid, 0x100);
Process::proc_exit(pid);
if pid == thread::current().id() {
processor().yield_now();
}
@ -123,8 +124,8 @@ fn sys_getpid() -> i32 {
/// Exit the current process
fn sys_exit(exit_code: usize) -> i32 {
let pid = thread::current().id();
info!("exit: {}", pid);
processor().manager().exit(pid, exit_code);
Process::proc_exit(pid);
processor().yield_now();
unreachable!();
}

Loading…
Cancel
Save