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)]
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
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)]
#[cfg(target_arch = "aarch64")]
pub unsafe fn disable_and_store() -> usize {
@ -53,3 +69,9 @@ pub unsafe fn disable_and_store() -> usize {
pub unsafe fn restore(flags: usize) {
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();
unsafe { interrupt::disable_and_store(); }
loop {
let proc = inner.manager.run(inner.id);
trace!("CPU{} begin running process {}", inner.id, proc.0);
inner.proc = Some(proc);
unsafe {
inner.loop_context.switch_to(&mut *inner.proc.as_mut().unwrap().1);
if let Some(proc) = inner.manager.run(inner.id) {
trace!("CPU{} begin running thread {}", inner.id, proc.0);
inner.proc = Some(proc);
unsafe {
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.
/// Yield and reschedule.
///
/// The interrupt may be enabled.
pub fn yield_now(&self) {
let inner = self.inner();
unsafe {
@ -88,11 +96,14 @@ impl Processor {
&*self.inner().manager
}
/// Called by timer interrupt handler.
///
/// The interrupt should be disabled in the handler.
pub fn tick(&self) {
let flags = unsafe { interrupt::disable_and_store() };
let need_reschedule = self.manager().tick(self.tid());
unsafe { interrupt::restore(flags); }
// If I'm idle, tid == None, need_reschedule == false.
// Will go back to `run()` after interrupt return.
let tid = self.inner().proc.as_ref().map(|p| p.0);
let need_reschedule = self.manager().tick(self.inner().id, tid);
if need_reschedule {
self.yield_now();
}

@ -78,15 +78,20 @@ impl ThreadPool {
/// Make process `tid` time slice -= 1.
/// Return true if time slice == 0.
/// Called by timer interrupt handler.
pub fn tick(&self, tid: Tid) -> bool {
let mut timer = self.timer.lock();
timer.tick();
while let Some(event) = timer.pop() {
match event {
Event::Wakeup(tid) => self.set_status(tid, Status::Ready),
pub(crate) fn tick(&self, cpu_id: usize, tid: Option<Tid>) -> bool {
if cpu_id == 0 {
let mut timer = self.timer.lock();
timer.tick();
while let Some(event) = timer.pop() {
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`
@ -97,20 +102,21 @@ impl ThreadPool {
/// Called by Processor to get a process to run.
/// The manager first mark it `Running`,
/// 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 tid = scheduler.select()
.expect("failed to select a runnable process");
scheduler.remove(tid);
let mut proc_lock = self.threads[tid].lock();
let mut proc = proc_lock.as_mut().expect("process not exist");
proc.status = Status::Running(cpu_id);
(tid, proc.context.take().expect("context not exist"))
scheduler.select()
.map(|tid| {
scheduler.remove(tid);
let mut proc_lock = self.threads[tid].lock();
let mut proc = proc_lock.as_mut().expect("process not exist");
proc.status = Status::Running(cpu_id);
(tid, proc.context.take().expect("context not exist"))
})
}
/// Called by Processor to finish running a process
/// 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 = proc_lock.as_mut().expect("process not exist");
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();
info!("process init end");

Loading…
Cancel
Save