Merge pull request #1 from dramforever/ch3_doc

Merge docs ch3_doc -> ch3
ch3
chyyuu 3 years ago committed by GitHub
commit 776fc2388c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -41,10 +41,12 @@ impl UserStack {
}
}
/// Get base address of app i.
fn get_base_i(app_id: usize) -> usize {
APP_BASE_ADDRESS + app_id * APP_SIZE_LIMIT
}
/// Get the total number of applications.
pub fn get_num_app() -> usize {
extern "C" {
fn _num_app();
@ -52,6 +54,8 @@ pub fn get_num_app() -> usize {
unsafe { (_num_app as usize as *const usize).read_volatile() }
}
/// Load nth user app at
/// [APP_BASE_ADDRESS + n * APP_SIZE_LIMIT, APP_BASE_ADDRESS + (n+1) * APP_SIZE_LIMIT).
pub fn load_apps() {
extern "C" {
fn _num_app();
@ -78,6 +82,7 @@ pub fn load_apps() {
}
}
/// get app info with entry and sp and save `TrapContext` in kernel stack
pub fn init_app_cx(app_id: usize) -> usize {
KERNEL_STACK[app_id].push_context(TrapContext::app_init_context(
get_base_i(app_id),

@ -27,18 +27,22 @@ fn sbi_call(which: usize, arg0: usize, arg1: usize, arg2: usize) -> usize {
ret
}
/// use sbi call to set timer
pub fn set_timer(timer: usize) {
sbi_call(SBI_SET_TIMER, timer, 0, 0);
}
/// use sbi call to putchar in console (qemu uart handler)
pub fn console_putchar(c: usize) {
sbi_call(SBI_CONSOLE_PUTCHAR, c, 0, 0);
}
/// use sbi call to getchar from console (qemu uart handler)
pub fn console_getchar() -> usize {
sbi_call(SBI_CONSOLE_GETCHAR, 0, 0, 0)
}
/// use sbi call to shutdown the kernel
pub fn shutdown() -> ! {
sbi_call(SBI_SHUTDOWN, 0, 0, 0);
panic!("It should shutdown!");

@ -9,6 +9,7 @@ mod process;
use fs::*;
use process::*;
/// handle syscall exception with `syscall_id` and other arguments
pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize {
match syscall_id {
SYSCALL_WRITE => sys_write(args[0], args[1] as *const u8, args[2]),

@ -1,17 +1,20 @@
use crate::task::{exit_current_and_run_next, suspend_current_and_run_next};
use crate::timer::get_time_ms;
/// task exits and submit an exit code
pub fn sys_exit(exit_code: i32) -> ! {
println!("[kernel] Application exited with code {}", exit_code);
exit_current_and_run_next();
panic!("Unreachable in sys_exit!");
}
/// current task gives up resources for other tasks
pub fn sys_yield() -> isize {
suspend_current_and_run_next();
0
}
/// get time in milliseconds
pub fn sys_get_time() -> isize {
get_time_ms() as isize
}

@ -13,12 +13,16 @@ use task::{TaskControlBlock, TaskStatus};
pub use context::TaskContext;
pub struct TaskManager {
/// total number of tasks
num_app: usize,
/// use inner value to get mutable access
inner: UPSafeCell<TaskManagerInner>,
}
struct TaskManagerInner {
/// task list
tasks: [TaskControlBlock; MAX_APP_NUM],
/// id of current `Running` task
current_task: usize,
}
@ -46,6 +50,10 @@ lazy_static! {
}
impl TaskManager {
/// Run the first task in task list.
///
/// Generally, the first task in task list is an idle task (we call it zero process later).
/// But in ch3, we load apps statically, so the first task is a real app.
fn run_first_task(&self) -> ! {
let mut inner = self.inner.exclusive_access();
let task0 = &mut inner.tasks[0];
@ -60,18 +68,23 @@ impl TaskManager {
panic!("unreachable in run_first_task!");
}
/// Change the status of current `Running` task into `Ready`.
fn mark_current_suspended(&self) {
let mut inner = self.inner.exclusive_access();
let current = inner.current_task;
inner.tasks[current].task_status = TaskStatus::Ready;
}
/// Change the status of current `Running` task into `Exited`.
fn mark_current_exited(&self) {
let mut inner = self.inner.exclusive_access();
let current = inner.current_task;
inner.tasks[current].task_status = TaskStatus::Exited;
}
/// Find next task to run and return app id.
///
/// In this case, we only return the first `Ready` task in task list.
fn find_next_task(&self) -> Option<usize> {
let inner = self.inner.exclusive_access();
let current = inner.current_task;
@ -80,6 +93,8 @@ impl TaskManager {
.find(|id| inner.tasks[*id].task_status == TaskStatus::Ready)
}
/// Switch current `Running` task to the task we have found,
/// or there is no `Ready` task and we can exit with all applications completed
fn run_next_task(&self) {
if let Some(next) = self.find_next_task() {
let mut inner = self.inner.exclusive_access();

@ -5,14 +5,17 @@ use riscv::register::time;
const TICKS_PER_SEC: usize = 100;
const MSEC_PER_SEC: usize = 1000;
/// read the `mtime` register
pub fn get_time() -> usize {
time::read()
}
/// get current time in milliseconds
pub fn get_time_ms() -> usize {
time::read() / (CLOCK_FREQ / MSEC_PER_SEC)
}
/// set the next timer interrupt
pub fn set_next_trigger() {
set_timer(get_time() + CLOCK_FREQ / TICKS_PER_SEC);
}

@ -12,6 +12,7 @@ use riscv::register::{
global_asm!(include_str!("trap.S"));
/// initialize CSR `stvec` as the entry of `__alltraps`
pub fn init() {
extern "C" {
fn __alltraps();
@ -21,6 +22,7 @@ pub fn init() {
}
}
/// timer interrupt enabled
pub fn enable_timer_interrupt() {
unsafe {
sie::set_stimer();
@ -28,9 +30,10 @@ pub fn enable_timer_interrupt() {
}
#[no_mangle]
/// handle an interrupt, exception, or system call from user space
pub fn trap_handler(cx: &mut TrapContext) -> &mut TrapContext {
let scause = scause::read();
let stval = stval::read();
let scause = scause::read(); // get trap cause
let stval = stval::read(); // get extra value
match scause.cause() {
Trap::Exception(Exception::UserEnvCall) => {
cx.sepc += 4;

Loading…
Cancel
Save