Split process mod to extern crate

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

@ -1,13 +1,15 @@
use super::*;
use consts::MAX_PROCESS_NUM;
use alloc::BinaryHeap;
type Pid = usize;
const MAX_PROCESS_NUM: usize = 32;
///
pub trait Scheduler {
fn insert(&mut self, pid: Pid);
fn remove(&mut self, pid: Pid);
fn select(&mut self) -> Option<Pid>;
fn tick(&mut self, current: Pid) -> bool; // need reschedule?
fn set_priority(&mut self, pid: Pid, priority: u8);
}
pub use self::rr::RRScheduler;
@ -73,6 +75,9 @@ mod rr {
}
*rest == 0
}
fn set_priority(&mut self, pid: usize, priority: u8) {
}
}
impl RRScheduler {
@ -177,6 +182,11 @@ mod stride {
}
*rest == 0
}
fn set_priority(&mut self, pid: Pid, priority: u8) {
self.infos[pid].priority = priority;
debug!("{} priority = {}", pid, priority);
}
}
impl StrideScheduler {
@ -187,9 +197,5 @@ mod stride {
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)",
"uart_16550 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ucore-memory 0.1.0",
"ucore-process 0.1.0",
"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)",
"xmas-elf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -175,6 +176,13 @@ dependencies = [
name = "ucore-memory"
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]]
name = "usize_conversions"
version = "0.2.0"

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

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

@ -8,10 +8,16 @@ pub struct Context {
memory_set: MemorySet,
}
impl Context {
pub unsafe fn switch(&mut self, target: &mut Self) {
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 {
pub unsafe fn new_init() -> Self {
Context {

@ -1,16 +1,20 @@
use alloc::String;
pub use self::context::*;
pub use self::processor::*;
use spin::Once;
use sync::{SpinNoIrqLock, Mutex, MutexGuard, SpinNoIrq};
pub use self::context::Context;
pub use ucore_process::processor::*;
pub use ucore_process::scheduler::*;
mod context;
mod processor;
mod scheduler;
type Processor = Processor_<Context, StrideScheduler>;
pub fn init() {
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 {
let mut processor = processor();
processor.lab6_set_priority(priority as u8);
processor.set_priority(priority as u8);
0
}

@ -1,5 +1,4 @@
use core::fmt::Debug;
pub use self::event::EventHub;
pub fn bytes_sum<T>(p: &T) -> u8 {
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();
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