1
0
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:
WangRunji 2018-05-21 20:07:20 +08:00
parent a7f6ba2556
commit daac42ce8b
4 changed files with 50 additions and 44 deletions

View File

@ -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;
}

View File

@ -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();

View File

@ -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);
}
}

View File

@ -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
}