Multicore processing WORKS! Basically ...

- Rewrite processor.rs
  Refactor to `Processor` & `ProcessManager`
- Use Box<dyn> instead of generic.
- Wait/sleep/wakeup is not supported yet.
  I'm considering to implement them with WaitQueue.
toolchain_update
WangRunji 6 years ago
parent 6741ba399b
commit f7eb09e856

@ -5,3 +5,4 @@ authors = ["WangRunji <wangrunji0408@163.com>"]
[dependencies]
log = "0.4"
spin = "0.4"

@ -5,6 +5,7 @@
extern crate alloc;
#[macro_use]
extern crate log;
extern crate spin;
// To use `println!` in test
#[cfg(test)]

@ -1,273 +1,208 @@
use alloc::{boxed::Box, collections::BTreeMap};
use scheduler::*;
use event_hub::EventHub;
use util::GetMut2;
use core::fmt::Debug;
#[derive(Debug)]
pub struct Process<T> {
pid: Pid,
parent: Pid,
status: Status,
context: T,
use alloc::boxed::Box;
use alloc::vec::Vec;
use alloc::sync::Arc;
use spin::Mutex;
use scheduler::Scheduler;
use core::cell::UnsafeCell;
/// Process executor
///
/// Per-CPU struct. Defined at global.
/// Only accessed by associated CPU with interrupt disabled.
#[derive(Default)]
pub struct Processor {
inner: UnsafeCell<Option<ProcessorInner>>,
}
pub type Pid = usize;
pub type ErrorCode = usize;
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum Status {
Ready,
Running,
Waiting(Pid),
Sleeping,
Exited(ErrorCode),
}
unsafe impl Sync for Processor {}
pub trait Context: Debug {
unsafe fn switch(&mut self, target: &mut Self);
fn new_kernel(entry: extern fn(usize) -> !, arg: usize) -> Self;
struct ProcessorInner {
id: usize,
proc: Option<(Pid, Box<Context>)>,
loop_context: Box<Context>,
manager: Arc<ProcessManager>,
}
pub struct Processor_<T: Context, S: Scheduler> {
procs: BTreeMap<Pid, Process<T>>,
current_pid: Pid,
event_hub: EventHub<Event>,
// WARNING: if MAX_PROCESS_NUM is too large, will cause stack overflow
scheduler: S,
}
impl<T> Process<T> {
fn exit_code(&self) -> Option<ErrorCode> {
match self.status {
Status::Exited(code) => Some(code),
_ => None,
}
impl Processor {
pub const fn new() -> Self {
Processor { inner: UnsafeCell::new(None) }
}
}
// TODO: 除schedule()外的其它函数应该只设置进程状态不应调用schedule
impl<T: Context, S: Scheduler> Processor_<T, S> {
pub fn new(init_context: T, scheduler: S) -> Self {
let init_proc = Process {
pid: 0,
parent: 0,
status: Status::Running,
context: init_context,
};
Processor_ {
procs: {
let mut map = BTreeMap::<Pid, Process<T>>::new();
map.insert(0, init_proc);
map
},
current_pid: 0,
event_hub: EventHub::new(),
scheduler,
pub unsafe fn init(&self, id: usize, context: Box<Context>, manager: Arc<ProcessManager>) {
unsafe {
*self.inner.get() = Some(ProcessorInner {
id,
proc: None,
loop_context: context,
manager,
});
}
}
pub fn set_priority(&mut self, priority: u8) {
self.scheduler.set_priority(self.current_pid, priority);
}
pub fn yield_now(&mut self) {
let pid = self.current_pid;
self.set_status(pid, Status::Ready);
}
fn alloc_pid(&self) -> Pid {
let mut next: Pid = 0;
for &i in self.procs.keys() {
if i != next {
return next;
} else {
next = i + 1;
fn inner(&self) -> &mut ProcessorInner {
unsafe { &mut *self.inner.get() }.as_mut()
.expect("Processor is not initialized")
}
/// Begin running processes after CPU setup.
///
/// This function never returns. It loops, doing:
/// - choose a process to run
/// - switch to start running that process
/// - eventually that process transfers control
/// via switch back to the scheduler.
pub fn run(&self) -> ! {
let inner = self.inner();
loop {
let proc = inner.manager.run(inner.id);
trace!("CPU{} begin running process {}", inner.id, proc.0);
inner.proc = Some(proc);
unsafe {
inner.loop_context.switch_to(&mut *inner.proc.as_mut().unwrap().1);
}
let (pid, context) = inner.proc.take().unwrap();
trace!("CPU{} stop running process {}", inner.id, pid);
inner.manager.stop(pid, context);
}
return next;
}
fn set_status(&mut self, pid: Pid, status: Status) {
let status0 = self.get(pid).status.clone();
match (&status0, &status) {
(&Status::Ready, &Status::Ready) => return,
(&Status::Ready, _) => self.scheduler.remove(pid),
(_, &Status::Ready) => self.scheduler.insert(pid),
_ => {}
/// Called by process running on this Processor.
/// Yield and reschedule.
pub fn yield_now(&self) {
let inner = self.inner();
unsafe {
inner.proc.as_mut().unwrap().1.switch_to(&mut *inner.loop_context);
}
trace!("process {} {:?} -> {:?}", pid, status0, status);
self.get_mut(pid).status = status;
}
/// Called by timer.
/// Handle events.
pub fn tick(&mut self) {
let current_pid = self.current_pid;
if self.scheduler.tick(current_pid) {
self.yield_now();
}
self.event_hub.tick();
while let Some(event) = self.event_hub.pop() {
debug!("event {:?}", event);
match event {
Event::Schedule => {
self.event_hub.push(10, Event::Schedule);
self.yield_now();
},
Event::Wakeup(pid) => {
self.set_status(pid, Status::Ready);
self.yield_now();
self.scheduler.move_to_head(pid);
},
}
}
pub fn pid(&self) -> Pid {
self.inner().proc.as_ref().unwrap().0
}
pub fn get_time(&self) -> usize {
self.event_hub.get_time()
pub fn manager(&self) -> &ProcessManager {
&*self.inner().manager
}
pub fn add(&mut self, context: T) -> Pid {
let pid = self.alloc_pid();
let process = Process {
pid,
parent: self.current_pid,
status: Status::Ready,
context,
};
self.scheduler.insert(pid);
self.procs.insert(pid, process);
pid
}
/// Called every interrupt end
/// Do schedule ONLY IF current status != Running
pub fn schedule(&mut self) {
if self.get(self.current_pid).status == Status::Running {
return;
pub fn tick(&self) {
let need_reschedule = self.manager().tick(self.pid());
if need_reschedule {
self.yield_now();
}
let pid = self.scheduler.select().unwrap();
self.switch_to(pid);
}
}
/// Switch to process `pid`.
/// The current status must be set before, and not be `Running`.
/// The target status must be `Ready`.
fn switch_to(&mut self, pid: Pid) {
// for debug print
let pid0 = self.current_pid;
if pid == self.current_pid {
if self.get(self.current_pid).status != Status::Running {
self.set_status(pid, Status::Running);
}
return;
}
self.current_pid = pid;
struct Process {
id: Pid,
status: Status,
status_after_stop: Status,
context: Option<Box<Context>>,
}
let (from, to) = self.procs.get_mut2(pid0, pid);
type Pid = usize;
type ExitCode = usize;
const MAX_PROC_NUM: usize = 32;
assert_ne!(from.status, Status::Running);
assert_eq!(to.status, Status::Ready);
to.status = Status::Running;
self.scheduler.remove(pid);
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum Status {
Ready,
Running(usize),
Waiting(Pid),
Sleeping,
Exited(ExitCode),
}
info!("switch from {} to {} {:x?}", pid0, pid, to.context);
unsafe { from.context.switch(&mut to.context); }
}
pub trait Context {
unsafe fn switch_to(&mut self, target: &mut Context);
}
fn get(&self, pid: Pid) -> &Process<T> {
self.procs.get(&pid).unwrap()
}
fn get_mut(&mut self, pid: Pid) -> &mut Process<T> {
self.procs.get_mut(&pid).unwrap()
}
pub fn current_context(&self) -> &T {
&self.get(self.current_pid).context
}
pub fn current_pid(&self) -> Pid {
self.current_pid
}
pub struct ProcessManager {
procs: [Mutex<Option<Process>>; MAX_PROC_NUM],
scheduler: Mutex<Box<Scheduler>>,
}
pub fn kill(&mut self, pid: Pid) {
self.exit(pid, 0x1000); // TODO: error code for killed
}
impl ProcessManager {
pub fn exit(&mut self, pid: Pid, error_code: ErrorCode) {
info!("{} exit, code: {}", pid, error_code);
self.set_status(pid, Status::Exited(error_code));
if let Some(waiter) = self.find_waiter(pid) {
info!(" then wakeup {}", waiter);
self.set_status(waiter, Status::Ready);
self.scheduler.move_to_head(waiter);
pub fn new(scheduler: Box<Scheduler>) -> Self {
ProcessManager {
procs: Default::default(),
scheduler: Mutex::new(scheduler),
}
}
pub fn sleep(&mut self, pid: Pid, time: usize) {
self.set_status(pid, Status::Sleeping);
self.event_hub.push(time, Event::Wakeup(pid));
}
pub fn sleep_(&mut self, pid: Pid) {
self.set_status(pid, Status::Sleeping);
}
pub fn wakeup_(&mut self, pid: Pid) {
self.set_status(pid, Status::Ready);
fn alloc_pid(&self) -> Pid {
for i in 0..MAX_PROC_NUM {
if self.procs[i].lock().is_none() {
return i;
}
}
panic!("Process number exceeded");
}
/// Let current process wait for another
pub fn current_wait_for(&mut self, pid: Pid) -> WaitResult {
info!("current {} wait for {:?}", self.current_pid, pid);
if self.procs.values().filter(|&p| p.parent == self.current_pid).next().is_none() {
return WaitResult::NotExist;
}
let pid = self.try_wait(pid).unwrap_or_else(|| {
let current_pid = self.current_pid;
self.set_status(current_pid, Status::Waiting(pid));
self.schedule(); // yield
self.try_wait(pid).unwrap()
/// Add a new process
pub fn add(&self, context: Box<Context>) -> Pid {
let pid = self.alloc_pid();
// TODO: check parent
*self.procs[pid].lock() = Some(Process {
id: pid,
status: Status::Ready,
status_after_stop: Status::Ready,
context: Some(context),
});
let exit_code = self.get(pid).exit_code().unwrap();
info!("{} wait end and remove {}", self.current_pid, pid);
self.procs.remove(&pid);
WaitResult::Ok(pid, exit_code)
self.scheduler.lock().insert(pid);
pid
}
/// Try to find a exited wait target
fn try_wait(&mut self, pid: Pid) -> Option<Pid> {
match pid {
0 => self.procs.values()
.find(|&p| p.parent == self.current_pid && p.exit_code().is_some())
.map(|p| p.pid),
_ => self.get(pid).exit_code().map(|_| pid),
/// Make process `pid` time slice -= 1.
/// Return true if time slice == 0.
/// Called by timer interrupt handler.
pub fn tick(&self, pid: Pid) -> bool {
self.scheduler.lock().tick(pid)
}
/// Called by Processor to get a process to run.
/// The manager first mark it `Running`,
/// then take out and return its Context.
pub fn run(&self, cpu_id: usize) -> (Pid, Box<Context>) {
let mut scheduler = self.scheduler.lock();
let pid = scheduler.select()
.expect("failed to select a runnable process");
scheduler.remove(pid);
let mut proc_lock = self.procs[pid].lock();
let mut proc = proc_lock.as_mut().unwrap();
proc.status = Status::Running(cpu_id);
(pid, proc.context.take().unwrap())
}
/// Called by Processor to finish running a process
/// and give its context back.
pub fn stop(&self, pid: Pid, context: Box<Context>) {
let mut proc_lock = self.procs[pid].lock();
let mut proc = proc_lock.as_mut().unwrap();
proc.status = proc.status_after_stop.clone();
proc.status_after_stop = Status::Ready;
proc.context = Some(context);
if proc.status == Status::Ready {
self.scheduler.lock().insert(pid);
}
}
fn find_waiter(&self, pid: Pid) -> Option<Pid> {
self.procs.values().find(|&p| {
p.status == Status::Waiting(pid) ||
(p.status == Status::Waiting(0) && self.get(pid).parent == p.pid)
}).map(|ref p| p.pid)
}
}
#[derive(Debug)]
pub enum WaitResult {
/// The target process is exited with `ErrorCode`.
Ok(Pid, ErrorCode),
/// The target process is not exist.
NotExist,
}
#[derive(Debug)]
enum Event {
Schedule,
Wakeup(Pid),
}
impl<T: Context> GetMut2<Pid> for BTreeMap<Pid, Process<T>> {
type Output = Process<T>;
fn get_mut(&mut self, id: Pid) -> &mut Process<T> {
self.get_mut(&id).unwrap()
/// Switch the status of a process.
/// Insert/Remove it to/from scheduler if necessary.
pub fn set_status(&self, pid: Pid, status: Status) {
let mut scheduler = self.scheduler.lock();
let mut proc_lock = self.procs[pid].lock();
let mut proc = proc_lock.as_mut().unwrap();
match (&proc.status, &status) {
(Status::Ready, Status::Ready) => return,
(Status::Ready, _) => scheduler.remove(pid),
(Status::Running(_), _) => {},
(_, Status::Ready) => scheduler.insert(pid),
_ => {}
}
trace!("process {} {:?} -> {:?}", pid, proc.status, status);
match proc.status {
Status::Running(_) => proc.status_after_stop = status,
_ => proc.status = status,
}
}
}

@ -38,10 +38,8 @@ use scheduler::Scheduler;
/// All dependencies for thread mod.
pub trait ThreadSupport {
type Context: Context;
type Scheduler: Scheduler;
type ProcessorGuard: DerefMut<Target=Processor_<Self::Context, Self::Scheduler>>;
fn processor() -> Self::ProcessorGuard;
fn processor() -> &'static Processor;
fn new_kernel(entry: extern fn(usize) -> !, arg: usize) -> Box<Context>;
}
/// Root structure served as thread mod
@ -53,7 +51,7 @@ impl<S: ThreadSupport> ThreadMod<S> {
/// Gets a handle to the thread that invokes it.
pub fn current() -> Thread<S> {
Thread {
pid: S::processor().current_pid(),
pid: S::processor().pid(),
mark: PhantomData,
}
}
@ -62,10 +60,8 @@ impl<S: ThreadSupport> ThreadMod<S> {
pub fn sleep(dur: Duration) {
let time = dur_to_ticks(dur);
info!("sleep: {:?} ticks", time);
let mut processor = S::processor();
let pid = processor.current_pid();
processor.sleep(pid, time);
processor.schedule();
// TODO: register wakeup
Self::park();
fn dur_to_ticks(dur: Duration) -> usize {
return dur.as_secs() as usize * 100 + dur.subsec_nanos() as usize / 10_000_000;
@ -111,16 +107,17 @@ impl<S: ThreadSupport> ThreadMod<S> {
// unsafe { LocalKey::<usize>::get_map() }.clear();
// 让Processor退出当前线程
// 把f返回值在堆上的指针以线程返回码的形式传递出去
let mut processor = S::processor();
let pid = processor.current_pid();
processor.exit(pid, Box::into_raw(ret) as usize);
processor.schedule();
let pid = S::processor().pid();
let exit_code = Box::into_raw(ret) as usize;
S::processor().manager().set_status(pid, Status::Exited(exit_code));
S::processor().yield_now();
// 再也不会被调度回来了
unreachable!()
}
// 在Processor中创建新的线程
let pid = S::processor().add(Context::new_kernel(kernel_thread_entry::<S, F, T>, f as usize));
let context = S::new_kernel(kernel_thread_entry::<S, F, T>, f as usize);
let pid = S::processor().manager().add(context);
// 接下来看看`JoinHandle::join()`的实现
// 了解是如何获取f返回值的
@ -133,18 +130,15 @@ impl<S: ThreadSupport> ThreadMod<S> {
/// Cooperatively gives up a timeslice to the OS scheduler.
pub fn yield_now() {
info!("yield:");
let mut processor = S::processor();
processor.yield_now();
processor.schedule();
S::processor().yield_now();
}
/// Blocks unless or until the current thread's token is made available.
pub fn park() {
info!("park:");
let mut processor = S::processor();
let pid = processor.current_pid();
processor.sleep_(pid);
processor.schedule();
let pid = S::processor().pid();
S::processor().manager().set_status(pid, Status::Sleeping);
S::processor().yield_now();
}
}
@ -157,8 +151,7 @@ pub struct Thread<S: ThreadSupport> {
impl<S: ThreadSupport> Thread<S> {
/// Atomically makes the handle's token available if it is not already.
pub fn unpark(&self) {
let mut processor = S::processor();
processor.wakeup_(self.pid);
S::processor().manager().set_status(self.pid, Status::Ready);
}
/// Gets the thread's unique identifier.
pub fn id(&self) -> usize {
@ -179,14 +172,8 @@ impl<S: ThreadSupport, T> JoinHandle<S, T> {
}
/// Waits for the associated thread to finish.
pub fn join(self) -> Result<T, ()> {
let mut processor = S::processor();
match processor.current_wait_for(self.thread.pid) {
WaitResult::Ok(_, exit_code) => unsafe {
// Find return value on the heap from the exit code.
Ok(*Box::from_raw(exit_code as *mut T))
}
WaitResult::NotExist => Err(()),
}
// TODO: wait for the thread
unimplemented!()
}
}

1
kernel/Cargo.lock generated

@ -285,6 +285,7 @@ name = "ucore-process"
version = "0.1.0"
dependencies = [
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"spin 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]

@ -57,6 +57,5 @@ fn other_start() -> ! {
idt::init();
gdt::init();
cpu::init();
// unsafe{ let a = *(0xdeadbeaf as *const u8); } // Page fault
loop {}
::kmain();
}

@ -46,8 +46,8 @@ pub fn shell() {
if let Ok(file) = root.borrow().lookup(name.as_str()) {
use process::*;
let len = file.borrow().read_at(0, &mut *buf).unwrap();
let pid = processor().add(Context::new_user(&buf[..len]));
processor().current_wait_for(pid);
processor().manager().add(ContextImpl::new_user(&buf[..len]));
// TODO: wait for new process
} else {
println!("Program not exist");
}

@ -9,6 +9,7 @@
#![feature(panic_info_message)]
#![feature(global_asm)]
#![feature(compiler_builtins_lib)]
#![feature(raw)]
#![no_std]
@ -61,18 +62,18 @@ pub mod arch;
pub mod arch;
pub fn kmain() -> ! {
process::init();
unsafe { arch::interrupt::enable(); }
if arch::cpu::id() == 0 {
process::init();
thread::spawn(fs::shell);
}
fs::shell();
process::processor().run();
// thread::test::local_key();
// thread::test::unpack();
// sync::test::philosopher_using_mutex();
// sync::test::philosopher_using_monitor();
// sync::mpsc::test::test_all();
loop {}
}
/// Global heap allocator

@ -2,39 +2,45 @@ use arch::interrupt::{TrapFrame, Context as ArchContext};
use memory::{MemoryArea, MemoryAttr, MemorySet};
use xmas_elf::{ElfFile, header, program::{Flags, ProgramHeader, Type}};
use core::fmt::{Debug, Error, Formatter};
use ucore_process::processor::Context;
use alloc::boxed::Box;
pub struct Context {
pub struct ContextImpl {
arch: ArchContext,
memory_set: MemorySet,
}
impl ::ucore_process::processor::Context for Context {
unsafe fn switch(&mut self, target: &mut Self) {
super::PROCESSOR.try().unwrap().force_unlock();
self.arch.switch(&mut target.arch);
use core::mem::forget;
forget(super::processor());
}
impl Context for ContextImpl {
unsafe fn switch_to(&mut self, target: &mut Context) {
use core::raw::TraitObject;
use core::mem::transmute;
fn new_kernel(entry: extern fn(usize) -> !, arg: usize) -> Self {
let ms = MemorySet::new();
Context {
arch: unsafe { ArchContext::new_kernel_thread(entry, arg, ms.kstack_top(), ms.token()) },
memory_set: ms,
}
// Cast &mut Context -> &mut ContextImpl
let raw: TraitObject = transmute(target);
let target = &mut *(raw.data as *mut ContextImpl);
self.arch.switch(&mut target.arch);
}
}
impl Context {
pub unsafe fn new_init() -> Self {
Context {
impl ContextImpl {
pub unsafe fn new_init() -> Box<Context> {
Box::new(ContextImpl {
arch: ArchContext::null(),
memory_set: MemorySet::new(),
}
})
}
pub fn new_kernel(entry: extern fn(usize) -> !, arg: usize) -> Box<Context> {
let ms = MemorySet::new();
Box::new(ContextImpl {
arch: unsafe { ArchContext::new_kernel_thread(entry, arg, ms.kstack_top(), ms.token()) },
memory_set: ms,
})
}
/// Make a new user thread from ELF data
pub fn new_user(data: &[u8]) -> Self {
pub fn new_user(data: &[u8]) -> Box<Context> {
// Parse elf
let elf = ElfFile::new(data).expect("failed to read elf");
let is32 = match elf.header.pt2 {
@ -81,17 +87,17 @@ impl Context {
});
}
Context {
Box::new(ContextImpl {
arch: unsafe {
ArchContext::new_user_thread(
entry_addr, user_stack_top - 8, memory_set.kstack_top(), is32, memory_set.token())
},
memory_set,
}
})
}
/// Fork
pub fn fork(&self, tf: &TrapFrame) -> Self {
pub fn fork(&self, tf: &TrapFrame) -> Box<Context> {
// Clone memory set, make a new page table
let memory_set = self.memory_set.clone();
@ -110,14 +116,14 @@ impl Context {
});
}
Context {
Box::new(ContextImpl {
arch: unsafe { ArchContext::new_fork(tf, memory_set.kstack_top(), memory_set.token()) },
memory_set,
}
})
}
}
impl Debug for Context {
impl Debug for ContextImpl {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
write!(f, "{:x?}", self.arch)
}

@ -1,36 +1,41 @@
use spin::Once;
use sync::{SpinNoIrqLock, Mutex, MutexGuard, SpinNoIrq};
pub use self::context::Context;
pub use ucore_process::processor::{*, Context as _whatever};
pub use self::context::ContextImpl;
pub use ucore_process::processor::*;
pub use ucore_process::scheduler::*;
pub use ucore_process::thread::*;
use alloc::boxed::Box;
use consts::MAX_CPU_NUM;
use arch::cpu;
use alloc::sync::Arc;
use alloc::vec::Vec;
mod context;
type Processor = Processor_<Context, StrideScheduler>;
pub fn init() {
PROCESSOR.call_once(||
SpinNoIrqLock::new({
let mut processor = Processor::new(
unsafe { Context::new_init() },
// NOTE: max_time_slice <= 5 to ensure 'priority' test pass
StrideScheduler::new(5),
);
extern fn idle(arg: usize) -> ! {
loop {}
}
processor.add(Context::new_kernel(idle, 0));
processor
})
);
// NOTE: max_time_slice <= 5 to ensure 'priority' test pass
let scheduler = Box::new(RRScheduler::new(5));
let manager = Arc::new(ProcessManager::new(scheduler));
extern fn idle(_arg: usize) -> ! {
loop { cpu::halt(); }
}
for i in 0..MAX_CPU_NUM {
manager.add(ContextImpl::new_kernel(idle, i));
}
unsafe {
for cpu_id in 0..MAX_CPU_NUM {
PROCESSORS[cpu_id].init(cpu_id, ContextImpl::new_init(), manager.clone());
}
}
info!("process init end");
}
pub static PROCESSOR: Once<SpinNoIrqLock<Processor>> = Once::new();
static PROCESSORS: [Processor; MAX_CPU_NUM] = [Processor::new(), Processor::new(), Processor::new(), Processor::new(), Processor::new(), Processor::new(), Processor::new(), Processor::new()];
pub fn processor() -> MutexGuard<'static, Processor, SpinNoIrq> {
PROCESSOR.try().unwrap().lock()
pub fn processor() -> &'static Processor {
&PROCESSORS[cpu::id()]
}
#[allow(non_camel_case_types)]
@ -43,11 +48,10 @@ pub mod thread_ {
pub struct ThreadSupportImpl;
impl ThreadSupport for ThreadSupportImpl {
type Context = Context;
type Scheduler = StrideScheduler;
type ProcessorGuard = MutexGuard<'static, Processor, SpinNoIrq>;
fn processor() -> Self::ProcessorGuard {
fn processor() -> &'static Processor {
processor()
}
fn new_kernel(entry: extern fn(usize) -> !, arg: usize) -> Box<Context> {
ContextImpl::new_kernel(entry, arg)
}
}

@ -58,26 +58,13 @@ fn sys_close(fd: usize) -> i32 {
/// Fork the current process. Return the child's PID.
fn sys_fork(tf: &TrapFrame) -> i32 {
let mut processor = processor();
let context = processor.current_context().fork(tf);
let pid = processor.add(context);
info!("fork: {} -> {}", processor.current_pid(), pid);
pid as i32
unimplemented!();
}
/// Wait the process exit.
/// Return the PID. Store exit code to `code` if it's not null.
fn sys_wait(pid: usize, code: *mut i32) -> i32 {
let mut processor = processor();
match processor.current_wait_for(pid) {
WaitResult::Ok(pid, error_code) => {
if !code.is_null() {
unsafe { *code = error_code as i32 };
}
0
}
WaitResult::NotExist => -1,
}
unimplemented!();
}
fn sys_yield() -> i32 {
@ -87,7 +74,7 @@ fn sys_yield() -> i32 {
/// Kill the process
fn sys_kill(pid: usize) -> i32 {
processor().kill(pid);
processor().manager().set_status(pid, Status::Exited(0x100));
0
}
@ -97,10 +84,10 @@ fn sys_getpid() -> i32 {
}
/// Exit the current process
fn sys_exit(error_code: usize) -> i32 {
let mut processor = processor();
let pid = processor.current_pid();
processor.exit(pid, error_code);
fn sys_exit(exit_code: usize) -> i32 {
let pid = processor().pid();
processor().manager().set_status(pid, Status::Exited(exit_code));
processor().yield_now();
0
}
@ -111,13 +98,11 @@ fn sys_sleep(time: usize) -> i32 {
}
fn sys_get_time() -> i32 {
let processor = processor();
processor.get_time() as i32
unimplemented!();
}
fn sys_lab6_set_priority(priority: usize) -> i32 {
let mut processor = processor();
processor.set_priority(priority as u8);
unimplemented!();
0
}

@ -1,26 +1,19 @@
use process::*;
use arch::interrupt::TrapFrame;
use arch::cpu;
pub fn timer() {
let mut processor = processor();
processor.tick();
processor().tick();
}
pub fn before_return() {
if let Some(processor) = PROCESSOR.try() {
processor.lock().schedule();
}
}
pub fn error(tf: &TrapFrame) -> ! {
if let Some(processor) = PROCESSOR.try() {
let mut processor = processor.lock();
let pid = processor.current_pid();
error!("Process {} error:\n{:#x?}", pid, tf);
processor.exit(pid, 0x100); // TODO: Exit code for error
processor.schedule();
unreachable!();
} else {
panic!("Exception when processor not inited\n{:#x?}", tf);
}
let pid = processor().pid();
error!("On CPU{} Process {}:\n{:#x?}", cpu::id(), pid, tf);
processor().manager().set_status(pid, Status::Exited(0x100));
processor().yield_now();
unreachable!();
}
Loading…
Cancel
Save