fix thread crate example

toolchain_update
WangRunji 6 years ago
parent cc6a069586
commit 7eaeb4711e

@ -3,7 +3,6 @@
#![feature(asm)]
#![feature(alloc)]
#![feature(naked_functions)]
#![feature(panic_info_message)]
#![feature(lang_items)]
extern crate alloc;
@ -33,21 +32,26 @@ pub extern "C" fn _start() -> ! {
// init heap
unsafe { HEAP_ALLOCATOR.lock().init(HEAP.as_ptr() as usize, HEAP_SIZE); }
// init processor
let scheduler = Box::new(scheduler::RRScheduler::new(5));
let scheduler = scheduler::RRScheduler::new(5);
let thread_pool = Arc::new(ThreadPool::new(scheduler, MAX_PROC_NUM));
unsafe { processor().init(0, Thread::init(), thread_pool); }
// init threads
thread::spawn(|| {
let tid = processor().tid();
serial_println!("I'm thread {}! yield...", tid);
serial_println!("[{}] yield", tid);
thread::yield_now();
serial_println!("I'm thread {}! exit...", tid);
});
thread::spawn(|| {
serial_println!("[{}] spawn", tid);
let t2 = thread::spawn(|| {
let tid = processor().tid();
serial_println!("I'm thread {}! yield...", tid);
serial_println!("[{}] yield", tid);
thread::yield_now();
serial_println!("I'm thread {}! exit...", tid);
serial_println!("[{}] return 8", tid);
8
});
serial_println!("[{}] join", tid);
let ret = t2.join();
serial_println!("[{}] get {:?}", tid, ret);
serial_println!("[{}] exit", tid);
});
// run threads
processor().run();
@ -158,6 +162,9 @@ impl Context for Thread {
: : : : "intel" "volatile" )
}
}
fn set_tid(&mut self, _tid: usize) {
}
}
/// Define global `Processor` for each core.
@ -180,9 +187,7 @@ pub fn new_kernel_context(entry: extern fn(usize) -> !, arg0: usize) -> Box<Cont
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
let location = info.location().unwrap();
let message = info.message().unwrap();
serial_println!("\nPANIC @ {}\n\t{}", location, message);
serial_println!("\n{}", info);
unsafe { exit_qemu(); }
loop {}

@ -143,16 +143,11 @@ impl<T> JoinHandle<T> {
/// Waits for the associated thread to finish.
pub fn join(self) -> Result<T, ()> {
loop {
trace!("join thread {}", self.thread.tid);
match processor().manager().get_status(self.thread.tid) {
Some(Status::Exited(exit_code)) => {
processor().manager().remove(self.thread.tid);
trace!("try to join thread {}", self.thread.tid);
if let Some(exit_code) = processor().manager().try_remove(self.thread.tid) {
// Find return value on the heap from the exit code.
return Ok(unsafe { *Box::from_raw(exit_code as *mut T) });
}
None => return Err(()),
_ => {}
}
processor().manager().wait(current().id(), self.thread.tid);
processor().yield_now();
}

@ -59,7 +59,7 @@ impl ThreadPool {
return (i, thread);
}
}
panic!("Process number exceeded");
panic!("Thread number exceeded");
}
/// Add a new thread
@ -77,7 +77,7 @@ impl ThreadPool {
tid
}
/// Make process `tid` time slice -= 1.
/// Make thread `tid` time slice -= 1.
/// Return true if time slice == 0.
/// Called by timer interrupt handler.
pub(crate) fn tick(&self, cpu_id: usize, tid: Option<Tid>) -> bool {
@ -96,35 +96,35 @@ impl ThreadPool {
}
}
/// Set the priority of process `tid`
/// Set the priority of thread `tid`
pub fn set_priority(&self, tid: Tid, priority: u8) {
self.scheduler.set_priority(tid, priority);
}
/// Called by Processor to get a process to run.
/// Called by Processor to get a thread to run.
/// The manager first mark it `Running`,
/// then take out and return its Context.
pub(crate) fn run(&self, cpu_id: usize) -> Option<(Tid, Box<Context>)> {
self.scheduler.pop(cpu_id)
.map(|tid| {
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("thread not exist");
proc.status = Status::Running(cpu_id);
(tid, proc.context.take().expect("context not exist"))
})
}
/// Called by Processor to finish running a process
/// Called by Processor to finish running a thread
/// and give its context back.
pub(crate) fn stop(&self, tid: Tid, context: Box<Context>) {
let mut proc_lock = self.threads[tid].lock();
let mut proc = proc_lock.as_mut().expect("process not exist");
let proc = proc_lock.as_mut().expect("thread not exist");
proc.status = proc.status_after_stop.clone();
proc.status_after_stop = Status::Ready;
proc.context = Some(context);
match proc.status {
Status::Ready => self.scheduler.push(tid),
Status::Exited(_) => self.exit_handler(tid, proc),
Status::Exited(_) => self.exit_handler(proc),
_ => {}
}
}
@ -135,22 +135,22 @@ impl ThreadPool {
pub(crate) fn wait(&self, tid: Tid, target: Tid) {
self.set_status(tid, Status::Sleeping);
let mut target_lock = self.threads[target].lock();
let target = target_lock.as_mut().expect("process not exist");
let target = target_lock.as_mut().expect("thread not exist");
target.waiter = Some(tid);
}
/// Switch the status of a process.
/// Switch the status of a thread.
/// Insert/Remove it to/from scheduler if necessary.
fn set_status(&self, tid: Tid, status: Status) {
let mut proc_lock = self.threads[tid].lock();
if let Some(mut proc) = proc_lock.as_mut() {
trace!("process {} {:?} -> {:?}", tid, proc.status, status);
trace!("thread {} {:?} -> {:?}", tid, proc.status, status);
match (&proc.status, &status) {
(Status::Ready, Status::Ready) => return,
(Status::Ready, _) => panic!("can not remove a process from ready queue"),
(Status::Ready, _) => panic!("can not remove a thread from ready queue"),
(Status::Exited(_), _) => panic!("can not set status for a exited thread"),
(Status::Sleeping, Status::Exited(_)) => self.timer.lock().stop(Event::Wakeup(tid)),
(Status::Running(_), Status::Ready) => {} // process will be added to scheduler in stop()
(Status::Running(_), Status::Ready) => {} // thread will be added to scheduler in stop()
(_, Status::Ready) => self.scheduler.push(tid),
_ => {}
}
@ -159,30 +159,25 @@ impl ThreadPool {
_ => proc.status = status,
}
match proc.status {
Status::Exited(_) => self.exit_handler(tid, proc),
Status::Exited(_) => self.exit_handler(proc),
_ => {}
}
}
}
pub fn get_status(&self, tid: Tid) -> Option<Status> {
if tid < self.threads.len() {
self.threads[tid].lock().as_ref().map(|p| p.status.clone())
} else {
None
}
}
/// Remove an exited proc `tid`.
pub fn remove(&self, tid: Tid) {
/// Try to remove an exited thread `tid`.
/// Return its exit code if success.
pub fn try_remove(&self, tid: Tid) -> Option<ExitCode> {
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("thread not exist");
match proc.status {
Status::Exited(_) => {}
_ => panic!("can not remove non-exited process"),
}
Status::Exited(code) => {
// release the tid
*proc_lock = None;
Some(code)
},
_ => None,
}
}
/// Sleep `tid` for `time` ticks.
@ -203,7 +198,7 @@ impl ThreadPool {
self.set_status(tid, Status::Exited(code));
}
/// Called when a thread exit
fn exit_handler(&self, _tid: Tid, proc: &mut Thread) {
fn exit_handler(&self, proc: &mut Thread) {
// wake up waiter
if let Some(waiter) = proc.waiter {
self.wakeup(waiter);

Loading…
Cancel
Save