From 8b2f8bf2a37e700075cdaede4f232b3882c6da9c Mon Sep 17 00:00:00 2001 From: Tateisi Date: Sun, 3 Aug 2025 11:54:14 +0800 Subject: [PATCH] lab 03 --- os/src/config.rs | 1 + os/src/syscall/mod.rs | 5 +++++ os/src/syscall/process.rs | 29 +++++++++++++++++++++++++++-- os/src/task/mod.rs | 35 +++++++++++++++++++++++++++++++++-- os/src/task/task.rs | 12 ++++++++++++ user/src/bin/00power_3.rs | 26 +++++++------------------- user/src/bin/04taskinfo.rs | 16 ++++++++++++++++ user/src/lib.rs | 32 ++++++++++++++++++++++++++++++++ user/src/syscall.rs | 7 +++++++ 9 files changed, 140 insertions(+), 23 deletions(-) create mode 100644 user/src/bin/04taskinfo.rs diff --git a/os/src/config.rs b/os/src/config.rs index ff7ffbe..9d019a7 100644 --- a/os/src/config.rs +++ b/os/src/config.rs @@ -5,6 +5,7 @@ pub const KERNEL_STACK_SIZE: usize = 4096 * 2; pub const MAX_APP_NUM: usize = 4; pub const APP_BASE_ADDRESS: usize = 0x80400000; pub const APP_SIZE_LIMIT: usize = 0x20000; +pub const MAX_SYSCALL_NUM: usize = 500; /* #[cfg(feature = "board_k210")] diff --git a/os/src/syscall/mod.rs b/os/src/syscall/mod.rs index ee52f5b..7adbc78 100644 --- a/os/src/syscall/mod.rs +++ b/os/src/syscall/mod.rs @@ -14,6 +14,7 @@ const SYSCALL_WRITE: usize = 64; const SYSCALL_EXIT: usize = 93; const SYSCALL_YIELD: usize = 124; const SYSCALL_GET_TIME: usize = 169; +const SYSCALL_TASK_INFO: usize = 410; mod fs; mod process; @@ -21,13 +22,17 @@ mod process; use fs::*; use process::*; +use crate::task::TASK_MANAGER; + /// handle syscall exception with `syscall_id` and other arguments pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize { + TASK_MANAGER.mark_syscall(syscall_id); match syscall_id { SYSCALL_WRITE => sys_write(args[0], args[1] as *const u8, args[2]), SYSCALL_EXIT => sys_exit(args[0] as i32), SYSCALL_YIELD => sys_yield(), SYSCALL_GET_TIME => sys_get_time(), + SYSCALL_TASK_INFO => sys_task_info(args[0] as *mut TaskInfo), _ => panic!("Unsupported syscall_id: {}", syscall_id), } } diff --git a/os/src/syscall/process.rs b/os/src/syscall/process.rs index bdf5c8b..7d6d102 100644 --- a/os/src/syscall/process.rs +++ b/os/src/syscall/process.rs @@ -1,6 +1,20 @@ //! Process management syscalls -use crate::task::{exit_current_and_run_next, suspend_current_and_run_next}; -use crate::timer::get_time_ms; +use log::trace; + +use crate::task::{exit_current_and_run_next, suspend_current_and_run_next, TaskStatus, TASK_MANAGER}; +use crate::timer::{get_time, get_time_ms}; +use crate::config::MAX_SYSCALL_NUM; + +/// Task information +#[allow(dead_code)] +pub struct TaskInfo { + /// Task status in it's life cycle + status: TaskStatus, + /// The numbers of syscall called by task + syscall_times: [u32; MAX_SYSCALL_NUM], + /// Total running time of task + time: usize, +} /// task exits and submit an exit code pub fn sys_exit(exit_code: i32) -> ! { @@ -19,3 +33,14 @@ pub fn sys_yield() -> isize { pub fn sys_get_time() -> isize { get_time_ms() as isize } + +/// YOUR JOB: Finish sys_task_info to pass testcases +pub fn sys_task_info(ti: *mut TaskInfo) -> isize { + unsafe { + (*ti).status = TASK_MANAGER.get_current_status(); + (*ti).time = get_time(); + (*ti).syscall_times = TASK_MANAGER.get_current_syscall_times() + } + trace!("kernel: sys_task_info"); + 0 +} diff --git a/os/src/task/mod.rs b/os/src/task/mod.rs index 8696db4..0e15858 100644 --- a/os/src/task/mod.rs +++ b/os/src/task/mod.rs @@ -15,13 +15,13 @@ mod switch; #[allow(clippy::module_inception)] mod task; -use crate::config::MAX_APP_NUM; +use crate::config::{MAX_APP_NUM, MAX_SYSCALL_NUM}; use crate::loader::{get_num_app, init_app_cx}; use crate::sbi::shutdown; use crate::sync::UPSafeCell; use lazy_static::*; use switch::__switch; -use task::{TaskControlBlock, TaskStatus}; +pub use task::{TaskControlBlock, TaskStatus}; pub use context::TaskContext; @@ -56,6 +56,7 @@ lazy_static! { let mut tasks = [TaskControlBlock { task_cx: TaskContext::zero_init(), task_status: TaskStatus::UnInit, + syscall_times: [0; MAX_SYSCALL_NUM] }; MAX_APP_NUM]; for (i, task) in tasks.iter_mut().enumerate() { task.task_cx = TaskContext::goto_restore(init_app_cx(i)); @@ -138,6 +139,36 @@ impl TaskManager { shutdown(false); } } + + /// get current task id + pub fn get_current_id(&self) -> usize { + let inner = self.inner.exclusive_access(); + inner.current_task + } + + /// get current task status + pub fn get_current_status(&self) -> TaskStatus { + let inner = self.inner.exclusive_access(); + let current = inner.current_task; + inner.tasks[current].task_status + } + + /// get current task syscall times + pub fn get_current_syscall_times(&self) -> [u32; MAX_SYSCALL_NUM] { + let inner = self.inner.exclusive_access(); + let current = inner.current_task; + return inner.tasks[current].syscall_times.clone(); + } + + /// record syscall + pub fn mark_syscall(&self, syscall_id: usize) { + if syscall_id >= MAX_SYSCALL_NUM { + return; + } + let mut inner = self.inner.exclusive_access(); + let current = inner.current_task; + inner.tasks[current].syscall_times[syscall_id] += 1; + } } /// run first task diff --git a/os/src/task/task.rs b/os/src/task/task.rs index d72efc7..1826ac8 100644 --- a/os/src/task/task.rs +++ b/os/src/task/task.rs @@ -1,17 +1,29 @@ //! Types related to task management +use crate::config::MAX_SYSCALL_NUM; + use super::TaskContext; +/// The task control block (TCB) of a task. #[derive(Copy, Clone)] pub struct TaskControlBlock { + /// The task status in it's lifecycle pub task_status: TaskStatus, + /// The task context pub task_cx: TaskContext, + /// The numbers of syscall called by task + pub syscall_times: [u32; MAX_SYSCALL_NUM], } +/// The status of a task #[derive(Copy, Clone, PartialEq)] pub enum TaskStatus { + /// uninitialized UnInit, + /// ready to run Ready, + /// running Running, + /// exited Exited, } diff --git a/user/src/bin/00power_3.rs b/user/src/bin/00power_3.rs index 1a04dc7..963e7c9 100644 --- a/user/src/bin/00power_3.rs +++ b/user/src/bin/00power_3.rs @@ -1,28 +1,16 @@ #![no_std] #![no_main] -#[macro_use] extern crate user_lib; -const LEN: usize = 100; +use user_lib::{ + println, task_info, TaskInfo, +}; #[no_mangle] -fn main() -> i32 { - let p = 3u64; - let m = 998244353u64; - let iter: usize = 200000; - let mut s = [0u64; LEN]; - let mut cur = 0usize; - s[cur] = 1; - for i in 1..=iter { - let next = if cur + 1 == LEN { 0 } else { cur + 1 }; - s[next] = s[cur] * p % m; - cur = next; - if i % 10000 == 0 { - println!("power_3 [{}/{}]", i, iter); - } - } - println!("{}^{} = {}(MOD {})", p, iter, s[cur], m); - println!("Test power_3 OK!"); +pub fn main() -> usize { + let info = TaskInfo::new(); + assert_eq!(0, task_info(&info)); + println!("task_info {:?}", info); 0 } diff --git a/user/src/bin/04taskinfo.rs b/user/src/bin/04taskinfo.rs new file mode 100644 index 0000000..963e7c9 --- /dev/null +++ b/user/src/bin/04taskinfo.rs @@ -0,0 +1,16 @@ +#![no_std] +#![no_main] + +extern crate user_lib; + +use user_lib::{ + println, task_info, TaskInfo, +}; + +#[no_mangle] +pub fn main() -> usize { + let info = TaskInfo::new(); + assert_eq!(0, task_info(&info)); + println!("task_info {:?}", info); + 0 +} diff --git a/user/src/lib.rs b/user/src/lib.rs index 1491afc..5dc26ae 100644 --- a/user/src/lib.rs +++ b/user/src/lib.rs @@ -45,3 +45,35 @@ pub fn yield_() -> isize { pub fn get_time() -> isize { sys_get_time() } + + +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum TaskStatus { + UnInit, + Ready, + Running, + Exited, +} + +const MAX_SYSCALL_NUM: usize = 500; + +#[derive(Debug)] +pub struct TaskInfo { + pub status: TaskStatus, + pub syscall_times: [u32; MAX_SYSCALL_NUM], + pub time: usize, +} + +impl TaskInfo { + pub fn new() -> Self { + TaskInfo { + status: TaskStatus::UnInit, + syscall_times: [0; MAX_SYSCALL_NUM], + time: 0, + } + } +} + +pub fn task_info(info: &TaskInfo) -> isize { + sys_task_info(info) +} diff --git a/user/src/syscall.rs b/user/src/syscall.rs index b009569..45ee63f 100644 --- a/user/src/syscall.rs +++ b/user/src/syscall.rs @@ -1,9 +1,12 @@ use core::arch::asm; +use crate::TaskInfo; + const SYSCALL_WRITE: usize = 64; const SYSCALL_EXIT: usize = 93; const SYSCALL_YIELD: usize = 124; const SYSCALL_GET_TIME: usize = 169; +pub const SYSCALL_TASK_INFO: usize = 410; fn syscall(id: usize, args: [usize; 3]) -> isize { let mut ret: isize; @@ -34,3 +37,7 @@ pub fn sys_yield() -> isize { pub fn sys_get_time() -> isize { syscall(SYSCALL_GET_TIME, [0, 0, 0]) } + +pub fn sys_task_info(info: &TaskInfo) -> isize { + syscall(SYSCALL_TASK_INFO, [info as *const _ as usize, 0, 0]) +} \ No newline at end of file