support idle for rcore-thread, remove idle thread in kernel

master
WangRunji 6 years ago
parent fc98719559
commit e678186b3d

@ -16,6 +16,12 @@ pub unsafe fn restore(flags: usize) {
} }
} }
#[inline(always)]
#[cfg(target_arch = "x86_64")]
pub unsafe fn enable_and_wfi() {
asm!("sti; hlt" :::: "volatile");
}
#[inline(always)] #[inline(always)]
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
pub unsafe fn disable_and_store() -> usize { pub unsafe fn disable_and_store() -> usize {
@ -40,6 +46,16 @@ pub unsafe fn restore(flags: usize) {
} }
} }
#[inline(always)]
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
pub unsafe fn enable_and_wfi() {
if env!("M_MODE") == "1" {
asm!("csrsi mstatus, 1 << 3; wfi" :::: "volatile");
} else {
asm!("csrsi sstatus, 1 << 1; wfi" :::: "volatile");
}
}
#[inline(always)] #[inline(always)]
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
pub unsafe fn disable_and_store() -> usize { pub unsafe fn disable_and_store() -> usize {
@ -53,3 +69,9 @@ pub unsafe fn disable_and_store() -> usize {
pub unsafe fn restore(flags: usize) { pub unsafe fn restore(flags: usize) {
asm!("msr DAIF, $0" :: "r"(flags as u32) :: "volatile"); asm!("msr DAIF, $0" :: "r"(flags as u32) :: "volatile");
} }
#[inline(always)]
#[cfg(target_arch = "aarch64")]
pub unsafe fn enable_and_wfi() {
asm!("msr daifclr, #2; wfi" :::: "volatile");
}

@ -53,20 +53,28 @@ impl Processor {
let inner = self.inner(); let inner = self.inner();
unsafe { interrupt::disable_and_store(); } unsafe { interrupt::disable_and_store(); }
loop { loop {
let proc = inner.manager.run(inner.id); if let Some(proc) = inner.manager.run(inner.id) {
trace!("CPU{} begin running process {}", inner.id, proc.0); trace!("CPU{} begin running thread {}", inner.id, proc.0);
inner.proc = Some(proc); inner.proc = Some(proc);
unsafe { unsafe {
inner.loop_context.switch_to(&mut *inner.proc.as_mut().unwrap().1); inner.loop_context.switch_to(&mut *inner.proc.as_mut().unwrap().1);
}
let (pid, context) = inner.proc.take().unwrap();
trace!("CPU{} stop running thread {}", inner.id, pid);
inner.manager.stop(pid, context);
} else {
trace!("CPU{} idle", inner.id);
unsafe { interrupt::enable_and_wfi(); }
// wait for a timer interrupt
unsafe { interrupt::disable_and_store(); }
} }
let (pid, context) = inner.proc.take().unwrap();
trace!("CPU{} stop running process {}", inner.id, pid);
inner.manager.stop(pid, context);
} }
} }
/// Called by process running on this Processor. /// Called by process running on this Processor.
/// Yield and reschedule. /// Yield and reschedule.
///
/// The interrupt may be enabled.
pub fn yield_now(&self) { pub fn yield_now(&self) {
let inner = self.inner(); let inner = self.inner();
unsafe { unsafe {
@ -88,11 +96,14 @@ impl Processor {
&*self.inner().manager &*self.inner().manager
} }
/// Called by timer interrupt handler.
///
/// The interrupt should be disabled in the handler.
pub fn tick(&self) { pub fn tick(&self) {
let flags = unsafe { interrupt::disable_and_store() }; // If I'm idle, tid == None, need_reschedule == false.
let need_reschedule = self.manager().tick(self.tid()); // Will go back to `run()` after interrupt return.
unsafe { interrupt::restore(flags); } let tid = self.inner().proc.as_ref().map(|p| p.0);
let need_reschedule = self.manager().tick(self.inner().id, tid);
if need_reschedule { if need_reschedule {
self.yield_now(); self.yield_now();
} }

@ -78,15 +78,20 @@ impl ThreadPool {
/// Make process `tid` 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, tid: Tid) -> bool { pub(crate) fn tick(&self, cpu_id: usize, tid: Option<Tid>) -> bool {
let mut timer = self.timer.lock(); if cpu_id == 0 {
timer.tick(); let mut timer = self.timer.lock();
while let Some(event) = timer.pop() { timer.tick();
match event { while let Some(event) = timer.pop() {
Event::Wakeup(tid) => self.set_status(tid, Status::Ready), match event {
Event::Wakeup(tid) => self.set_status(tid, Status::Ready),
}
} }
} }
self.scheduler.lock().tick(tid) match tid {
Some(tid) => self.scheduler.lock().tick(tid),
None => false,
}
} }
/// Set the priority of process `tid` /// Set the priority of process `tid`
@ -97,20 +102,21 @@ impl ThreadPool {
/// 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) -> (Tid, Box<Context>) { pub(crate) fn run(&self, cpu_id: usize) -> Option<(Tid, Box<Context>)> {
let mut scheduler = self.scheduler.lock(); let mut scheduler = self.scheduler.lock();
let tid = scheduler.select() scheduler.select()
.expect("failed to select a runnable process"); .map(|tid| {
scheduler.remove(tid); scheduler.remove(tid);
let mut proc_lock = self.threads[tid].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);
(tid, 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, tid: Tid, context: Box<Context>) { pub(crate) fn stop(&self, tid: Tid, context: Box<Context>) {
let mut proc_lock = self.threads[tid].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();

@ -20,15 +20,6 @@ pub fn init() {
} }
} }
// Add idle threads
extern fn idle(_arg: usize) -> ! {
loop { cpu::halt(); }
}
use core::str::FromStr;
let cores = usize::from_str(env!("SMP")).unwrap();
for i in 0..cores {
manager.add(Thread::new_kernel(idle, i), 0);
}
crate::shell::run_user_shell(); crate::shell::run_user_shell();
info!("process init end"); info!("process init end");

Loading…
Cancel
Save