mirror of
https://github.com/panpaul/tiny_os
synced 2024-09-20 09:45:19 +08:00
feat: add idle thread
This commit is contained in:
parent
cdcc709d70
commit
0d0a5471af
@ -2,7 +2,6 @@ use crate::entry::HART_ID;
|
||||
use crate::plat::console::CONSOLE;
|
||||
use crate::plat::timer::{Timer, TimerOps};
|
||||
use crate::plat::trap::{Trap, TrapContextOps, TrapOps};
|
||||
use crate::scheduler::SCHEDULER;
|
||||
use log::trace;
|
||||
use riscv::register::scause::{Exception as E, Interrupt as I, Trap as T};
|
||||
use riscv::register::stvec::TrapMode;
|
||||
@ -17,12 +16,45 @@ extern "C" {
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn kernel_trap_handler(tf: &mut TrapContext) {
|
||||
// No trap in kernel, except from IDLE thread
|
||||
// TODO: Replace CONSOLE Mutex to ReentrantLock
|
||||
unsafe { CONSOLE.force_unlock() }
|
||||
trap_handler(tf, true)
|
||||
tf.trap_handler(true);
|
||||
}
|
||||
|
||||
fn trap_handler(tf: &mut TrapContext, from_kernel: bool) {
|
||||
impl TrapOps for Trap {
|
||||
fn init() {
|
||||
// anyway, clear sscratch
|
||||
riscv::register::sscratch::write(0);
|
||||
// set trap_entry
|
||||
unsafe { riscv::register::stvec::write(trap_entry as usize, TrapMode::Direct) }
|
||||
}
|
||||
}
|
||||
|
||||
#[naked]
|
||||
extern "C" fn idle_thread() {
|
||||
unsafe {
|
||||
core::arch::asm!(
|
||||
"
|
||||
1: wfi
|
||||
j 1b
|
||||
",
|
||||
options(noreturn)
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
impl TrapContextOps for TrapContext {
|
||||
fn restore(&mut self) {
|
||||
unsafe { switch_to_user(self) }
|
||||
}
|
||||
|
||||
fn configure_idle_thread(&mut self) {
|
||||
self.sepc = idle_thread as usize;
|
||||
self.sstatus = (1 << 5) | (1 << 8); // SPIE + SPP
|
||||
}
|
||||
|
||||
fn trap_handler(&mut self, from_kernel: bool) {
|
||||
let scause = riscv::register::scause::read();
|
||||
trace!("[Trap] cpu@{} scause: {:?}", HART_ID.get(), scause.cause());
|
||||
|
||||
@ -33,23 +65,17 @@ fn trap_handler(tf: &mut TrapContext, from_kernel: bool) {
|
||||
$msg,
|
||||
scause.cause(),
|
||||
scause.bits(),
|
||||
tf.sepc,
|
||||
self.sepc,
|
||||
riscv::register::stval::read()
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
match scause.cause() {
|
||||
T::Interrupt(I::SupervisorTimer) => {
|
||||
Timer::do_tick();
|
||||
|
||||
if !from_kernel {
|
||||
SCHEDULER.schedule()
|
||||
}
|
||||
},
|
||||
T::Interrupt(I::SupervisorTimer) => Timer::do_tick(),
|
||||
T::Exception(E::UserEnvCall) => {
|
||||
// TODO: handle syscall
|
||||
tf.sepc += 4;
|
||||
self.sepc += 4;
|
||||
},
|
||||
T::Interrupt(I::SupervisorExternal) => {
|
||||
// TODO: handle external interrupt, e.g. plic
|
||||
@ -66,23 +92,9 @@ fn trap_handler(tf: &mut TrapContext, from_kernel: bool) {
|
||||
Timer::set_next();
|
||||
trace!("[Trap] exiting...");
|
||||
}
|
||||
|
||||
impl TrapOps for Trap {
|
||||
fn init() {
|
||||
// anyway, clear sscratch
|
||||
riscv::register::sscratch::write(0);
|
||||
// set trap_entry
|
||||
unsafe { riscv::register::stvec::write(trap_entry as usize, TrapMode::Direct) }
|
||||
}
|
||||
}
|
||||
|
||||
impl TrapContextOps for TrapContext {
|
||||
fn restore(&mut self) {
|
||||
unsafe { switch_to_user(self) }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Default)]
|
||||
#[repr(C)]
|
||||
pub struct GeneralRegs {
|
||||
pub ra: usize,
|
||||
@ -118,7 +130,7 @@ pub struct GeneralRegs {
|
||||
pub t6: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Default)]
|
||||
#[repr(C)]
|
||||
pub struct TrapContext {
|
||||
// [0:30] GPRs exclude zero
|
||||
|
@ -6,4 +6,6 @@ pub trait TrapOps {
|
||||
|
||||
pub trait TrapContextOps {
|
||||
fn restore(&mut self);
|
||||
fn configure_idle_thread(&mut self);
|
||||
fn trap_handler(&mut self, from_kernel: bool);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user