Skip to content

Commit

Permalink
finish ch3(lab1)
Browse files Browse the repository at this point in the history
    加入了task_info系统调用
  • Loading branch information
Eternal60f3 committed May 5, 2024
1 parent d37f7bd commit c68fce3
Show file tree
Hide file tree
Showing 8 changed files with 125 additions and 94 deletions.
73 changes: 7 additions & 66 deletions os/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
35 changes: 16 additions & 19 deletions os/build.rs
Original file line number Diff line number Diff line change
@@ -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| {
Expand All @@ -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(())
}
2 changes: 2 additions & 0 deletions os/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
22 changes: 21 additions & 1 deletion os/src/syscall/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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!()
// }
// }
16 changes: 10 additions & 6 deletions os/src/syscall/process.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
//! 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,
}

/// Task information
#[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
Expand Down Expand Up @@ -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
}
63 changes: 62 additions & 1 deletion os/src/task/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand All @@ -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.
Expand All @@ -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();
Expand Down
5 changes: 5 additions & 0 deletions os/src/task/task.rs
Original file line number Diff line number Diff line change
@@ -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)]
Expand All @@ -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
Expand Down
3 changes: 2 additions & 1 deletion os/src/trap/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand Down Expand Up @@ -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) => {
Expand Down

0 comments on commit c68fce3

Please sign in to comment.