mirror of
https://github.com/rcore-os/rCore.git
synced 2024-11-23 00:16:17 +04:00
Merge all schedule operations to one at the end of interrupt handling.
This commit is contained in:
parent
a7f6ba2556
commit
daac42ce8b
@ -25,8 +25,6 @@ use super::TrapFrame;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn rust_trap(tf: &mut TrapFrame) -> usize {
|
||||
let mut rsp = tf as *const _ as usize;
|
||||
|
||||
// Dispatch
|
||||
match tf.trap_num as u8 {
|
||||
T_BRKPT => breakpoint(),
|
||||
@ -36,7 +34,7 @@ pub extern fn rust_trap(tf: &mut TrapFrame) -> usize {
|
||||
T_IRQ0...64 => {
|
||||
let irq = tf.trap_num as u8 - T_IRQ0;
|
||||
match irq {
|
||||
IRQ_TIMER => timer(tf, &mut rsp),
|
||||
IRQ_TIMER => timer(),
|
||||
IRQ_KBD => keyboard(),
|
||||
IRQ_COM1 => com1(),
|
||||
IRQ_COM2 => com2(),
|
||||
@ -50,11 +48,15 @@ pub extern fn rust_trap(tf: &mut TrapFrame) -> usize {
|
||||
}
|
||||
T_SWITCH_TOK => to_kernel(tf),
|
||||
T_SWITCH_TOU => to_user(tf),
|
||||
T_SYSCALL => syscall(tf, &mut rsp),
|
||||
0x80 => syscall32(tf, &mut rsp),
|
||||
T_SYSCALL => syscall(tf),
|
||||
T_SYSCALL32 => syscall32(tf),
|
||||
_ => panic!("Unhandled interrupt {:x}", tf.trap_num),
|
||||
}
|
||||
|
||||
let mut rsp = tf as *const _ as usize;
|
||||
use process::PROCESSOR;
|
||||
PROCESSOR.try().unwrap().lock().schedule(&mut rsp);
|
||||
|
||||
// Set return rsp if to user
|
||||
let tf = unsafe { &*(rsp as *const TrapFrame) };
|
||||
set_return_rsp(tf);
|
||||
@ -115,9 +117,10 @@ fn com2() {
|
||||
COM2.lock().receive();
|
||||
}
|
||||
|
||||
fn timer(tf: &mut TrapFrame, rsp: &mut usize) {
|
||||
use process;
|
||||
process::timer_handler(tf, rsp);
|
||||
fn timer() {
|
||||
use process::PROCESSOR;
|
||||
let mut processor = PROCESSOR.try().unwrap().lock();
|
||||
processor.tick();
|
||||
}
|
||||
|
||||
fn to_user(tf: &mut TrapFrame) {
|
||||
@ -135,17 +138,17 @@ fn to_kernel(tf: &mut TrapFrame) {
|
||||
tf.ss = gdt::KDATA_SELECTOR.0 as usize;
|
||||
}
|
||||
|
||||
fn syscall(tf: &mut TrapFrame, rsp: &mut usize) {
|
||||
fn syscall(tf: &mut TrapFrame) {
|
||||
info!("\nInterupt: Syscall {:#x?}", tf.rax);
|
||||
use syscall::syscall;
|
||||
let ret = syscall(tf, rsp, false);
|
||||
let ret = syscall(tf, false);
|
||||
tf.rax = ret as usize;
|
||||
}
|
||||
|
||||
fn syscall32(tf: &mut TrapFrame, rsp: &mut usize) {
|
||||
fn syscall32(tf: &mut TrapFrame) {
|
||||
// info!("\nInterupt: Syscall {:#x?}", tf.rax);
|
||||
use syscall::syscall;
|
||||
let ret = syscall(tf, rsp, true);
|
||||
let ret = syscall(tf, true);
|
||||
tf.rax = ret as usize;
|
||||
}
|
||||
|
||||
|
@ -36,11 +36,6 @@ extern fn idle_thread() {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn timer_handler(tf: &TrapFrame, rsp: &mut usize) {
|
||||
let mut processor = PROCESSOR.try().unwrap().lock();
|
||||
processor.tick(rsp);
|
||||
}
|
||||
|
||||
pub fn add_user_process(name: impl AsRef<str>, data: &[u8]) {
|
||||
let mut processor = PROCESSOR.try().unwrap().lock();
|
||||
let mut mc = MC.try().unwrap().lock();
|
||||
|
@ -12,6 +12,8 @@ pub struct Processor {
|
||||
/// All kernel threads share one page table.
|
||||
/// When running user process, it will be stored here.
|
||||
kernel_page_table: Option<InactivePageTable>,
|
||||
/// Choose what on next schedule ?
|
||||
next: Option<Pid>,
|
||||
}
|
||||
|
||||
impl Processor {
|
||||
@ -25,9 +27,15 @@ impl Processor {
|
||||
e
|
||||
},
|
||||
kernel_page_table: None,
|
||||
next: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_reschedule(&mut self) {
|
||||
let pid = self.current_pid;
|
||||
self.get_mut(pid).status = Status::Ready;
|
||||
}
|
||||
|
||||
fn alloc_pid(&self) -> Pid {
|
||||
let mut next: Pid = 0;
|
||||
for &i in self.procs.keys() {
|
||||
@ -42,18 +50,19 @@ impl Processor {
|
||||
|
||||
/// Called by timer.
|
||||
/// Handle events.
|
||||
pub fn tick(&mut self, rsp: &mut usize) {
|
||||
pub fn tick(&mut self) {
|
||||
self.event_hub.tick();
|
||||
while let Some(event) = self.event_hub.pop() {
|
||||
debug!("Processor: event {:?}", event);
|
||||
match event {
|
||||
Event::Schedule => {
|
||||
self.event_hub.push(10, Event::Schedule);
|
||||
self.schedule(rsp);
|
||||
self.set_reschedule();
|
||||
},
|
||||
Event::Wakeup(pid) => {
|
||||
self.get_mut(pid).status = Status::Ready;
|
||||
self.switch_to(pid, rsp);
|
||||
self.set_reschedule();
|
||||
self.next = Some(pid);
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -70,8 +79,13 @@ impl Processor {
|
||||
pid
|
||||
}
|
||||
|
||||
/// Called every interrupt end
|
||||
/// Do schedule ONLY IF current status != Running
|
||||
pub fn schedule(&mut self, rsp: &mut usize) {
|
||||
let pid = self.find_next();
|
||||
if self.current().status == Status::Running {
|
||||
return;
|
||||
}
|
||||
let pid = self.next.take().unwrap_or_else(|| self.find_next());
|
||||
self.switch_to(pid, rsp);
|
||||
}
|
||||
|
||||
@ -84,7 +98,7 @@ impl Processor {
|
||||
|
||||
/// Switch process to `pid`, switch page table if necessary.
|
||||
/// Store `rsp` and point it to target kernel stack.
|
||||
/// The current status will be set to `Ready` if it is `Running` now.
|
||||
/// The current status must be set before, and not be `Running`.
|
||||
fn switch_to(&mut self, pid: Pid, rsp: &mut usize) {
|
||||
// for debug print
|
||||
let pid0 = self.current_pid;
|
||||
@ -98,9 +112,7 @@ impl Processor {
|
||||
let (from, to) = self.procs.get_mut2(pid0, pid);
|
||||
|
||||
// set `from`
|
||||
if from.status == Status::Running {
|
||||
from.status = Status::Ready;
|
||||
}
|
||||
assert_ne!(from.status, Status::Running);
|
||||
from.rsp = *rsp;
|
||||
|
||||
// set `to`
|
||||
@ -144,7 +156,6 @@ impl Processor {
|
||||
}
|
||||
|
||||
pub fn exit(&mut self, pid: Pid, error_code: ErrorCode) {
|
||||
assert_ne!(pid, self.current_pid);
|
||||
info!("Processor: {} exit, code: {}", pid, error_code);
|
||||
self.get_mut(pid).status = Status::Exited(error_code);
|
||||
if let Some(waiter) = self.find_waiter(pid) {
|
||||
@ -153,8 +164,10 @@ impl Processor {
|
||||
p.status = Status::Ready;
|
||||
p.set_return_value(error_code);
|
||||
}
|
||||
info!("Processor: remove {}", pid);
|
||||
self.procs.remove(&pid);
|
||||
// FIXME: remove this process
|
||||
self.get_mut(pid).parent = 0;
|
||||
// info!("Processor: remove {}", pid);
|
||||
// self.procs.remove(&pid);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@ use util;
|
||||
/// 当发生系统调用中断时,中断服务例程将控制权转移到这里。
|
||||
/// 它从中断帧中提取参数,根据系统调用号分发执行具体操作。
|
||||
/// 它同时支持 xv6的64位程序 和 uCore的32位程序。
|
||||
pub fn syscall(tf: &TrapFrame, rsp: &mut usize, is32: bool) -> i32 {
|
||||
pub fn syscall(tf: &TrapFrame, is32: bool) -> i32 {
|
||||
let id = match is32 {
|
||||
false => Syscall::Xv6(tf.rax),
|
||||
true => Syscall::Ucore(tf.rax),
|
||||
@ -29,19 +29,19 @@ pub fn syscall(tf: &TrapFrame, rsp: &mut usize, is32: bool) -> i32 {
|
||||
Syscall::Xv6(SYS_CLOSE) | Syscall::Ucore(UCORE_SYS_CLOSE) =>
|
||||
sys_close(args[0]),
|
||||
Syscall::Xv6(SYS_WAIT) | Syscall::Ucore(UCORE_SYS_WAIT) =>
|
||||
sys_wait(rsp, args[0], args[1] as *mut i32),
|
||||
sys_wait(args[0], args[1] as *mut i32),
|
||||
Syscall::Xv6(SYS_FORK) | Syscall::Ucore(UCORE_SYS_FORK) =>
|
||||
sys_fork(tf),
|
||||
Syscall::Xv6(SYS_KILL) | Syscall::Ucore(UCORE_SYS_KILL) =>
|
||||
sys_kill(args[0]),
|
||||
Syscall::Xv6(SYS_EXIT) | Syscall::Ucore(UCORE_SYS_EXIT) =>
|
||||
sys_exit(rsp, args[0]),
|
||||
sys_exit(args[0]),
|
||||
Syscall::Ucore(UCORE_SYS_YIELD) =>
|
||||
sys_yield(rsp),
|
||||
sys_yield(),
|
||||
Syscall::Ucore(UCORE_SYS_GETPID) =>
|
||||
sys_getpid(),
|
||||
Syscall::Ucore(UCORE_SYS_SLEEP) =>
|
||||
sys_sleep(rsp, args[0]),
|
||||
sys_sleep(args[0]),
|
||||
Syscall::Ucore(UCORE_SYS_GETTIME) =>
|
||||
sys_get_time(),
|
||||
Syscall::Ucore(UCORE_SYS_PUTC) =>
|
||||
@ -92,7 +92,7 @@ fn sys_fork(tf: &TrapFrame) -> i32 {
|
||||
|
||||
/// Wait the process exit.
|
||||
/// Return the PID. Store exit code to `code` if it's not null.
|
||||
fn sys_wait(rsp: &mut usize, pid: usize, code: *mut i32) -> i32 {
|
||||
fn sys_wait(pid: usize, code: *mut i32) -> i32 {
|
||||
let mut processor = PROCESSOR.try().unwrap().lock();
|
||||
let target = match pid {
|
||||
0 => WaitTarget::AnyChild,
|
||||
@ -105,18 +105,15 @@ fn sys_wait(rsp: &mut usize, pid: usize, code: *mut i32) -> i32 {
|
||||
}
|
||||
0 // pid as i32
|
||||
},
|
||||
WaitResult::Blocked => {
|
||||
processor.schedule(rsp);
|
||||
0 /* unused */
|
||||
},
|
||||
WaitResult::Blocked => 0, // unused
|
||||
WaitResult::NotExist => -1,
|
||||
}
|
||||
}
|
||||
|
||||
fn sys_yield(rsp: &mut usize) -> i32 {
|
||||
fn sys_yield() -> i32 {
|
||||
info!("yield:");
|
||||
let mut processor = PROCESSOR.try().unwrap().lock();
|
||||
processor.schedule(rsp);
|
||||
processor.set_reschedule();
|
||||
0
|
||||
}
|
||||
|
||||
@ -132,19 +129,17 @@ fn sys_getpid() -> i32 {
|
||||
}
|
||||
|
||||
/// Exit the current process
|
||||
fn sys_exit(rsp: &mut usize, error_code: usize) -> i32 {
|
||||
fn sys_exit(error_code: usize) -> i32 {
|
||||
let mut processor = PROCESSOR.try().unwrap().lock();
|
||||
let pid = processor.current_pid();
|
||||
processor.schedule(rsp);
|
||||
processor.exit(pid, error_code);
|
||||
0
|
||||
}
|
||||
|
||||
fn sys_sleep(rsp: &mut usize, time: usize) -> i32 {
|
||||
fn sys_sleep(time: usize) -> i32 {
|
||||
info!("sleep: {} ticks", time);
|
||||
let mut processor = PROCESSOR.try().unwrap().lock();
|
||||
let pid = processor.current_pid();
|
||||
processor.schedule(rsp);
|
||||
processor.sleep(pid, time);
|
||||
0
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user