From 78006a94351030f2a08ee945f22aa00fbaba08ba Mon Sep 17 00:00:00 2001 From: ChenRuiwei <1982833213@qq.com> Date: Fri, 26 Jul 2024 15:20:07 +0800 Subject: [PATCH 1/7] refactor(pipe): pipe can have dynamic len --- crates/ring-buffer/src/lib.rs | 8 ++++---- kernel/src/syscall/fs.rs | 4 ++-- kernel/src/syscall/net.rs | 3 ++- modules/vfs/src/pipefs.rs | 10 +++++----- user/src/bin/final_tests.rs | 6 +++--- 5 files changed, 16 insertions(+), 15 deletions(-) diff --git a/crates/ring-buffer/src/lib.rs b/crates/ring-buffer/src/lib.rs index 793dd482..4d4bc2ad 100644 --- a/crates/ring-buffer/src/lib.rs +++ b/crates/ring-buffer/src/lib.rs @@ -14,7 +14,7 @@ enum RingBufferState { Normal, } -pub struct RingBuffer { +pub struct RingBuffer { arr: Vec, // NOTE: When and only when `head` equals `tail`, `state` can only be `Full` or `Empty`. head: usize, @@ -22,10 +22,10 @@ pub struct RingBuffer { state: RingBufferState, } -impl RingBuffer { - pub fn new() -> Self { +impl RingBuffer { + pub fn new(len: usize) -> Self { Self { - arr: vec![0; N], + arr: vec![0; len], head: 0, tail: 0, state: RingBufferState::Empty, diff --git a/kernel/src/syscall/fs.rs b/kernel/src/syscall/fs.rs index b670ee5e..4ae1e9c8 100644 --- a/kernel/src/syscall/fs.rs +++ b/kernel/src/syscall/fs.rs @@ -8,7 +8,7 @@ use core::{ use arch::time::get_time_duration; use async_utils::{dyn_future, Async, Select2Futures, SelectOutput}; -use config::board::BLOCK_SIZE; +use config::{board::BLOCK_SIZE, fs::PIPE_BUF_LEN}; use driver::BLOCK_DEVICE; use memory::VirtAddr; use strum::FromRepr; @@ -514,7 +514,7 @@ impl Syscall<'_> { let task = self.task; let flags = OpenFlags::from_bits(flags) .unwrap_or_else(|| unimplemented!("unknown flags, should add them")); - let (pipe_read, pipe_write) = new_pipe(); + let (pipe_read, pipe_write) = new_pipe(PIPE_BUF_LEN); let pipe = task.with_mut_fd_table(|table| { let fd_read = table.alloc(pipe_read, flags)?; let fd_write = table.alloc(pipe_write, flags)?; diff --git a/kernel/src/syscall/net.rs b/kernel/src/syscall/net.rs index 322e6294..51cd3488 100644 --- a/kernel/src/syscall/net.rs +++ b/kernel/src/syscall/net.rs @@ -8,6 +8,7 @@ use socket::*; use systype::{SysError, SysResult, SyscallResult}; use vfs::pipefs::new_pipe; use vfs_core::OpenFlags; +use virtio_drivers::PAGE_SIZE; use super::Syscall; use crate::{ @@ -314,7 +315,7 @@ impl Syscall<'_> { sv: UserWritePtr<[u32; 2]>, ) -> SyscallResult { let task = self.task; - let (pipe_read, pipe_write) = new_pipe(); + let (pipe_read, pipe_write) = new_pipe(PAGE_SIZE); let pipe = task.with_mut_fd_table(|table| { let fd_read = table.alloc(pipe_read, OpenFlags::empty())?; let fd_write = table.alloc(pipe_write, OpenFlags::empty())?; diff --git a/modules/vfs/src/pipefs.rs b/modules/vfs/src/pipefs.rs index 6427834a..85ab2709 100644 --- a/modules/vfs/src/pipefs.rs +++ b/modules/vfs/src/pipefs.rs @@ -26,7 +26,7 @@ pub struct PipeInode { pub struct PipeInodeInner { is_write_closed: bool, is_read_closed: bool, - ring_buffer: RingBuffer, + ring_buffer: RingBuffer, // WARN: `Waker` may not wake the task exactly, it may be abandoned. // Rust only guarentees that waker will wake the task from the last poll where the waker is // passed in. @@ -37,12 +37,12 @@ pub struct PipeInodeInner { } impl PipeInode { - pub fn new() -> Arc { + pub fn new(len: usize) -> Arc { let meta = InodeMeta::new(InodeMode::FIFO, Arc::::new_uninit(), PIPE_BUF_LEN); let inner = Mutex::new(PipeInodeInner { is_write_closed: false, is_read_closed: false, - ring_buffer: RingBuffer::new(), + ring_buffer: RingBuffer::new(len), read_waker: VecDeque::new(), write_waker: VecDeque::new(), }); @@ -293,8 +293,8 @@ impl File for PipeReadFile { } } -pub fn new_pipe() -> (Arc, Arc) { - let pipe_inode = PipeInode::new(); +pub fn new_pipe(len: usize) -> (Arc, Arc) { + let pipe_inode = PipeInode::new(len); let read_end = PipeReadFile::new(pipe_inode.clone()); let write_end = PipeWriteFile::new(pipe_inode); (read_end, write_end) diff --git a/user/src/bin/final_tests.rs b/user/src/bin/final_tests.rs index 91acfa2e..7b45d10e 100644 --- a/user/src/bin/final_tests.rs +++ b/user/src/bin/final_tests.rs @@ -10,12 +10,12 @@ use user_lib::{execve, fork, wait, waitpid}; #[macro_use] extern crate user_lib; -const TESTCASES: [&str; 12] = [ +const TESTCASES: [&str; 10] = [ "time-test", "busybox_testcode.sh", "lua_testcode.sh", - "netperf_testcode.sh", - "cyclictest_testcode.sh", + // "netperf_testcode.sh", + // "cyclictest_testcode.sh", "./test-ltp.sh ltp/testcases/bin/abs01", "./test-ltp.sh ltp/testcases/bin/read01", "libc-bench", From 04944f21df24244adbe9687cf4a26ea5e073e673 Mon Sep 17 00:00:00 2001 From: ChenRuiwei <1982833213@qq.com> Date: Fri, 26 Jul 2024 15:29:09 +0800 Subject: [PATCH 2/7] feat(time): print time cost periodicly --- kernel/src/main.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 62f18109..49b74c50 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -31,6 +31,7 @@ use core::{ sync::atomic::{AtomicBool, Ordering}, }; +use arch::time::get_time_duration; use driver::BLOCK_DEVICE; use executor::task_len; use timer::timelimited_task::ksleep_s; @@ -84,12 +85,12 @@ fn rust_main(hart_id: usize, dtb_addr: usize) { // ksleep_s(3).await; // } // }); - // task::spawn_kernel_task(async move { - // loop { - // log::error!("task counts {}", task_len()); - // ksleep_s(3).await; - // } - // }); + task::spawn_kernel_task(async move { + loop { + log::error!("current time {:?}", get_time_duration()); + ksleep_s(5).await; + } + }); #[cfg(feature = "smp")] boot::start_harts(hart_id); From c128c84dc18ebc405c2d81ee8bb5b2c215196906 Mon Sep 17 00:00:00 2001 From: ChenRuiwei <1982833213@qq.com> Date: Fri, 26 Jul 2024 15:54:26 +0800 Subject: [PATCH 3/7] refactor(user): refactor user_lib --- modules/page/src/buffer_cache.rs | 1 - user/src/bin/exec_test.rs | 92 ---------- user/src/bin/final_tests.rs | 24 +-- user/src/bin/init_proc.rs | 15 +- user/src/bin/preliminary_tests.rs | 8 +- user/src/bin/shell.rs | 293 ------------------------------ user/src/lib.rs | 17 +- 7 files changed, 24 insertions(+), 426 deletions(-) delete mode 100644 user/src/bin/exec_test.rs delete mode 100644 user/src/bin/shell.rs diff --git a/modules/page/src/buffer_cache.rs b/modules/page/src/buffer_cache.rs index 260fae15..7806ed82 100644 --- a/modules/page/src/buffer_cache.rs +++ b/modules/page/src/buffer_cache.rs @@ -31,7 +31,6 @@ pub struct BufferCache { // block data. pub pages: LruCache>, /// Block idx to `BufferHead`. - // TODO: add lru support, otherwise may occupy too much heap space // NOTE: Stores all accesses to block device. Some of them will be attached // to pages above, while others with file related will be attached to pages // stored in address space. diff --git a/user/src/bin/exec_test.rs b/user/src/bin/exec_test.rs deleted file mode 100644 index 8a88d36c..00000000 --- a/user/src/bin/exec_test.rs +++ /dev/null @@ -1,92 +0,0 @@ -#![no_std] -#![no_main] - -extern crate user_lib; - -extern crate alloc; - -use user_lib::{execve, fork, println, wait}; - -#[no_mangle] -fn main() -> i32 { - println!("begin exec_test"); - let tests = [ - "brk", - "chdir", - "clone", - "close", - "dup", - "dup2", - "execve", - "exit", - "fork", - "fstat", - "getcwd", - "getdents", - "getpid", - "getppid", - "gettimeofday", - "mkdir_", - "mmap", - "mnt", - "mount", - "munmap", - "open", - "openat", - "pipe", - "read", - "run-all.sh", - "sleep", - "test_echo", - "text.txt", - "times", - "umount", - "uname", - "unlink", - "wait", - "waitpid", - "write", - "yield", - ]; - if fork() == 0 { - execve( - "busybox\0", - &[ - "busybox\0".as_ptr(), - "sh\0".as_ptr(), - core::ptr::null::(), - ], - &[ - "PATH=/:/bin:/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin:\0".as_ptr(), - "LD_LIBRARY_PATH=/:/lib:/lib64/lp64d:/usr/lib:/usr/local/lib:\0".as_ptr(), - "TERM=screen\0".as_ptr(), - core::ptr::null::(), - ], - ); - } else { - heap_test(); - let mut wstatus: i32 = 0; - let pid = wait(&mut wstatus); - println!( - "[initproc] Released a zombie process, pid={}, wstatus={:#x}", - pid, wstatus, - ); - } - 0 -} - -fn heap_test() { - use alloc::{boxed::Box, vec::Vec}; - let a = Box::new(5); - assert_eq!(*a, 5); - drop(a); - let mut v: Vec = Vec::new(); - for i in 0..500 { - v.push(i); - } - for (i, val) in v.iter().take(500).enumerate() { - assert_eq!(*val, i); - } - drop(v); - println!("heap_test passed"); -} diff --git a/user/src/bin/final_tests.rs b/user/src/bin/final_tests.rs index 7b45d10e..e2c706ef 100644 --- a/user/src/bin/final_tests.rs +++ b/user/src/bin/final_tests.rs @@ -28,18 +28,11 @@ const TESTCASES: [&str; 10] = [ fn run_cmd(cmd: &str) { if fork() == 0 { execve( - "busybox\0", + "busybox", + &["busybox", "sh", "-c", cmd], &[ - "busybox\0".as_ptr(), - "sh\0".as_ptr(), - "-c\0".as_ptr(), - cmd.as_ptr(), - core::ptr::null::(), - ], - &[ - "PATH=/:/bin\0".as_ptr(), - "LD_LIBRARY_PATH=/:/lib:/lib/glibc/:/lib/musl\0".as_ptr(), - core::ptr::null::(), + "PATH=/:/bin", + "LD_LIBRARY_PATH=/:/lib:/lib/glibc/:/lib/musl", ], ); } else { @@ -50,12 +43,11 @@ fn run_cmd(cmd: &str) { #[no_mangle] fn main() -> i32 { - run_cmd("busybox touch sort.src\0"); - run_cmd("busybox cp /lib/dlopen_dso.so dlopen_dso.so\0"); + run_cmd("busybox touch sort.src"); + run_cmd("busybox cp /lib/dlopen_dso.so dlopen_dso.so"); if fork() == 0 { - for testcase in TESTCASES { - let testname = testcase.to_string() + "\0"; - run_cmd(&testname); + for test in TESTCASES { + run_cmd(&test); } } else { loop { diff --git a/user/src/bin/init_proc.rs b/user/src/bin/init_proc.rs index 134dd8f1..1b4d8a5c 100644 --- a/user/src/bin/init_proc.rs +++ b/user/src/bin/init_proc.rs @@ -9,17 +9,12 @@ use user_lib::{execve, fork, println, wait}; fn main() -> i32 { if fork() == 0 { execve( - "busybox\0", + "busybox", + &["busybox", "sh"], &[ - "busybox\0".as_ptr(), - "sh\0".as_ptr(), - core::ptr::null::(), - ], - &[ - "PATH=/:/bin\0".as_ptr(), - "LD_LIBRARY_PATH=/:/lib:/lib/glibc/:/lib/musl\0".as_ptr(), - "TERM=screen\0".as_ptr(), - core::ptr::null::(), + "PATH=/:/bin", + "LD_LIBRARY_PATH=/:/lib:/lib/glibc/:/lib/musl", + "TERM=screen", ], ); } else { diff --git a/user/src/bin/preliminary_tests.rs b/user/src/bin/preliminary_tests.rs index 5e2daf1e..2f633c9b 100644 --- a/user/src/bin/preliminary_tests.rs +++ b/user/src/bin/preliminary_tests.rs @@ -54,13 +54,7 @@ fn main() -> i32 { for testcase in TESTCASES { let pid = fork(); if pid == 0 { - let testname = testcase.to_string() + "\0"; - if execve( - &testname, - &[testname.as_ptr(), core::ptr::null::()], - &[core::ptr::null::()], - ) != 0 - { + if execve(testcase, &[testcase], &[]) != 0 { println!("Error when executing!"); return 0; } diff --git a/user/src/bin/shell.rs b/user/src/bin/shell.rs deleted file mode 100644 index 552c0c8c..00000000 --- a/user/src/bin/shell.rs +++ /dev/null @@ -1,293 +0,0 @@ -#![no_std] -#![no_main] -#![allow(clippy::println_empty_string)] - -extern crate alloc; - -#[macro_use] -extern crate user_lib; - -const LF: u8 = 0x0au8; -const CR: u8 = 0x0du8; -const DL: u8 = 0x7fu8; -const BS: u8 = 0x08u8; -const LINE_START: &str = ">> "; - -use alloc::{ - string::{String, ToString}, - vec::Vec, -}; - -use user_lib::{ - close, console::getchar, dup, execve, exit, fork, openat, pipe, types::OpenFlags, waitpid, -}; - -#[derive(Debug)] -struct ProcessArguments { - input: String, - output: String, - args_copy: Vec, - args_addr: Vec<*const u8>, -} - -impl ProcessArguments { - pub fn new(command: &str) -> Self { - let args: Vec<_> = command.split(' ').collect(); - let mut args_copy: Vec = args - .iter() - .filter(|&arg| !arg.is_empty()) - .map(|&arg| { - let mut string = String::new(); - string.push_str(arg); - string.push('\0'); - string - }) - .collect(); - - // redirect input - let mut input = String::new(); - if let Some((idx, _)) = args_copy - .iter() - .enumerate() - .find(|(_, arg)| arg.as_str() == "<\0") - { - input = args_copy[idx + 1].clone(); - args_copy.drain(idx..=idx + 1); - } - - // redirect output - let mut output = String::new(); - if let Some((idx, _)) = args_copy - .iter() - .enumerate() - .find(|(_, arg)| arg.as_str() == ">\0") - { - output = args_copy[idx + 1].clone(); - args_copy.drain(idx..=idx + 1); - } - - let mut args_addr: Vec<*const u8> = args_copy.iter().map(|arg| arg.as_ptr()).collect(); - args_addr.push(core::ptr::null::()); - - Self { - input, - output, - args_copy, - args_addr, - } - } -} - -const PRELIMINARY_TESTS: [&str; 32] = [ - "getdents", - "brk", - "chdir", - "clone", - "close", - "dup2", - "dup", - "sleep", - "execve", - "exit", - "fork", - "fstat", - "getcwd", - "getpid", - "getppid", - "gettimeofday", - "mkdir_", - "mmap", - "mount", - "open", - "pipe", - "read", - "times", - "umount", - "uname", - "unlink", - "wait", - "waitpid", - "write", - "yield", - "munmap", - "openat", -]; - -#[allow(unused)] -fn preliminary_test() { - print!("---------- START TO RUN PRELIMINARY TEST -----------\n"); - println!(""); - for test in PRELIMINARY_TESTS { - let pid = fork(); - if pid == 0 { - // println!("==== start to test {} ====", test); - let test = test.to_string() + "\0"; - if execve( - &test, - &[test.as_ptr(), core::ptr::null::()], - &[core::ptr::null::()], - ) != 0 - { - println!("Error when executing!"); - return; - } - } else { - let mut exit_code: i32 = 0; - let exit_pid = waitpid(pid as usize, &mut exit_code); - assert_eq!(pid, exit_pid); - } - } - exit(0); -} - -#[no_mangle] -pub fn main() -> i32 { - println!("Rust user shell"); - let mut line: String = String::new(); - - #[cfg(feature = "preliminary")] - preliminary_test(); - - print!("{}", LINE_START); - loop { - let c = getchar(); - match c { - LF | CR => { - println!(""); - if !line.is_empty() { - let splited: Vec<_> = line.as_str().split('|').collect(); - let process_arguments_list: Vec<_> = splited - .iter() - .map(|&cmd| ProcessArguments::new(cmd)) - .collect(); - let mut valid = true; - for (i, process_args) in process_arguments_list.iter().enumerate() { - if i == 0 { - if !process_args.output.is_empty() { - valid = false; - } - } else if i == process_arguments_list.len() - 1 { - if !process_args.input.is_empty() { - valid = false; - } - } else if !process_args.output.is_empty() || !process_args.input.is_empty() - { - valid = false; - } - } - if process_arguments_list.len() == 1 { - valid = true; - } - if !valid { - println!("Invalid command: Inputs/Outputs cannot be correctly binded!"); - } else { - // create pipes - let mut pipes_fd: Vec<[i32; 2]> = Vec::new(); - if !process_arguments_list.is_empty() { - for _ in 0..process_arguments_list.len() - 1 { - let mut pipe_fd = [0i32; 2]; - pipe(&mut pipe_fd); - pipes_fd.push(pipe_fd); - } - } - let mut children: Vec<_> = Vec::new(); - for (i, process_argument) in process_arguments_list.iter().enumerate() { - let pid = fork(); - if pid == 0 { - let input = &process_argument.input; - let output = &process_argument.output; - let args_copy = &process_argument.args_copy; - let args_addr = &process_argument.args_addr; - // redirect input - if !input.is_empty() { - let input_fd = openat(input.as_str(), OpenFlags::O_RDONLY); - if input_fd == -1 { - println!("Error when opening file {}", input); - return -4; - } - let input_fd = input_fd as usize; - close(0); - assert_eq!(dup(input_fd), 0); - close(input_fd); - } - // redirect output - if !output.is_empty() { - let output_fd = openat( - output.as_str(), - OpenFlags::O_CREATE | OpenFlags::O_WRONLY, - ); - if output_fd == -1 { - println!("Error when opening file {}", output); - return -4; - } - let output_fd = output_fd as usize; - close(1); - assert_eq!(dup(output_fd), 1); - close(output_fd); - } - // receive input from the previous process - if i > 0 { - close(0); - let read_end = pipes_fd.get(i - 1).unwrap()[0]; - assert_eq!(dup(read_end as usize), 0); - } - // send output to the next process - if i < process_arguments_list.len() - 1 { - close(1); - let write_end = pipes_fd.get(i).unwrap()[1]; - assert_eq!(dup(write_end as usize), 1); - } - // close all pipe ends inherited from the parent process - for pipe_fd in pipes_fd.iter() { - close(pipe_fd[0] as usize); - close(pipe_fd[1] as usize); - } - // execute new application - // println!("args 0 addr {:#x}", args_addr[0] as usize); - // println!("args copy 0 addr {:#x}", args_copy[0].as_ptr() as - // usize); - if execve( - args_copy[0].as_str(), - args_addr.as_slice(), - &[core::ptr::null::()], - ) != 0 - { - println!("Error when executing!"); - return -4; - } - unreachable!(); - } else { - children.push(pid); - } - } - for pipe_fd in pipes_fd.iter() { - close(pipe_fd[0] as usize); - close(pipe_fd[1] as usize); - } - let mut exit_code: i32 = 0; - for pid in children.into_iter() { - let exit_pid = waitpid(pid as usize, &mut exit_code); - assert_eq!(pid, exit_pid); - // println!("Shell: Process {} exited with code {}", - // pid, exit_code); - } - } - line.clear(); - } - print!("{}", LINE_START); - } - BS | DL => { - if !line.is_empty() { - print!("{}", BS as char); - print!(" "); - print!("{}", BS as char); - line.pop(); - } - } - _ => { - print!("{}", c as char); - line.push(c as char); - } - } - } -} diff --git a/user/src/lib.rs b/user/src/lib.rs index f4d92e6d..e39444a8 100644 --- a/user/src/lib.rs +++ b/user/src/lib.rs @@ -15,7 +15,7 @@ pub mod types; extern crate bitflags; extern crate alloc; -use alloc::vec::Vec; +use alloc::{ffi::CString, vec::Vec}; use bitflags::Flags; use buddy_system_allocator::LockedHeap; @@ -162,12 +162,15 @@ pub fn create_thread(flags: CloneFlags) -> isize { pub fn kill(pid: isize, sig: Sig) -> isize { sys_kill(pid as usize, sig.raw() as i32) } -pub fn execve(cmd: &str, args: &[*const u8], env: &[*const u8]) -> isize { - sys_execve( - cmd.as_ptr(), - args.as_ptr() as *const usize, - env.as_ptr() as *const usize, - ) +pub fn execve(path: &str, argv: &[&str], envp: &[&str]) -> isize { + let path = CString::new(path).unwrap(); + let argv: Vec<_> = argv.iter().map(|s| CString::new(*s).unwrap()).collect(); + let envp: Vec<_> = envp.iter().map(|s| CString::new(*s).unwrap()).collect(); + let mut argv = argv.iter().map(|s| s.as_ptr() as usize).collect::>(); + let mut envp = envp.iter().map(|s| s.as_ptr() as usize).collect::>(); + argv.push(0); + envp.push(0); + sys_execve(path.as_ptr() as *const u8, argv.as_ptr(), envp.as_ptr()) } pub fn wait(exit_code: &mut i32) -> isize { From c4dd75e76d502aa7aa887341fce1b7a992a0d52d Mon Sep 17 00:00:00 2001 From: ChenRuiwei <1982833213@qq.com> Date: Fri, 26 Jul 2024 18:22:04 +0800 Subject: [PATCH 4/7] fix(exit): parent exit without calling wait to clean zombie children should wake init proc --- crates/recycle-allocator/src/lib.rs | 4 +++ kernel/src/main.rs | 24 ++++++++++++----- kernel/src/task/manager.rs | 4 +++ kernel/src/task/mod.rs | 2 +- kernel/src/task/task.rs | 17 ++++++++++++ kernel/src/task/tid.rs | 2 +- kernel/src/trap/user_trap.rs | 40 ++++++++++++++++------------- modules/vfs/src/pipefs.rs | 19 +++++++++++--- user/src/bin/final_tests.rs | 6 ++--- 9 files changed, 84 insertions(+), 34 deletions(-) diff --git a/crates/recycle-allocator/src/lib.rs b/crates/recycle-allocator/src/lib.rs index 3daf0126..e8b8bf2c 100644 --- a/crates/recycle-allocator/src/lib.rs +++ b/crates/recycle-allocator/src/lib.rs @@ -44,4 +44,8 @@ impl RecycleAllocator { ); self.recycled.push(Reverse(id)); } + + pub fn recycled_len(&self) -> usize { + self.recycled.len() + } } diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 49b74c50..e904f16b 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -36,7 +36,10 @@ use driver::BLOCK_DEVICE; use executor::task_len; use timer::timelimited_task::ksleep_s; -use crate::{processor::hart, task::TASK_MANAGER}; +use crate::{ + processor::hart, + task::{TASK_MANAGER, TID_ALLOCATOR}, +}; extern crate alloc; @@ -85,12 +88,19 @@ fn rust_main(hart_id: usize, dtb_addr: usize) { // ksleep_s(3).await; // } // }); - task::spawn_kernel_task(async move { - loop { - log::error!("current time {:?}", get_time_duration()); - ksleep_s(5).await; - } - }); + // task::spawn_kernel_task(async move { + // loop { + // log::error!("current time {:?}", get_time_duration()); + // ksleep_s(5).await; + // } + // }); + // + // task::spawn_kernel_task(async move { + // loop { + // log::error!("current tid len {:?}", TASK_MANAGER.tasks()); + // ksleep_s(5).await; + // } + // }); #[cfg(feature = "smp")] boot::start_harts(hart_id); diff --git a/kernel/src/task/manager.rs b/kernel/src/task/manager.rs index ca9e3ef2..f0902e12 100644 --- a/kernel/src/task/manager.rs +++ b/kernel/src/task/manager.rs @@ -44,6 +44,10 @@ impl TaskManager { } } + pub fn tasks(&self) -> Vec> { + self.0.lock().values().map(|t| t.upgrade().unwrap()).collect() + } + pub fn for_each(&self, f: impl Fn(&Arc) -> SysResult<()>) -> SysResult<()> { for task in self.0.lock().values() { f(&task.upgrade().unwrap())? diff --git a/kernel/src/task/mod.rs b/kernel/src/task/mod.rs index 1f90bf1c..a1b51a90 100644 --- a/kernel/src/task/mod.rs +++ b/kernel/src/task/mod.rs @@ -13,7 +13,7 @@ use config::process::USER_STACK_SIZE; pub use manager::{PROCESS_GROUP_MANAGER, TASK_MANAGER}; pub use schedule::{spawn_kernel_task, spawn_user_task}; pub use task::Task; -pub use tid::{PGid, Pid, Tid}; +pub use tid::{PGid, Pid, Tid, TID_ALLOCATOR}; use vfs::sys_root_dentry; use vfs_core::Path; diff --git a/kernel/src/task/task.rs b/kernel/src/task/task.rs index 0ac2904d..b7412ecc 100644 --- a/kernel/src/task/task.rs +++ b/kernel/src/task/task.rs @@ -562,6 +562,23 @@ impl Task { "[Task::do_eixt] reparent child process pid {} to init", c.pid() ); + if c.is_zombie() { + // NOTE: self has not called wait to clear zombie children, we need to notify + // init to clear these zombie children. + init_proc.receive_siginfo( + SigInfo { + sig: Sig::SIGCHLD, + code: SigInfo::CLD_EXITED, + details: SigDetails::CHLD { + pid: c.pid(), + status: c.exit_code(), + utime: c.time_stat().user_time(), + stime: c.time_stat().sys_time(), + }, + }, + false, + ) + } *c.parent.lock() = Some(Arc::downgrade(&init_proc)); } init_proc.children.lock().extend(children.clone()); diff --git a/kernel/src/task/tid.rs b/kernel/src/task/tid.rs index b423f635..a08be79f 100644 --- a/kernel/src/task/tid.rs +++ b/kernel/src/task/tid.rs @@ -2,7 +2,7 @@ use config::process::INIT_PROC_PID; use recycle_allocator::RecycleAllocator; use sync::mutex::SpinNoIrqLock; -static TID_ALLOCATOR: SpinNoIrqLock = +pub static TID_ALLOCATOR: SpinNoIrqLock = SpinNoIrqLock::new(RecycleAllocator::new(INIT_PROC_PID)); pub type Tid = usize; diff --git a/kernel/src/trap/user_trap.rs b/kernel/src/trap/user_trap.rs index 1a3246e6..28b02d94 100644 --- a/kernel/src/trap/user_trap.rs +++ b/kernel/src/trap/user_trap.rs @@ -112,26 +112,30 @@ pub async fn trap_handler(task: &Arc) -> bool { } } } - Trap::Interrupt(Interrupt::SupervisorTimer) => { - // NOTE: user may trap into kernel frequently, as a consequence, this timer are - // likely not triggered in user mode but rather be triggered in supervisor mode, - // which will cause user program running on the cpu for a long time. - log::trace!("[trap_handler] timer interrupt, sepc {sepc:#x}"); - TIMER_MANAGER.check(get_time_duration()); - unsafe { set_next_timer_irq() }; - if executor::has_task() { - yield_now().await; + Trap::Interrupt(i) => { + match i { + Interrupt::SupervisorTimer => { + // NOTE: user may trap into kernel frequently, as a consequence, this timer are + // likely not triggered in user mode but rather be triggered in supervisor mode, + // which will cause user program running on the cpu for a long time. + log::trace!("[trap_handler] timer interrupt, sepc {sepc:#x}"); + TIMER_MANAGER.check(get_time_duration()); + unsafe { set_next_timer_irq() }; + if executor::has_task() { + yield_now().await; + } + } + Interrupt::SupervisorExternal => { + log::info!("[kernel] receive externel interrupt"); + driver::get_device_manager_mut().handle_irq(); + } + _ => { + panic!( + "[trap_handler] Unsupported trap {cause:?}, stval = {stval:#x}!, sepc = {sepc:#x}" + ); + } } } - Trap::Interrupt(Interrupt::SupervisorExternal) => { - log::info!("[kernel] receive externel interrupt"); - driver::get_device_manager_mut().handle_irq(); - } - _ => { - panic!( - "[trap_handler] Unsupported trap {cause:?}, stval = {stval:#x}!, sepc = {sepc:#x}" - ); - } } false } diff --git a/modules/vfs/src/pipefs.rs b/modules/vfs/src/pipefs.rs index 85ab2709..2a3dafbf 100644 --- a/modules/vfs/src/pipefs.rs +++ b/modules/vfs/src/pipefs.rs @@ -127,7 +127,10 @@ impl Drop for PipeWriteFile { .inode() .downcast_arc::() .unwrap_or_else(|_| unreachable!()); - log::info!("[PipeWriteFile::drop] pipe write end is closed"); + log::info!( + "[PipeWriteFile::drop] pipe ino {} write end is closed", + pipe.meta().ino + ); let mut inner = pipe.inner.lock(); inner.is_write_closed = true; while let Some(waker) = inner.read_waker.pop_front() { @@ -153,7 +156,10 @@ impl Drop for PipeReadFile { .inode() .downcast_arc::() .unwrap_or_else(|_| unreachable!()); - log::info!("[PipeReadFile::drop] pipe read end is closed"); + log::info!( + "[PipeReadFile::drop] pipe ino {} read end is closed", + pipe.meta().ino + ); let mut inner = pipe.inner.lock(); inner.is_read_closed = true; while let Some(waker) = inner.write_waker.pop_front() { @@ -177,7 +183,10 @@ impl File for PipeWriteFile { .inode() .downcast_arc::() .unwrap_or_else(|_| unreachable!()); - + log::info!( + "[PipeWriteFile::base_write_at] read pipe ino {}", + pipe.meta().ino + ); let revents = PipeWritePollFuture::new(pipe.clone(), PollEvents::OUT).await; if revents.contains(PollEvents::ERR) { return Err(SysError::EPIPE); @@ -254,6 +263,10 @@ impl File for PipeReadFile { .inode() .downcast_arc::() .unwrap_or_else(|_| unreachable!()); + log::info!( + "[PipeReadFile::base_read_at] read pipe ino {}", + pipe.meta().ino + ); let events = PollEvents::IN; let revents = PipeReadPollFuture::new(pipe.clone(), events).await; if revents.contains(PollEvents::HUP) { diff --git a/user/src/bin/final_tests.rs b/user/src/bin/final_tests.rs index e2c706ef..9a75843d 100644 --- a/user/src/bin/final_tests.rs +++ b/user/src/bin/final_tests.rs @@ -10,14 +10,12 @@ use user_lib::{execve, fork, wait, waitpid}; #[macro_use] extern crate user_lib; -const TESTCASES: [&str; 10] = [ +const TESTCASES: [&str; 9] = [ "time-test", "busybox_testcode.sh", "lua_testcode.sh", - // "netperf_testcode.sh", + "netperf_testcode.sh", // "cyclictest_testcode.sh", - "./test-ltp.sh ltp/testcases/bin/abs01", - "./test-ltp.sh ltp/testcases/bin/read01", "libc-bench", "libctest_testcode.sh", "iozone_testcode.sh", From 2c6afab505fc9b13edcbe3ffbe344296535e2d7e Mon Sep 17 00:00:00 2001 From: ChenRuiwei <1982833213@qq.com> Date: Fri, 26 Jul 2024 21:57:50 +0800 Subject: [PATCH 5/7] fix(wait4): wait4 should not depend on SIGCHLD since duplicate signals will be lost --- kernel/Cargo.toml | 1 + kernel/src/main.rs | 28 +++++------------------- kernel/src/mm/memory_space/mod.rs | 5 +++-- kernel/src/syscall/process.rs | 36 ++++++++++++++++++------------- kernel/src/task/mod.rs | 10 ++++----- kernel/src/task/task.rs | 31 +++++++++++++++++++++++--- kernel/src/trap/context.rs | 7 +++--- kernel/src/trap/user_trap.rs | 4 ++-- kernel/src/utils/mod.rs | 32 +++++++++++++++++++++++++++ 9 files changed, 100 insertions(+), 54 deletions(-) diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 3460b373..bee5fc39 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -51,3 +51,4 @@ config = { path = "../config" } strace = [] smp = [] preempt = [] +debug = [] diff --git a/kernel/src/main.rs b/kernel/src/main.rs index e904f16b..51f1d742 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -39,6 +39,7 @@ use timer::timelimited_task::ksleep_s; use crate::{ processor::hart, task::{TASK_MANAGER, TID_ALLOCATOR}, + utils::{print_proc_tree, spawn_debug_tasks}, }; extern crate alloc; @@ -75,33 +76,14 @@ fn rust_main(hart_id: usize, dtb_addr: usize) { trap::init(); driver::init(); vfs::init(); + + #[cfg(feature = "debug")] + utils::spawn_debug_tasks(print_proc_tree, 5); + task::spawn_kernel_task(async move { task::spawn_init_proc(); }); - // task::spawn_kernel_task(async move { - // loop { - // log::error!( - // "buffer head cnts {}", - // BLOCK_DEVICE.get().unwrap().buffer_head_cnts() - // ); - // ksleep_s(3).await; - // } - // }); - // task::spawn_kernel_task(async move { - // loop { - // log::error!("current time {:?}", get_time_duration()); - // ksleep_s(5).await; - // } - // }); - // - // task::spawn_kernel_task(async move { - // loop { - // log::error!("current tid len {:?}", TASK_MANAGER.tasks()); - // ksleep_s(5).await; - // } - // }); - #[cfg(feature = "smp")] boot::start_harts(hart_id); } else { diff --git a/kernel/src/mm/memory_space/mod.rs b/kernel/src/mm/memory_space/mod.rs index 23e9c330..3b9c25c5 100644 --- a/kernel/src/mm/memory_space/mod.rs +++ b/kernel/src/mm/memory_space/mod.rs @@ -242,8 +242,9 @@ impl MemorySpace { (entry, auxv) } - /// Check whether the elf file is dynamic linked and - /// if so, load the dl interpreter. + /// Check whether the elf file is dynamic linked and if so, load the dl + /// interpreter. + /// /// Return the interpreter's entry point(at the base of DL_INTERP_OFFSET) if /// so. pub fn load_dl_interp_if_needed(&mut self, elf: &ElfFile) -> Option { diff --git a/kernel/src/syscall/process.rs b/kernel/src/syscall/process.rs index 10eb08b5..13eea1ff 100644 --- a/kernel/src/syscall/process.rs +++ b/kernel/src/syscall/process.rs @@ -217,23 +217,29 @@ impl Syscall<'_> { task.set_running(); let si = task.with_mut_sig_pending(|pending| pending.get_expect(SigSet::SIGCHLD)); if let Some(info) = si { - if let SigDetails::CHLD { - pid, - status, - utime, - stime, - } = info.details - { - match target { - WaitFor::AnyChild => break (pid, status, utime, stime), - WaitFor::Pid(target_pid) => { - if target_pid == pid { - break (pid, status, utime, stime); - } + let children = task.children(); + let child = match target { + WaitFor::AnyChild => children + .values() + .find(|c| c.is_zombie() && c.with_thread_group(|tg| tg.len() == 1)), + WaitFor::Pid(pid) => { + let child = children.get(&pid).unwrap(); + if child.is_zombie() && child.with_thread_group(|tg| tg.len() == 1) { + Some(child) + } else { + None } - WaitFor::PGid(_) => unimplemented!(), - WaitFor::AnyChildInGroup => unimplemented!(), } + WaitFor::PGid(_) => unimplemented!(), + WaitFor::AnyChildInGroup => unimplemented!(), + }; + if let Some(child) = child { + break ( + child.pid(), + child.exit_code(), + child.time_stat_ref().user_time(), + child.time_stat_ref().sys_time(), + ); } } else { return Err(SysError::EINTR); diff --git a/kernel/src/task/mod.rs b/kernel/src/task/mod.rs index a1b51a90..183649de 100644 --- a/kernel/src/task/mod.rs +++ b/kernel/src/task/mod.rs @@ -6,7 +6,7 @@ pub mod signal; pub mod task; mod tid; -use alloc::{sync::Arc, vec::Vec}; +use alloc::{string::ToString, sync::Arc, vec, vec::Vec}; use async_utils::block_on; use config::process::USER_STACK_SIZE; @@ -25,7 +25,7 @@ use crate::{ pub fn spawn_init_proc() { let init_proc_path = "/init_proc"; - let argv = Vec::new(); + let args = vec![init_proc_path.to_string()]; let envp = Vec::new(); let file = Path::new(sys_root_dentry(), sys_root_dentry(), init_proc_path) @@ -37,14 +37,14 @@ pub fn spawn_init_proc() { let mut memory_space = MemorySpace::new_user(); unsafe { memory_space.switch_page_table() }; - let (entry, auxv) = memory_space.parse_and_map_elf(file, &elf_data); + let (entry, auxv) = memory_space.parse_and_map_elf(file.clone(), &elf_data); let sp_init = memory_space.alloc_stack_lazily(USER_STACK_SIZE); - let (sp, argc, argv, envp) = within_sum(|| init_stack(sp_init, argv, envp, auxv)); + let (sp, argc, argv, envp) = within_sum(|| init_stack(sp_init, args.clone(), envp, auxv)); memory_space.alloc_heap_lazily(); let trap_context = TrapContext::new(entry, sp); - let task = Task::new_init(memory_space, trap_context); + let task = Task::new_init(memory_space, trap_context, file, args); schedule::spawn_user_task(task); } diff --git a/kernel/src/task/task.rs b/kernel/src/task/task.rs index b7412ecc..67bd62a8 100644 --- a/kernel/src/task/task.rs +++ b/kernel/src/task/task.rs @@ -123,6 +123,10 @@ pub struct Task { tid_address: SyncUnsafeCell, cpus_allowed: SyncUnsafeCell, pgid: Shared, + /// Elf file it executes on. + elf: SyncUnsafeCell>, + /// + args: SyncUnsafeCell>, } impl core::fmt::Debug for Task { @@ -166,7 +170,16 @@ pub enum TaskState { impl Task { // you can use is_running() / set_running()、 is_zombie() / set_zombie() generate_state_methods!(Running, Zombie, Stopped, Interruptable, UnInterruptable); - generate_accessors!(waker: Option, tid_address: TidAddress, sig_mask: SigSet, sig_stack: Option, time_stat: TaskTimeStat, cpus_allowed: CpuMask); + generate_accessors!( + waker: Option, + tid_address: TidAddress, + sig_mask: SigSet, + sig_stack: Option, + time_stat: TaskTimeStat, + cpus_allowed: CpuMask, + elf: Arc, + args: Vec + ); generate_atomic_accessors!(exit_code: i32, sig_ucontext_ptr: usize); generate_with_methods!( fd_table: FdTable, @@ -181,7 +194,12 @@ impl Task { itimers: [ITimer;3] ); - pub fn new_init(memory_space: MemorySpace, trap_context: TrapContext) -> Arc { + pub fn new_init( + memory_space: MemorySpace, + trap_context: TrapContext, + elf_file: Arc, + args: Vec, + ) -> Arc { let tid = alloc_tid(); let pgid = tid.0; let task = Arc::new(Self { @@ -210,6 +228,8 @@ impl Task { cpus_allowed: SyncUnsafeCell::new(CpuMask::CPU_ALL), shm_ids: new_shared(BTreeMap::new()), pgid: new_shared(pgid), + elf: SyncUnsafeCell::new(elf_file), + args: SyncUnsafeCell::new(args), }); task.thread_group.lock().push(task.clone()); @@ -404,6 +424,8 @@ impl Task { // After a fork(2), the child inherits the attached shared memory segments. shm_ids, pgid, + elf: SyncUnsafeCell::new(self.elf_ref().clone()), + args: SyncUnsafeCell::new(self.args_ref().clone()), }); if !flags.contains(CloneFlags::THREAD) { @@ -430,7 +452,7 @@ impl Task { log::debug!("[Task::do_execve] parsing elf"); let mut memory_space = MemorySpace::new_user(); memory_space.set_task(&self.leader()); - let (mut entry, mut auxv) = memory_space.parse_and_map_elf(elf_file, elf_data); + let (mut entry, mut auxv) = memory_space.parse_and_map_elf(elf_file.clone(), elf_data); let elf = xmas_elf::ElfFile::new(elf_data).unwrap(); if let Some(interp_entry_point) = memory_space.load_dl_interp_if_needed(&elf) { @@ -466,6 +488,9 @@ impl Task { log::debug!("[Task::do_execve] allocing stack"); let sp_init = self.with_mut_memory_space(|m| m.alloc_stack_lazily(USER_STACK_SIZE)); + *self.elf() = elf_file; + *self.args() = argv.clone(); + let (sp, argc, argv, envp) = within_sum(|| init_stack(sp_init, argv, envp, auxv)); // alloc heap diff --git a/kernel/src/trap/context.rs b/kernel/src/trap/context.rs index 96f6881c..2df9a1f0 100644 --- a/kernel/src/trap/context.rs +++ b/kernel/src/trap/context.rs @@ -8,15 +8,15 @@ use riscv::register::sstatus::{FS, SPP}; #[derive(Clone, Copy, Debug)] #[repr(C)] pub struct TrapContext { - // User to kernel should save: - /// general regs[0..31] + // NOTE: User to kernel should save these: + /// General regs from x0 to x31. pub user_x: [usize; 32], /// CSR sstatus pub sstatus: Sstatus, // 32 /// CSR sepc pub sepc: usize, // 33 - // Kernel to user should save: + // NOTE: Kernel to user should save these: pub kernel_sp: usize, // 34 /// pub kernel_ra: usize, // 35 @@ -27,7 +27,6 @@ pub struct TrapContext { /// kernel hart address pub kernel_tp: usize, // 49 /// Float regs - /// TODO: add dirty flag to know whether we should save pub user_fx: UserFloatContext, pub last_a0: usize, diff --git a/kernel/src/trap/user_trap.rs b/kernel/src/trap/user_trap.rs index 28b02d94..f2558bac 100644 --- a/kernel/src/trap/user_trap.rs +++ b/kernel/src/trap/user_trap.rs @@ -115,9 +115,9 @@ pub async fn trap_handler(task: &Arc) -> bool { Trap::Interrupt(i) => { match i { Interrupt::SupervisorTimer => { - // NOTE: user may trap into kernel frequently, as a consequence, this timer are + // NOTE: User may trap into kernel frequently. As a consequence, this timer are // likely not triggered in user mode but rather be triggered in supervisor mode, - // which will cause user program running on the cpu for a long time. + // which will cause user program running on the cpu for a quite long time. log::trace!("[trap_handler] timer interrupt, sepc {sepc:#x}"); TIMER_MANAGER.check(get_time_duration()); unsafe { set_next_timer_irq() }; diff --git a/kernel/src/utils/mod.rs b/kernel/src/utils/mod.rs index 334e984f..7207fda0 100644 --- a/kernel/src/utils/mod.rs +++ b/kernel/src/utils/mod.rs @@ -1,3 +1,9 @@ +use alloc::{format, sync::Arc}; + +use timer::timelimited_task::ksleep_s; + +use crate::task::{self, Task, TASK_MANAGER}; + /// Code block that only runs in debug mode. #[macro_export] macro_rules! when_debug { @@ -18,3 +24,29 @@ pub fn exam_hash(buf: &[u8]) -> usize { } h } + +pub fn spawn_debug_tasks(f: F, interval_secs: usize) +where + F: FnOnce() + Send + Copy + 'static, +{ + task::spawn_kernel_task(async move { + let f = f; + loop { + f(); + ksleep_s(interval_secs).await; + } + }); +} + +pub fn print_proc_tree() { + fn print_helper(proc: Arc, level: usize, prefix: &str) { + let indent = " ".repeat(level * 4); + println!("{}{}{}", indent, prefix, proc.args_ref().join(" ")); + for (i, child) in proc.children().iter() { + print_helper(child.clone(), level + 1, &format!("P{i} -- ")); + } + } + + let init = TASK_MANAGER.init_proc(); + print_helper(init, 0, "P1 -- "); +} From 43d4b8a06415162108d563a37700c3df8c043a4d Mon Sep 17 00:00:00 2001 From: ChenRuiwei <1982833213@qq.com> Date: Fri, 26 Jul 2024 22:06:23 +0800 Subject: [PATCH 6/7] refactor(signal): remove SigDetails::CHLD --- kernel/src/task/signal.rs | 7 +------ kernel/src/task/task.rs | 14 ++------------ modules/signal/src/siginfo.rs | 8 -------- 3 files changed, 3 insertions(+), 26 deletions(-) diff --git a/kernel/src/task/signal.rs b/kernel/src/task/signal.rs index 8008054d..23257fd8 100644 --- a/kernel/src/task/signal.rs +++ b/kernel/src/task/signal.rs @@ -129,12 +129,7 @@ impl Task { SigInfo { sig: Sig::SIGCHLD, code, - details: SigDetails::CHLD { - pid: self.pid(), - status: signum.raw() as i32 & 0x7F, - utime: self.time_stat().user_time(), - stime: self.time_stat().sys_time(), - }, + details: SigDetails::None, }, false, ); diff --git a/kernel/src/task/task.rs b/kernel/src/task/task.rs index 67bd62a8..f0d168b1 100644 --- a/kernel/src/task/task.rs +++ b/kernel/src/task/task.rs @@ -594,12 +594,7 @@ impl Task { SigInfo { sig: Sig::SIGCHLD, code: SigInfo::CLD_EXITED, - details: SigDetails::CHLD { - pid: c.pid(), - status: c.exit_code(), - utime: c.time_stat().user_time(), - stime: c.time_stat().sys_time(), - }, + details: SigDetails::None, }, false, ) @@ -617,12 +612,7 @@ impl Task { SigInfo { sig: Sig::SIGCHLD, code: SigInfo::CLD_EXITED, - details: SigDetails::CHLD { - pid: self.pid(), - status: self.exit_code(), - utime: self.time_stat().user_time(), - stime: self.time_stat().sys_time(), - }, + details: SigDetails::None, }, false, ); diff --git a/modules/signal/src/siginfo.rs b/modules/signal/src/siginfo.rs index f6fec030..46e1af41 100644 --- a/modules/signal/src/siginfo.rs +++ b/modules/signal/src/siginfo.rs @@ -18,14 +18,6 @@ pub enum SigDetails { /// sender's pid pid: usize, }, - CHLD { - /// which child - pid: usize, - /// exit code - status: i32, - utime: Duration, - stime: Duration, - }, } #[allow(unused)] From 460a3f64f69db3c61eb4c66c5dfb2319a3e8db6d Mon Sep 17 00:00:00 2001 From: ChenRuiwei <1982833213@qq.com> Date: Sat, 27 Jul 2024 00:22:41 +0800 Subject: [PATCH 7/7] fix(time): fix clock_nanosleep bug and signal cause zombie state trap return to user bug --- Makefile | 1 + arch/src/riscv64/sstatus.rs | 4 ++++ kernel/Makefile | 3 +++ kernel/src/syscall/time.rs | 2 +- kernel/src/task/schedule.rs | 6 ++++++ kernel/src/trap/user_trap.rs | 2 ++ 6 files changed, 17 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 81a90e65..7c240815 100644 --- a/Makefile +++ b/Makefile @@ -44,6 +44,7 @@ TEST_DIR := ./testcase/$(TEST) export STRACE := export SMP := export PREEMPT := +export DEBUG := # Args DISASM_ARGS = -d diff --git a/arch/src/riscv64/sstatus.rs b/arch/src/riscv64/sstatus.rs index 9941347c..c20553cd 100644 --- a/arch/src/riscv64/sstatus.rs +++ b/arch/src/riscv64/sstatus.rs @@ -24,6 +24,10 @@ impl Sstatus { } } + pub fn sie(&mut self) -> bool { + self.bits.get_bit(1) + } + pub fn set_spie(&mut self, val: bool) { self.bits.set_bit(5, val); } diff --git a/kernel/Makefile b/kernel/Makefile index 366b7ce6..b24892d5 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -9,6 +9,9 @@ endif ifneq ($(PREEMPT), ) FEATURES += preempt endif +ifneq ($(DEBUG), ) + FEATURES += debug +endif CARGO_BUILD_ARGS := ifeq ($(MODE), release) diff --git a/kernel/src/syscall/time.rs b/kernel/src/syscall/time.rs index a6e9f36f..f3873c7e 100644 --- a/kernel/src/syscall/time.rs +++ b/kernel/src/syscall/time.rs @@ -173,7 +173,7 @@ impl Syscall<'_> { return Ok(0); } let sleep = req - current; - task.suspend_timeout(req).await + task.suspend_timeout(sleep).await } else { task.suspend_timeout(req).await }; diff --git a/kernel/src/task/schedule.rs b/kernel/src/task/schedule.rs index 04df8cb8..30f10b4a 100644 --- a/kernel/src/task/schedule.rs +++ b/kernel/src/task/schedule.rs @@ -79,6 +79,12 @@ impl + Send + 'static> Future for KernelTaskFuture { pub async fn task_loop(task: Arc) { *task.waker() = Some(get_waker().await); loop { + match task.state() { + Zombie => break, + Stopped => suspend_now().await, + _ => {} + } + trap::user_trap::trap_return(&task); // task may be set to zombie by other task, e.g. execve will kill other tasks in diff --git a/kernel/src/trap/user_trap.rs b/kernel/src/trap/user_trap.rs index f2558bac..f9a2092a 100644 --- a/kernel/src/trap/user_trap.rs +++ b/kernel/src/trap/user_trap.rs @@ -162,6 +162,8 @@ pub fn trap_return(task: &Arc) { // 2. This task encounter a signal handler task.trap_context_mut().user_fx.restore(); task.trap_context_mut().sstatus.set_fs(FS::Clean); + assert!(!task.trap_context_mut().sstatus.sie()); + assert!(!task.is_zombie()); unsafe { __return_to_user(task.trap_context_mut()); // NOTE: next time when user traps into kernel, it will come back here