rename 'process' crate to 'thread'

toolchain_update
WangRunji 6 years ago
parent 238de1b282
commit 5bffce787b

@ -1,7 +1,8 @@
[package] [package]
name = "rcore-process" name = "rcore-thread"
version = "0.1.0" version = "0.1.0"
authors = ["WangRunji <wangrunji0408@163.com>"] authors = ["WangRunji <wangrunji0408@163.com>"]
description = "Bare-metal thread scheduler and executor"
edition = "2018" edition = "2018"
[dependencies] [dependencies]

@ -1,3 +1,5 @@
//! Enable and disable interrupt for each architecture.
#[inline(always)] #[inline(always)]
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
pub unsafe fn disable_and_store() -> usize { pub unsafe fn disable_and_store() -> usize {

@ -9,12 +9,12 @@
extern crate alloc; extern crate alloc;
mod process_manager; mod thread_pool;
mod processor; mod processor;
pub mod scheduler; pub mod scheduler;
pub mod thread; pub mod std_thread;
mod event_hub; mod event_hub;
mod interrupt; mod interrupt;
pub use crate::process_manager::*; pub use crate::thread_pool::*;
pub use crate::processor::Processor; pub use crate::processor::Processor;

@ -2,10 +2,10 @@ use alloc::boxed::Box;
use alloc::sync::Arc; use alloc::sync::Arc;
use log::*; use log::*;
use core::cell::UnsafeCell; use core::cell::UnsafeCell;
use crate::process_manager::*; use crate::thread_pool::*;
use crate::interrupt; use crate::interrupt;
/// Process executor /// Thread executor
/// ///
/// Per-CPU struct. Defined at global. /// Per-CPU struct. Defined at global.
/// Only accessed by associated CPU with interrupt disabled. /// Only accessed by associated CPU with interrupt disabled.
@ -18,9 +18,9 @@ unsafe impl Sync for Processor {}
struct ProcessorInner { struct ProcessorInner {
id: usize, id: usize,
proc: Option<(Pid, Box<Context>)>, proc: Option<(Tid, Box<Context>)>,
loop_context: Box<Context>, loop_context: Box<Context>,
manager: Arc<ProcessManager>, manager: Arc<ThreadPool>,
} }
impl Processor { impl Processor {
@ -28,7 +28,7 @@ impl Processor {
Processor { inner: UnsafeCell::new(None) } Processor { inner: UnsafeCell::new(None) }
} }
pub unsafe fn init(&self, id: usize, context: Box<Context>, manager: Arc<ProcessManager>) { pub unsafe fn init(&self, id: usize, context: Box<Context>, manager: Arc<ThreadPool>) {
*self.inner.get() = Some(ProcessorInner { *self.inner.get() = Some(ProcessorInner {
id, id,
proc: None, proc: None,
@ -76,7 +76,7 @@ impl Processor {
} }
} }
pub fn pid(&self) -> Pid { pub fn tid(&self) -> Tid {
self.inner().proc.as_ref().unwrap().0 self.inner().proc.as_ref().unwrap().0
} }
@ -84,13 +84,13 @@ impl Processor {
&*self.inner().proc.as_ref().unwrap().1 &*self.inner().proc.as_ref().unwrap().1
} }
pub fn manager(&self) -> &ProcessManager { pub fn manager(&self) -> &ThreadPool {
&*self.inner().manager &*self.inner().manager
} }
pub fn tick(&self) { pub fn tick(&self) {
let flags = unsafe { interrupt::disable_and_store() }; let flags = unsafe { interrupt::disable_and_store() };
let need_reschedule = self.manager().tick(self.pid()); let need_reschedule = self.manager().tick(self.tid());
unsafe { interrupt::restore(flags); } unsafe { interrupt::restore(flags); }
if need_reschedule { if need_reschedule {

@ -1,4 +1,4 @@
//! Thread std-like interface //! `std::thread`-like interface
//! //!
//! Based on Processor. Used in kernel. //! Based on Processor. Used in kernel.
//! //!
@ -11,7 +11,7 @@ use core::marker::PhantomData;
use core::time::Duration; use core::time::Duration;
use log::*; use log::*;
use crate::processor::*; use crate::processor::*;
use crate::process_manager::*; use crate::thread_pool::*;
#[linkage = "weak"] #[linkage = "weak"]
#[no_mangle] #[no_mangle]
@ -30,7 +30,7 @@ fn new_kernel_context(_entry: extern fn(usize) -> !, _arg: usize) -> Box<Context
/// Gets a handle to the thread that invokes it. /// Gets a handle to the thread that invokes it.
pub fn current() -> Thread { pub fn current() -> Thread {
Thread { pid: processor().pid() } Thread { pid: processor().tid() }
} }
/// Puts the current thread to sleep for the specified amount of time. /// Puts the current thread to sleep for the specified amount of time.
@ -160,7 +160,7 @@ impl<T> JoinHandle<T> {
} }
} }
/// Force construct a JoinHandle struct /// Force construct a JoinHandle struct
pub unsafe fn _of(pid: Pid) -> JoinHandle<T> { pub unsafe fn _of(pid: Tid) -> JoinHandle<T> {
JoinHandle { JoinHandle {
thread: Thread { pid }, thread: Thread { pid },
mark: PhantomData, mark: PhantomData,

@ -5,17 +5,15 @@ use log::*;
use crate::scheduler::Scheduler; use crate::scheduler::Scheduler;
use crate::event_hub::EventHub; use crate::event_hub::EventHub;
struct Process { struct Thread {
#[allow(dead_code)]
id: Pid,
status: Status, status: Status,
status_after_stop: Status, status_after_stop: Status,
context: Option<Box<Context>>, context: Option<Box<Context>>,
parent: Pid, parent: Tid,
children: Vec<Pid>, children: Vec<Tid>,
} }
pub type Pid = usize; pub type Tid = usize;
type ExitCode = usize; type ExitCode = usize;
#[derive(Debug, Clone, Eq, PartialEq)] #[derive(Debug, Clone, Eq, PartialEq)]
@ -23,37 +21,37 @@ pub enum Status {
Ready, Ready,
Running(usize), Running(usize),
Sleeping, Sleeping,
Waiting(Pid), Waiting(Tid),
/// aka ZOMBIE. Its context was dropped. /// aka ZOMBIE. Its context was dropped.
Exited(ExitCode), Exited(ExitCode),
} }
#[derive(Eq, PartialEq)] #[derive(Eq, PartialEq)]
enum Event { enum Event {
Wakeup(Pid), Wakeup(Tid),
} }
pub trait Context { pub trait Context {
unsafe fn switch_to(&mut self, target: &mut Context); unsafe fn switch_to(&mut self, target: &mut Context);
} }
pub struct ProcessManager { pub struct ThreadPool {
procs: Vec<Mutex<Option<Process>>>, threads: Vec<Mutex<Option<Thread>>>,
scheduler: Mutex<Box<Scheduler>>, scheduler: Mutex<Box<Scheduler>>,
event_hub: Mutex<EventHub<Event>>, event_hub: Mutex<EventHub<Event>>,
} }
impl ProcessManager { impl ThreadPool {
pub fn new(scheduler: Box<Scheduler>, max_proc_num: usize) -> Self { pub fn new(scheduler: Box<Scheduler>, max_proc_num: usize) -> Self {
ProcessManager { ThreadPool {
procs: new_vec_default(max_proc_num), threads: new_vec_default(max_proc_num),
scheduler: Mutex::new(scheduler), scheduler: Mutex::new(scheduler),
event_hub: Mutex::new(EventHub::new()), event_hub: Mutex::new(EventHub::new()),
} }
} }
fn alloc_pid(&self) -> Pid { fn alloc_tid(&self) -> Tid {
for (i, proc) in self.procs.iter().enumerate() { for (i, proc) in self.threads.iter().enumerate() {
if proc.lock().is_none() { if proc.lock().is_none() {
return i; return i;
} }
@ -62,82 +60,81 @@ impl ProcessManager {
} }
/// Add a new process /// Add a new process
pub fn add(&self, context: Box<Context>, parent: Pid) -> Pid { pub fn add(&self, context: Box<Context>, parent: Tid) -> Tid {
let pid = self.alloc_pid(); let tid = self.alloc_tid();
*(&self.procs[pid]).lock() = Some(Process { *(&self.threads[tid]).lock() = Some(Thread {
id: pid,
status: Status::Ready, status: Status::Ready,
status_after_stop: Status::Ready, status_after_stop: Status::Ready,
context: Some(context), context: Some(context),
parent, parent,
children: Vec::new(), children: Vec::new(),
}); });
self.scheduler.lock().insert(pid); self.scheduler.lock().insert(tid);
self.procs[parent].lock().as_mut().expect("invalid parent proc") self.threads[parent].lock().as_mut().expect("invalid parent proc")
.children.push(pid); .children.push(tid);
pid tid
} }
/// Make process `pid` time slice -= 1. /// Make process `tid` time slice -= 1.
/// Return true if time slice == 0. /// Return true if time slice == 0.
/// Called by timer interrupt handler. /// Called by timer interrupt handler.
pub fn tick(&self, pid: Pid) -> bool { pub fn tick(&self, tid: Tid) -> bool {
let mut event_hub = self.event_hub.lock(); let mut event_hub = self.event_hub.lock();
event_hub.tick(); event_hub.tick();
while let Some(event) = event_hub.pop() { while let Some(event) = event_hub.pop() {
match event { match event {
Event::Wakeup(pid) => self.set_status(pid, Status::Ready), Event::Wakeup(tid) => self.set_status(tid, Status::Ready),
} }
} }
self.scheduler.lock().tick(pid) self.scheduler.lock().tick(tid)
} }
/// Set the priority of process `pid` /// Set the priority of process `tid`
pub fn set_priority(&self, pid: Pid, priority: u8) { pub fn set_priority(&self, tid: Tid, priority: u8) {
self.scheduler.lock().set_priority(pid, priority); self.scheduler.lock().set_priority(tid, priority);
} }
/// Called by Processor to get a process to run. /// Called by Processor to get a process to run.
/// The manager first mark it `Running`, /// The manager first mark it `Running`,
/// then take out and return its Context. /// then take out and return its Context.
pub fn run(&self, cpu_id: usize) -> (Pid, Box<Context>) { pub fn run(&self, cpu_id: usize) -> (Tid, Box<Context>) {
let mut scheduler = self.scheduler.lock(); let mut scheduler = self.scheduler.lock();
let pid = scheduler.select() let tid = scheduler.select()
.expect("failed to select a runnable process"); .expect("failed to select a runnable process");
scheduler.remove(pid); scheduler.remove(tid);
let mut proc_lock = self.procs[pid].lock(); let mut proc_lock = self.threads[tid].lock();
let mut proc = proc_lock.as_mut().expect("process not exist"); let mut proc = proc_lock.as_mut().expect("process not exist");
proc.status = Status::Running(cpu_id); proc.status = Status::Running(cpu_id);
(pid, proc.context.take().expect("context not exist")) (tid, proc.context.take().expect("context not exist"))
} }
/// Called by Processor to finish running a process /// Called by Processor to finish running a process
/// and give its context back. /// and give its context back.
pub fn stop(&self, pid: Pid, context: Box<Context>) { pub fn stop(&self, tid: Tid, context: Box<Context>) {
let mut proc_lock = self.procs[pid].lock(); let mut proc_lock = self.threads[tid].lock();
let mut proc = proc_lock.as_mut().expect("process not exist"); let mut proc = proc_lock.as_mut().expect("process not exist");
proc.status = proc.status_after_stop.clone(); proc.status = proc.status_after_stop.clone();
proc.status_after_stop = Status::Ready; proc.status_after_stop = Status::Ready;
proc.context = Some(context); proc.context = Some(context);
match proc.status { match proc.status {
Status::Ready => self.scheduler.lock().insert(pid), Status::Ready => self.scheduler.lock().insert(tid),
Status::Exited(_) => self.exit_handler(pid, proc), Status::Exited(_) => self.exit_handler(tid, proc),
_ => {} _ => {}
} }
} }
/// Switch the status of a process. /// Switch the status of a process.
/// Insert/Remove it to/from scheduler if necessary. /// Insert/Remove it to/from scheduler if necessary.
fn set_status(&self, pid: Pid, status: Status) { fn set_status(&self, tid: Tid, status: Status) {
let mut proc_lock = self.procs[pid].lock(); let mut proc_lock = self.threads[tid].lock();
let mut proc = proc_lock.as_mut().expect("process not exist"); let mut proc = proc_lock.as_mut().expect("process not exist");
trace!("process {} {:?} -> {:?}", pid, proc.status, status); trace!("process {} {:?} -> {:?}", tid, proc.status, status);
match (&proc.status, &status) { match (&proc.status, &status) {
(Status::Ready, Status::Ready) => return, (Status::Ready, Status::Ready) => return,
(Status::Ready, _) => self.scheduler.lock().remove(pid), (Status::Ready, _) => self.scheduler.lock().remove(tid),
(Status::Exited(_), _) => panic!("can not set status for a exited process"), (Status::Exited(_), _) => panic!("can not set status for a exited process"),
(Status::Sleeping, Status::Exited(_)) => self.event_hub.lock().remove(Event::Wakeup(pid)), (Status::Sleeping, Status::Exited(_)) => self.event_hub.lock().remove(Event::Wakeup(tid)),
(_, Status::Ready) => self.scheduler.lock().insert(pid), (_, Status::Ready) => self.scheduler.lock().insert(tid),
_ => {} _ => {}
} }
match proc.status { match proc.status {
@ -145,19 +142,19 @@ impl ProcessManager {
_ => proc.status = status, _ => proc.status = status,
} }
match proc.status { match proc.status {
Status::Exited(_) => self.exit_handler(pid, proc), Status::Exited(_) => self.exit_handler(tid, proc),
_ => {} _ => {}
} }
} }
pub fn get_status(&self, pid: Pid) -> Option<Status> { pub fn get_status(&self, tid: Tid) -> Option<Status> {
self.procs[pid].lock().as_ref().map(|p| p.status.clone()) self.threads[tid].lock().as_ref().map(|p| p.status.clone())
} }
/// Remove an exited proc `pid`. /// Remove an exited proc `tid`.
/// Its all children will be set parent to 0. /// Its all children will be set parent to 0.
pub fn remove(&self, pid: Pid) { pub fn remove(&self, tid: Tid) {
let mut proc_lock = self.procs[pid].lock(); let mut proc_lock = self.threads[tid].lock();
let proc = proc_lock.as_ref().expect("process not exist"); let proc = proc_lock.as_ref().expect("process not exist");
match proc.status { match proc.status {
Status::Exited(_) => {} Status::Exited(_) => {}
@ -165,49 +162,49 @@ impl ProcessManager {
} }
// orphan procs // orphan procs
for child in proc.children.iter() { for child in proc.children.iter() {
(&self.procs[*child]).lock().as_mut().expect("process not exist").parent = 0; (&self.threads[*child]).lock().as_mut().expect("process not exist").parent = 0;
} }
// remove self from parent's children list // remove self from parent's children list
self.procs[proc.parent].lock().as_mut().expect("process not exist") self.threads[proc.parent].lock().as_mut().expect("process not exist")
.children.retain(|&i| i != pid); .children.retain(|&i| i != tid);
// release the pid // release the tid
*proc_lock = None; *proc_lock = None;
} }
/// Sleep `pid` for `time` ticks. /// Sleep `tid` for `time` ticks.
/// `time` == 0 means sleep forever /// `time` == 0 means sleep forever
pub fn sleep(&self, pid: Pid, time: usize) { pub fn sleep(&self, tid: Tid, time: usize) {
self.set_status(pid, Status::Sleeping); self.set_status(tid, Status::Sleeping);
if time != 0 { if time != 0 {
self.event_hub.lock().push(time, Event::Wakeup(pid)); self.event_hub.lock().push(time, Event::Wakeup(tid));
} }
} }
pub fn wakeup(&self, pid: Pid) { pub fn wakeup(&self, tid: Tid) {
self.set_status(pid, Status::Ready); self.set_status(tid, Status::Ready);
} }
pub fn wait(&self, pid: Pid, target: Pid) { pub fn wait(&self, tid: Tid, target: Tid) {
self.set_status(pid, Status::Waiting(target)); self.set_status(tid, Status::Waiting(target));
} }
pub fn wait_child(&self, pid: Pid) { pub fn wait_child(&self, tid: Tid) {
self.set_status(pid, Status::Waiting(0)); self.set_status(tid, Status::Waiting(0));
} }
pub fn get_children(&self, pid: Pid) -> Vec<Pid> { pub fn get_children(&self, tid: Tid) -> Vec<Tid> {
self.procs[pid].lock().as_ref().expect("process not exist").children.clone() self.threads[tid].lock().as_ref().expect("process not exist").children.clone()
} }
pub fn exit(&self, pid: Pid, code: ExitCode) { pub fn exit(&self, tid: Tid, code: ExitCode) {
// NOTE: if `pid` is running, status change will be deferred. // NOTE: if `tid` is running, status change will be deferred.
self.set_status(pid, Status::Exited(code)); self.set_status(tid, Status::Exited(code));
} }
/// Called when a process exit /// Called when a process exit
fn exit_handler(&self, pid: Pid, proc: &mut Process) { fn exit_handler(&self, tid: Tid, proc: &mut Thread) {
// wakeup parent if waiting // wakeup parent if waiting
let parent = proc.parent; let parent = proc.parent;
match self.get_status(parent).expect("process not exist") { match self.get_status(parent).expect("process not exist") {
Status::Waiting(target) if target == pid || target == 0 => self.wakeup(parent), Status::Waiting(target) if target == tid || target == 0 => self.wakeup(parent),
_ => {} _ => {}
} }
// drop its context // drop its context

4
kernel/Cargo.lock generated

@ -248,7 +248,7 @@ dependencies = [
"pc-keyboard 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "pc-keyboard 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"raw-cpuid 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "raw-cpuid 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rcore-memory 0.1.0", "rcore-memory 0.1.0",
"rcore-process 0.1.0", "rcore-thread 0.1.0",
"riscv 0.3.0 (git+https://github.com/riscv-and-rust-and-decaf/riscv)", "riscv 0.3.0 (git+https://github.com/riscv-and-rust-and-decaf/riscv)",
"simple-filesystem 0.1.0 (git+https://github.com/wangrunji0408/SimpleFileSystem-Rust)", "simple-filesystem 0.1.0 (git+https://github.com/wangrunji0408/SimpleFileSystem-Rust)",
"smoltcp 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "smoltcp 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -267,7 +267,7 @@ dependencies = [
] ]
[[package]] [[package]]
name = "rcore-process" name = "rcore-thread"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",

@ -47,7 +47,7 @@ lazy_static = { version = "1.2", features = ["spin_no_std"] }
smoltcp = { version = "0.5.0", default-features = false, features = ["alloc", "log", "proto-ipv4", "proto-igmp", "socket-icmp", "socket-udp", "socket-tcp"] } smoltcp = { version = "0.5.0", default-features = false, features = ["alloc", "log", "proto-ipv4", "proto-igmp", "socket-icmp", "socket-udp", "socket-tcp"] }
bit-allocator = { path = "../crate/bit-allocator" } bit-allocator = { path = "../crate/bit-allocator" }
rcore-memory = { path = "../crate/memory" } rcore-memory = { path = "../crate/memory" }
rcore-process = { path = "../crate/process" } rcore-thread = { path = "../crate/thread" }
simple-filesystem = { git = "https://github.com/wangrunji0408/SimpleFileSystem-Rust" } simple-filesystem = { git = "https://github.com/wangrunji0408/SimpleFileSystem-Rust" }
[target.'cfg(target_arch = "x86_64")'.dependencies] [target.'cfg(target_arch = "x86_64")'.dependencies]

@ -13,7 +13,7 @@
extern crate alloc; extern crate alloc;
pub use crate::process::{processor, new_kernel_context}; pub use crate::process::{processor, new_kernel_context};
use rcore_process::thread; use rcore_thread::std_thread as thread;
use linked_list_allocator::LockedHeap; use linked_list_allocator::LockedHeap;
#[macro_use] // print! #[macro_use] // print!

@ -3,7 +3,7 @@ use alloc::{boxed::Box, collections::BTreeMap, string::String, sync::Arc, vec::V
use log::*; use log::*;
use simple_filesystem::file::File; use simple_filesystem::file::File;
use spin::Mutex; use spin::Mutex;
use rcore_process::Context; use rcore_thread::Context;
use xmas_elf::{ElfFile, header, program::{Flags, Type}}; use xmas_elf::{ElfFile, header, program::{Flags, Type}};
use crate::arch::interrupt::{Context as ArchContext, TrapFrame}; use crate::arch::interrupt::{Context as ArchContext, TrapFrame};

@ -1,5 +1,5 @@
pub use self::context::Process; pub use self::context::Process;
pub use rcore_process::*; pub use rcore_thread::*;
use crate::consts::{MAX_CPU_NUM, MAX_PROCESS_NUM}; use crate::consts::{MAX_CPU_NUM, MAX_PROCESS_NUM};
use crate::arch::cpu; use crate::arch::cpu;
use alloc::{boxed::Box, sync::Arc}; use alloc::{boxed::Box, sync::Arc};
@ -10,7 +10,7 @@ pub mod context;
pub fn init() { pub fn init() {
// NOTE: max_time_slice <= 5 to ensure 'priority' test pass // NOTE: max_time_slice <= 5 to ensure 'priority' test pass
let scheduler = Box::new(scheduler::RRScheduler::new(5)); let scheduler = Box::new(scheduler::RRScheduler::new(5));
let manager = Arc::new(ProcessManager::new(scheduler, MAX_PROCESS_NUM)); let manager = Arc::new(ThreadPool::new(scheduler, MAX_PROCESS_NUM));
unsafe { unsafe {
for cpu_id in 0..MAX_CPU_NUM { for cpu_id in 0..MAX_CPU_NUM {

@ -3,6 +3,7 @@
use alloc::string::String; use alloc::string::String;
use crate::fs::{ROOT_INODE, INodeExt}; use crate::fs::{ROOT_INODE, INodeExt};
use crate::process::*; use crate::process::*;
use crate::thread;
pub fn run_user_shell() { pub fn run_user_shell() {
if let Ok(inode) = ROOT_INODE.lookup("sh") { if let Ok(inode) = ROOT_INODE.lookup("sh") {

@ -14,7 +14,7 @@ pub fn timer() {
pub fn error(tf: &TrapFrame) -> ! { pub fn error(tf: &TrapFrame) -> ! {
error!("{:#x?}", tf); error!("{:#x?}", tf);
let pid = processor().pid(); let pid = processor().tid();
error!("On CPU{} Process {}", cpu::id(), pid); error!("On CPU{} Process {}", cpu::id(), pid);
processor().manager().exit(pid, 0x100); processor().manager().exit(pid, 0x100);

Loading…
Cancel
Save