From c68fce31861606697fe2948b72281b9da072a9ba Mon Sep 17 00:00:00 2001 From: Dream <2036019675@qq.com> Date: Sun, 5 May 2024 22:29:38 +0800 Subject: [PATCH] =?UTF-8?q?finish=20ch3(lab1)=20=20=20=20=20=E5=8A=A0?= =?UTF-8?q?=E5=85=A5=E4=BA=86task=5Finfo=E7=B3=BB=E7=BB=9F=E8=B0=83?= =?UTF-8?q?=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- os/Makefile | 73 ++++----------------------------------- os/build.rs | 35 +++++++++---------- os/src/config.rs | 2 ++ os/src/syscall/mod.rs | 22 +++++++++++- os/src/syscall/process.rs | 16 +++++---- os/src/task/mod.rs | 63 ++++++++++++++++++++++++++++++++- os/src/task/task.rs | 5 +++ os/src/trap/mod.rs | 3 +- 8 files changed, 125 insertions(+), 94 deletions(-) diff --git a/os/Makefile b/os/Makefile index aed0c96..7bc97b0 100644 --- a/os/Makefile +++ b/os/Makefile @@ -2,82 +2,23 @@ TARGET := riscv64gc-unknown-none-elf MODE := release KERNEL_ELF := target/$(TARGET)/$(MODE)/os -KERNEL_BIN := $(KERNEL_ELF).bin -DISASM_TMP := target/$(TARGET)/$(MODE)/asm -OFFLINE := # BOARD -BOARD := qemu +BOARD ?= qemu SBI ?= rustsbi BOOTLOADER := ../bootloader/$(SBI)-$(BOARD).bin -# Building mode argument -ifeq ($(MODE), release) - MODE_ARG := --release -endif - -# KERNEL ENTRY -KERNEL_ENTRY_PA := 0x80200000 - -# Binutils -OBJDUMP := rust-objdump --arch-name=riscv64 -OBJCOPY := rust-objcopy --binary-architecture=riscv64 - -CHAPTER ?= $(shell git rev-parse --abbrev-ref HEAD | sed -E 's/ch([0-9])/\1/') -TEST ?= $(CHAPTER) -BASE ?= 1 - -# Disassembly -DISASM ?= -x - -build: env $(KERNEL_BIN) - -env: -ifeq ($(OFFLINE),) - (rustup target list | grep "riscv64gc-unknown-none-elf (installed)") || rustup target add $(TARGET) - cargo install cargo-binutils - rustup component add rust-src - rustup component add llvm-tools-preview -endif - -$(KERNEL_BIN): kernel - @$(OBJCOPY) $(KERNEL_ELF) --strip-all -O binary $@ - kernel: - @make -C ../user build TEST=$(TEST) CHAPTER=$(CHAPTER) BASE=$(BASE) - @echo Platform: $(BOARD) - @cargo build $(MODE_ARG) + cargo build --release clean: - @cargo clean - -disasm: kernel - @$(OBJDUMP) $(DISASM) $(KERNEL_ELF) | less - -disasm-vim: kernel - @$(OBJDUMP) $(DISASM) $(KERNEL_ELF) > $(DISASM_TMP) - @vim $(DISASM_TMP) - @rm $(DISASM_TMP) - -run: run-inner + cargo clean -run-inner: build - @qemu-system-riscv64 \ +run: kernel + timeout --foreground 30s qemu-system-riscv64 \ -machine virt \ -nographic \ -bios $(BOOTLOADER) \ - -device loader,file=$(KERNEL_BIN),addr=$(KERNEL_ENTRY_PA) - -debug: build - @tmux new-session -d \ - "qemu-system-riscv64 -machine virt -nographic -bios $(BOOTLOADER) -device loader,file=$(KERNEL_BIN),addr=$(KERNEL_ENTRY_PA) -s -S" && \ - tmux split-window -h "riscv64-unknown-elf-gdb -ex 'file $(KERNEL_ELF)' -ex 'set arch riscv:rv64' -ex 'target remote localhost:1234'" && \ - tmux -2 attach-session -d - -gdbserver: build - @qemu-system-riscv64 -machine virt -nographic -bios $(BOOTLOADER) -device loader,file=$(KERNEL_BIN),addr=$(KERNEL_ENTRY_PA) -s -S - -gdbclient: - @riscv64-unknown-elf-gdb -ex 'file $(KERNEL_ELF)' -ex 'set arch riscv:rv64' -ex 'target remote localhost:1234' + -kernel $(KERNEL_ELF) -.PHONY: build env kernel clean disasm disasm-vim run-inner gdbserver gdbclient +.PHONY: build kernel clean run diff --git a/os/build.rs b/os/build.rs index 92953d5..6c341c6 100644 --- a/os/build.rs +++ b/os/build.rs @@ -1,20 +1,17 @@ -//! Building applications linker - -use std::fs::{read_dir, File}; use std::io::{Result, Write}; +use std::fs::{File, read_dir}; fn main() { - println!("cargo:rerun-if-changed=../user/src/"); + println!("cargo:rerun-if-changed=../ci-user/user/src/"); println!("cargo:rerun-if-changed={}", TARGET_PATH); insert_app_data().unwrap(); } -static TARGET_PATH: &str = "../user/build/bin/"; +static TARGET_PATH: &str = "../ci-user/user/build/bin/"; -/// get app data and build linker fn insert_app_data() -> Result<()> { let mut f = File::create("src/link_app.S").unwrap(); - let mut apps: Vec<_> = read_dir("../user/build/bin/") + let mut apps: Vec<_> = read_dir("../ci-user/user/build/bin") .unwrap() .into_iter() .map(|dir_entry| { @@ -25,35 +22,35 @@ fn insert_app_data() -> Result<()> { .collect(); apps.sort(); - writeln!( - f, - r#" + writeln!(f, r#" .align 3 .section .data .global _num_app _num_app: - .quad {}"#, - apps.len() - )?; + .quad {}"#, apps.len())?; for i in 0..apps.len() { writeln!(f, r#" .quad app_{}_start"#, i)?; } writeln!(f, r#" .quad app_{}_end"#, apps.len() - 1)?; + writeln!(f, r#" + .global _app_names +_app_names:"#)?; + for app in apps.iter() { + writeln!(f, r#" .string "{}""#, app)?; + } + for (idx, app) in apps.iter().enumerate() { println!("app_{}: {}", idx, app); - writeln!( - f, - r#" + writeln!(f, r#" .section .data .global app_{0}_start .global app_{0}_end + .align 3 app_{0}_start: .incbin "{2}{1}.bin" -app_{0}_end:"#, - idx, app, TARGET_PATH - )?; +app_{0}_end:"#, idx, app, TARGET_PATH)?; } Ok(()) } diff --git a/os/src/config.rs b/os/src/config.rs index 6b134af..fd5ee03 100644 --- a/os/src/config.rs +++ b/os/src/config.rs @@ -17,6 +17,8 @@ pub const APP_SIZE_LIMIT: usize = 0x20000; /// the max number of syscall pub const MAX_SYSCALL_NUM: usize = 500; +/// current number of syscall +pub const CURR_SYSCALL_NUM: usize = 5; /// clock frequency pub const CLOCK_FREQ: usize = 12500000; /// the physical memory end diff --git a/os/src/syscall/mod.rs b/os/src/syscall/mod.rs index e6e8f98..014bfc0 100644 --- a/os/src/syscall/mod.rs +++ b/os/src/syscall/mod.rs @@ -20,12 +20,22 @@ const SYSCALL_YIELD: usize = 124; const SYSCALL_GET_TIME: usize = 169; /// taskinfo syscall const SYSCALL_TASK_INFO: usize = 410; +/// syscall tong +pub const SYSCALL_TONG: [usize; CURR_SYSCALL_NUM] = [ + SYSCALL_WRITE, + SYSCALL_EXIT, + SYSCALL_YIELD, + SYSCALL_GET_TIME, + SYSCALL_TASK_INFO, +]; mod fs; mod process; use fs::*; -use process::*; +pub use process::*; +use crate::config::CURR_SYSCALL_NUM; + /// handle syscall exception with `syscall_id` and other arguments pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize { match syscall_id { @@ -37,3 +47,13 @@ pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize { _ => panic!("Unsupported syscall_id: {}", syscall_id), } } + +// pub fn tong_map(syscall_id: usize) -> usize { +// if let Some(id) = SYSCALL_TONG +// .iter() +// .find(|&val| syscall_id == *val) { +// *id +// } else { +// panic!() +// } +// } \ No newline at end of file diff --git a/os/src/syscall/process.rs b/os/src/syscall/process.rs index f1cd424..df76827 100644 --- a/os/src/syscall/process.rs +++ b/os/src/syscall/process.rs @@ -1,14 +1,17 @@ //! Process management syscalls use crate::{ config::MAX_SYSCALL_NUM, - task::{exit_current_and_run_next, suspend_current_and_run_next, TaskStatus}, + task::{exit_current_and_run_next, get_current_info, suspend_current_and_run_next, TaskStatus}, timer::get_time_us, }; #[repr(C)] #[derive(Debug)] +/// time pub struct TimeVal { + /// s pub sec: usize, + /// us pub usec: usize, } @@ -16,11 +19,11 @@ pub struct TimeVal { #[allow(dead_code)] pub struct TaskInfo { /// Task status in it's life cycle - status: TaskStatus, + pub status: TaskStatus, /// The numbers of syscall called by task - syscall_times: [u32; MAX_SYSCALL_NUM], + pub syscall_times: [u32; MAX_SYSCALL_NUM], /// Total running time of task - time: usize, + pub time: usize, } /// task exits and submit an exit code @@ -51,7 +54,8 @@ pub fn sys_get_time(ts: *mut TimeVal, _tz: usize) -> isize { } /// YOUR JOB: Finish sys_task_info to pass testcases -pub fn sys_task_info(_ti: *mut TaskInfo) -> isize { +pub fn sys_task_info(ti: *mut TaskInfo) -> isize { trace!("kernel: sys_task_info"); - -1 + get_current_info(ti); + 0 } diff --git a/os/src/task/mod.rs b/os/src/task/mod.rs index c1636ef..4451520 100644 --- a/os/src/task/mod.rs +++ b/os/src/task/mod.rs @@ -14,9 +14,11 @@ mod switch; #[allow(clippy::module_inception)] mod task; -use crate::config::MAX_APP_NUM; +use crate::config::{CURR_SYSCALL_NUM, MAX_SYSCALL_NUM, MAX_APP_NUM}; use crate::loader::{get_num_app, init_app_cx}; use crate::sync::UPSafeCell; +use crate::syscall::{SYSCALL_TONG, TaskInfo}; +use crate::timer::get_time_ms; use lazy_static::*; use switch::__switch; pub use task::{TaskControlBlock, TaskStatus}; @@ -54,6 +56,8 @@ lazy_static! { let mut tasks = [TaskControlBlock { task_cx: TaskContext::zero_init(), task_status: TaskStatus::UnInit, + syscall_times: [0; CURR_SYSCALL_NUM], + start_time: -1 }; MAX_APP_NUM]; for (i, task) in tasks.iter_mut().enumerate() { task.task_cx = TaskContext::goto_restore(init_app_cx(i)); @@ -81,6 +85,14 @@ impl TaskManager { let task0 = &mut inner.tasks[0]; task0.task_status = TaskStatus::Running; let next_task_cx_ptr = &task0.task_cx as *const TaskContext; + + // 初始化第一个task0的启动时间 + if task0.start_time == -1 { + task0.start_time = get_time_ms() as isize; + } else { + panic!("task0 is running"); + } + drop(inner); let mut _unused = TaskContext::zero_init(); // before this, we should drop local variables that must be dropped manually @@ -122,6 +134,12 @@ impl TaskManager { let mut inner = self.inner.exclusive_access(); let current = inner.current_task; inner.tasks[next].task_status = TaskStatus::Running; + + // 如果该任务是第一次运行初始化它的起始时间 + if inner.tasks[next].start_time == -1 { + inner.tasks[next].start_time = get_time_ms() as isize; + } + inner.current_task = next; let current_task_cx_ptr = &mut inner.tasks[current].task_cx as *mut TaskContext; let next_task_cx_ptr = &inner.tasks[next].task_cx as *const TaskContext; @@ -135,6 +153,39 @@ impl TaskManager { panic!("All applications completed!"); } } + + fn add_current_syscall_times(&self, syscall_id: usize) { + if let Some((id, _)) = SYSCALL_TONG + .iter() + .enumerate() + .find(|(_, &val)| syscall_id == val) + { + let mut inner = self.inner.exclusive_access(); + let current = inner.current_task; + inner.tasks[current].syscall_times[id] += 1; + } else { + panic!("Unsupported syscall_id: {}", syscall_id); + } + } + + fn get_current_info(&self, ti: *mut TaskInfo) { + let inner = self.inner.exclusive_access(); + let current = &inner.tasks[inner.current_task]; + let status = current.task_status; + let mut syscall_times = [0; MAX_SYSCALL_NUM]; + current.syscall_times.iter().enumerate().for_each(|(id, cnt)| { + let syscall_id = SYSCALL_TONG[id]; + syscall_times[syscall_id] = *cnt; + }); + let time = get_time_ms() - current.start_time as usize; + unsafe{ + *ti = TaskInfo { + status, + syscall_times, + time + }; + } + } } /// Run the first task in task list. @@ -158,6 +209,16 @@ fn mark_current_exited() { TASK_MANAGER.mark_current_exited(); } +/// Add syscall times of current 'Running' task +pub fn add_current_syscall_times(syscall_id: usize) { + TASK_MANAGER.add_current_syscall_times(syscall_id); +} + +/// Get info of current task +pub fn get_current_info(ti: *mut TaskInfo) { + TASK_MANAGER.get_current_info(ti); +} + /// Suspend the current 'Running' task and run the next task in task list. pub fn suspend_current_and_run_next() { mark_current_suspended(); diff --git a/os/src/task/task.rs b/os/src/task/task.rs index e6580c9..73f70cd 100644 --- a/os/src/task/task.rs +++ b/os/src/task/task.rs @@ -1,6 +1,7 @@ //! Types related to task management use super::TaskContext; +use crate::config::CURR_SYSCALL_NUM; /// The task control block (TCB) of a task. #[derive(Copy, Clone)] @@ -9,6 +10,10 @@ pub struct TaskControlBlock { pub task_status: TaskStatus, /// The task context pub task_cx: TaskContext, + /// The numbers of syscall called by task + pub syscall_times: [u32; CURR_SYSCALL_NUM], + /// Total running time of task + pub start_time: isize } /// The status of a task diff --git a/os/src/trap/mod.rs b/os/src/trap/mod.rs index d8f8e24..a1269b3 100644 --- a/os/src/trap/mod.rs +++ b/os/src/trap/mod.rs @@ -15,7 +15,7 @@ mod context; use crate::syscall::syscall; -use crate::task::{exit_current_and_run_next, suspend_current_and_run_next}; +use crate::task::{add_current_syscall_times, exit_current_and_run_next, suspend_current_and_run_next}; use crate::timer::set_next_trigger; use core::arch::global_asm; use riscv::register::{ @@ -54,6 +54,7 @@ pub fn trap_handler(cx: &mut TrapContext) -> &mut TrapContext { // jump to next instruction anyway cx.sepc += 4; // get system call return value + add_current_syscall_times(cx.x[17]); cx.x[10] = syscall(cx.x[17], [cx.x[10], cx.x[11], cx.x[12]]) as usize; } Trap::Exception(Exception::StoreFault) | Trap::Exception(Exception::StorePageFault) => {