Split process mod to extern crate

master
WangRunji 7 years ago
parent 37a6df252f
commit c8a9eaf3e6

@ -0,0 +1,7 @@
[package]
name = "ucore-process"
version = "0.1.0"
authors = ["WangRunji <wangrunji0408@163.com>"]
[dependencies]
log = { git = "https://github.com/riscv-and-rust-and-decaf/log.git" }

@ -0,0 +1,61 @@
use alloc::BinaryHeap;
use core::cmp::{Ordering, PartialOrd};
type Time = usize;
struct Timer<T> {
time: Time,
data: T,
}
impl<T> PartialEq for Timer<T> {
fn eq(&self, other: &Self) -> bool {
self.time.eq(&other.time)
}
}
impl<T> Eq for Timer<T> {}
impl<T> PartialOrd for Timer<T> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
other.time.partial_cmp(&self.time)
}
}
impl<T> Ord for Timer<T> {
fn cmp(&self, other: &Self) -> Ordering {
self.partial_cmp(&other).unwrap()
}
}
pub struct EventHub<T> {
tick: Time,
timers: BinaryHeap<Timer<T>>,
}
impl<T> EventHub<T> {
pub fn new() -> Self {
EventHub {
tick: 0,
timers: BinaryHeap::new(),
}
}
pub fn tick(&mut self) {
self.tick += 1;
}
pub fn pop(&mut self) -> Option<T> {
match self.timers.peek() {
None => return None,
Some(timer) if timer.time != self.tick => return None,
_ => {}
};
self.timers.pop().map(|t| t.data)
}
pub fn push(&mut self, time_after: Time, data: T) {
let time = self.tick + time_after;
self.timers.push(Timer { time, data });
}
pub fn get_time(&self) -> Time {
self.tick
}
}

@ -0,0 +1,19 @@
#![no_std]
#![feature(alloc)]
#![feature(const_fn)]
#![feature(linkage)]
#![feature(universal_impl_trait, conservative_impl_trait)]
extern crate alloc;
#[macro_use]
extern crate log;
// To use `println!` in test
#[cfg(test)]
#[macro_use]
extern crate std;
pub mod processor;
pub mod scheduler;
mod util;
mod event_hub;

@ -1,15 +1,15 @@
use alloc::BTreeMap; use alloc::{boxed::Box, BTreeMap};
use core::fmt::{Debug, Error, Formatter}; use scheduler::*;
use super::context::*; use event_hub::EventHub;
use super::scheduler::*; use util::GetMut2;
use util::{EventHub, GetMut2}; use core::fmt::Debug;
#[derive(Debug)] #[derive(Debug)]
pub struct Process { pub struct Process<T> {
pid: Pid, pid: Pid,
parent: Pid, parent: Pid,
status: Status, status: Status,
context: Context, context: T,
} }
pub type Pid = usize; pub type Pid = usize;
@ -24,17 +24,21 @@ pub enum Status {
Exited(ErrorCode), Exited(ErrorCode),
} }
pub struct Processor { pub trait Context: Debug {
procs: BTreeMap<Pid, Process>, unsafe fn switch(&mut self, target: &mut Self);
}
pub struct Processor_<T: Context, S: Scheduler> {
procs: BTreeMap<Pid, Process<T>>,
current_pid: Pid, current_pid: Pid,
event_hub: EventHub<Event>, event_hub: EventHub<Event>,
/// Choose what on next schedule ? /// Choose what on next schedule ?
next: Option<Pid>, next: Option<Pid>,
// WARNING: if MAX_PROCESS_NUM is too large, will cause stack overflow // WARNING: if MAX_PROCESS_NUM is too large, will cause stack overflow
scheduler: RRScheduler, scheduler: S,
} }
impl Process { impl<T> Process<T> {
fn exit_code(&self) -> Option<ErrorCode> { fn exit_code(&self) -> Option<ErrorCode> {
match self.status { match self.status {
Status::Exited(code) => Some(code), Status::Exited(code) => Some(code),
@ -44,30 +48,29 @@ impl Process {
} }
// TODO: 除schedule()外的其它函数应该只设置进程状态不应调用schedule // TODO: 除schedule()外的其它函数应该只设置进程状态不应调用schedule
impl Processor { impl<T: Context, S: Scheduler> Processor_<T, S> {
pub fn new(init_context: Context) -> Self { pub fn new(init_context: T, scheduler: S) -> Self {
let init_proc = Process { let init_proc = Process {
pid: 0, pid: 0,
parent: 0, parent: 0,
status: Status::Running, status: Status::Running,
context: init_context, context: init_context,
}; };
Processor { Processor_ {
procs: { procs: {
let mut map = BTreeMap::<Pid, Process>::new(); let mut map = BTreeMap::<Pid, Process<T>>::new();
map.insert(0, init_proc); map.insert(0, init_proc);
map map
}, },
current_pid: 0, current_pid: 0,
event_hub: EventHub::new(), event_hub: EventHub::new(),
next: None, next: None,
// NOTE: max_time_slice <= 5 to ensure 'priority' test pass scheduler,
scheduler: RRScheduler::new(5),
} }
} }
pub fn lab6_set_priority(&mut self, priority: u8) { pub fn set_priority(&mut self, priority: u8) {
// self.scheduler.set_priority(self.current_pid, priority); self.scheduler.set_priority(self.current_pid, priority);
} }
pub fn set_reschedule(&mut self) { pub fn set_reschedule(&mut self) {
@ -127,7 +130,7 @@ impl Processor {
self.event_hub.get_time() self.event_hub.get_time()
} }
pub fn add(&mut self, context: Context) -> Pid { pub fn add(&mut self, context: T) -> Pid {
let pid = self.alloc_pid(); let pid = self.alloc_pid();
let process = Process { let process = Process {
pid, pid,
@ -173,22 +176,16 @@ impl Processor {
self.scheduler.remove(pid); self.scheduler.remove(pid);
info!("switch from {} to {} {:x?}", pid0, pid, to.context); info!("switch from {} to {} {:x?}", pid0, pid, to.context);
unsafe { unsafe { from.context.switch(&mut to.context); }
// FIXME: safely pass MutexGuard
use core::mem::forget;
super::PROCESSOR.try().unwrap().force_unlock();
from.context.switch(&mut to.context);
forget(super::processor());
}
} }
fn get(&self, pid: Pid) -> &Process { fn get(&self, pid: Pid) -> &Process<T> {
self.procs.get(&pid).unwrap() self.procs.get(&pid).unwrap()
} }
fn get_mut(&mut self, pid: Pid) -> &mut Process { fn get_mut(&mut self, pid: Pid) -> &mut Process<T> {
self.procs.get_mut(&pid).unwrap() self.procs.get_mut(&pid).unwrap()
} }
pub fn current_context(&self) -> &Context { pub fn current_context(&self) -> &T {
&self.get(self.current_pid).context &self.get(self.current_pid).context
} }
pub fn current_pid(&self) -> Pid { pub fn current_pid(&self) -> Pid {
@ -270,9 +267,9 @@ enum Event {
Wakeup(Pid), Wakeup(Pid),
} }
impl GetMut2<Pid> for BTreeMap<Pid, Process> { impl<T: Context> GetMut2<Pid> for BTreeMap<Pid, Process<T>> {
type Output = Process; type Output = Process<T>;
fn get_mut(&mut self, id: Pid) -> &mut Process { fn get_mut(&mut self, id: Pid) -> &mut Process<T> {
self.get_mut(&id).unwrap() self.get_mut(&id).unwrap()
} }
} }

@ -1,13 +1,15 @@
use super::*;
use consts::MAX_PROCESS_NUM;
use alloc::BinaryHeap; use alloc::BinaryHeap;
type Pid = usize;
const MAX_PROCESS_NUM: usize = 32;
/// ///
pub trait Scheduler { pub trait Scheduler {
fn insert(&mut self, pid: Pid); fn insert(&mut self, pid: Pid);
fn remove(&mut self, pid: Pid); fn remove(&mut self, pid: Pid);
fn select(&mut self) -> Option<Pid>; fn select(&mut self) -> Option<Pid>;
fn tick(&mut self, current: Pid) -> bool; // need reschedule? fn tick(&mut self, current: Pid) -> bool; // need reschedule?
fn set_priority(&mut self, pid: Pid, priority: u8);
} }
pub use self::rr::RRScheduler; pub use self::rr::RRScheduler;
@ -73,6 +75,9 @@ mod rr {
} }
*rest == 0 *rest == 0
} }
fn set_priority(&mut self, pid: usize, priority: u8) {
}
} }
impl RRScheduler { impl RRScheduler {
@ -177,6 +182,11 @@ mod stride {
} }
*rest == 0 *rest == 0
} }
fn set_priority(&mut self, pid: Pid, priority: u8) {
self.infos[pid].priority = priority;
debug!("{} priority = {}", pid, priority);
}
} }
impl StrideScheduler { impl StrideScheduler {
@ -187,9 +197,5 @@ mod stride {
queue: BinaryHeap::new(), queue: BinaryHeap::new(),
} }
} }
pub fn set_priority(&mut self, pid: Pid, priority: u8) {
self.infos[pid].priority = priority;
debug!("{} priority = {}", pid, priority);
}
} }
} }

@ -0,0 +1,15 @@
use core::fmt::Debug;
/// Get values by 2 diff keys at the same time
pub trait GetMut2<Idx: Debug + Eq> {
type Output;
fn get_mut(&mut self, id: Idx) -> &mut Self::Output;
fn get_mut2(&mut self, id1: Idx, id2: Idx) -> (&mut Self::Output, &mut Self::Output) {
assert_ne!(id1, id2);
let self1 = self as *mut Self;
let self2 = self1;
let p1 = unsafe { &mut *self1 }.get_mut(id1);
let p2 = unsafe { &mut *self2 }.get_mut(id2);
(p1, p2)
}
}

8
kernel/Cargo.lock generated

@ -138,6 +138,7 @@ dependencies = [
"spin 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "spin 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"uart_16550 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "uart_16550 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ucore-memory 0.1.0", "ucore-memory 0.1.0",
"ucore-process 0.1.0",
"volatile 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "volatile 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"x86_64 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "x86_64 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"xmas-elf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "xmas-elf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -175,6 +176,13 @@ dependencies = [
name = "ucore-memory" name = "ucore-memory"
version = "0.1.0" version = "0.1.0"
[[package]]
name = "ucore-process"
version = "0.1.0"
dependencies = [
"log 0.4.3 (git+https://github.com/riscv-and-rust-and-decaf/log.git)",
]
[[package]] [[package]]
name = "usize_conversions" name = "usize_conversions"
version = "0.2.0" version = "0.2.0"

@ -36,6 +36,7 @@ volatile = "0.1.0"
lazy_static = { version = "1.0.0", features = ["spin_no_std"] } lazy_static = { version = "1.0.0", features = ["spin_no_std"] }
bit-allocator = { path = "../crate/bit-allocator" } bit-allocator = { path = "../crate/bit-allocator" }
ucore-memory = { path = "../crate/memory" } ucore-memory = { path = "../crate/memory" }
ucore-process = { path = "../crate/process" }
simple-filesystem = { git = "https://github.com/wangrunji0408/SimpleFileSystem-Rust" } simple-filesystem = { git = "https://github.com/wangrunji0408/SimpleFileSystem-Rust" }
[target.x86_64-blog_os.dependencies] [target.x86_64-blog_os.dependencies]

@ -40,6 +40,7 @@ extern crate compiler_builtins;
extern crate simple_filesystem; extern crate simple_filesystem;
extern crate spin; extern crate spin;
extern crate ucore_memory; extern crate ucore_memory;
extern crate ucore_process;
extern crate volatile; extern crate volatile;
#[macro_use] #[macro_use]
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]

@ -8,10 +8,16 @@ pub struct Context {
memory_set: MemorySet, memory_set: MemorySet,
} }
impl Context { impl ::ucore_process::processor::Context for Context {
pub unsafe fn switch(&mut self, target: &mut Self) { unsafe fn switch(&mut self, target: &mut Self) {
super::PROCESSOR.try().unwrap().force_unlock();
self.arch.switch(&mut target.arch); self.arch.switch(&mut target.arch);
use core::mem::forget;
forget(super::processor());
} }
}
impl Context {
pub unsafe fn new_init() -> Self { pub unsafe fn new_init() -> Self {
Context { Context {

@ -1,16 +1,20 @@
use alloc::String;
pub use self::context::*;
pub use self::processor::*;
use spin::Once; use spin::Once;
use sync::{SpinNoIrqLock, Mutex, MutexGuard, SpinNoIrq}; use sync::{SpinNoIrqLock, Mutex, MutexGuard, SpinNoIrq};
pub use self::context::Context;
pub use ucore_process::processor::*;
pub use ucore_process::scheduler::*;
mod context; mod context;
mod processor;
mod scheduler; type Processor = Processor_<Context, StrideScheduler>;
pub fn init() { pub fn init() {
PROCESSOR.call_once(|| PROCESSOR.call_once(||
SpinNoIrqLock::new(Processor::new(unsafe { Context::new_init() })) SpinNoIrqLock::new(Processor::new(
unsafe { Context::new_init() },
// NOTE: max_time_slice <= 5 to ensure 'priority' test pass
StrideScheduler::new(5),
))
); );
} }

@ -117,7 +117,7 @@ fn sys_get_time() -> i32 {
fn sys_lab6_set_priority(priority: usize) -> i32 { fn sys_lab6_set_priority(priority: usize) -> i32 {
let mut processor = processor(); let mut processor = processor();
processor.lab6_set_priority(priority as u8); processor.set_priority(priority as u8);
0 0
} }

@ -1,5 +1,4 @@
use core::fmt::Debug; use core::fmt::Debug;
pub use self::event::EventHub;
pub fn bytes_sum<T>(p: &T) -> u8 { pub fn bytes_sum<T>(p: &T) -> u8 {
use core::mem::size_of_val; use core::mem::size_of_val;
@ -28,82 +27,3 @@ pub unsafe fn from_cstr(s: *const u8) -> &'static str {
let len = (0usize..).find(|&i| *s.offset(i as isize) == 0).unwrap(); let len = (0usize..).find(|&i| *s.offset(i as isize) == 0).unwrap();
str::from_utf8(slice::from_raw_parts(s, len)).unwrap() str::from_utf8(slice::from_raw_parts(s, len)).unwrap()
} }
/// Get values by 2 diff keys at the same time
pub trait GetMut2<Idx: Debug + Eq> {
type Output;
fn get_mut(&mut self, id: Idx) -> &mut Self::Output;
fn get_mut2(&mut self, id1: Idx, id2: Idx) -> (&mut Self::Output, &mut Self::Output) {
assert_ne!(id1, id2);
let self1 = self as *mut Self;
let self2 = self1;
let p1 = unsafe { &mut *self1 }.get_mut(id1);
let p2 = unsafe { &mut *self2 }.get_mut(id2);
(p1, p2)
}
}
mod event {
use alloc::BinaryHeap;
use core::cmp::{Ordering, PartialOrd};
type Time = usize;
struct Timer<T> {
time: Time,
data: T,
}
impl<T> PartialEq for Timer<T> {
fn eq(&self, other: &Self) -> bool {
self.time.eq(&other.time)
}
}
impl<T> Eq for Timer<T> {}
impl<T> PartialOrd for Timer<T> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
other.time.partial_cmp(&self.time)
}
}
impl<T> Ord for Timer<T> {
fn cmp(&self, other: &Self) -> Ordering {
self.partial_cmp(&other).unwrap()
}
}
pub struct EventHub<T> {
tick: Time,
timers: BinaryHeap<Timer<T>>,
}
impl<T> EventHub<T> {
pub fn new() -> Self {
EventHub {
tick: 0,
timers: BinaryHeap::new(),
}
}
pub fn tick(&mut self) {
self.tick += 1;
}
pub fn pop(&mut self) -> Option<T> {
match self.timers.peek() {
None => return None,
Some(timer) if timer.time != self.tick => return None,
_ => {}
};
self.timers.pop().map(|t| t.data)
}
pub fn push(&mut self, time_after: Time, data: T) {
let time = self.tick + time_after;
self.timers.push(Timer { time, data });
}
pub fn get_time(&self) -> Time {
self.tick
}
}
}
Loading…
Cancel
Save