diff --git a/.github/workflows/build-doc.yml b/.github/workflows/build-doc.yml deleted file mode 100644 index a48f1474..00000000 --- a/.github/workflows/build-doc.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: Build Rust Doc - -on: [push] - -env: - CARGO_TERM_COLOR: always - -jobs: - build-doc: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Build doc - run: | - rustup target add riscv64gc-unknown-none-elf - rustup component add llvm-tools-preview - rustup component add rust-src - cd os - cargo doc --no-deps --verbose - - name: Deploy to Github Pages - uses: peaceiris/actions-gh-pages@v3 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: ./os/target/riscv64gc-unknown-none-elf/doc - destination_dir: ${{ github.ref_name }} \ No newline at end of file diff --git a/.github/workflows/doc-and-test.yml b/.github/workflows/doc-and-test.yml new file mode 100644 index 00000000..26524710 --- /dev/null +++ b/.github/workflows/doc-and-test.yml @@ -0,0 +1,45 @@ +name: Build Rust Doc And Run tests + +on: [push] + +env: + CARGO_TERM_COLOR: always + +jobs: + build-doc: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Build doc + run: | + rustup target add riscv64gc-unknown-none-elf + rustup component add llvm-tools-preview + rustup component add rust-src + cd os + cargo doc --no-deps --verbose + - name: Deploy to Github Pages + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./os/target/riscv64gc-unknown-none-elf/doc + destination_dir: ${{ github.ref_name }} + run-tests: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Install QEMU + run: | + sudo apt-get update + sudo apt-get install ninja-build -y + [ ! -d qemu-6.1.0 ] && wget https://download.qemu.org/qemu-6.1.0.tar.xz \ + && tar xJf qemu-6.1.0.tar.xz > /dev/null \ + && cd qemu-6.1.0 && ./configure --target-list=riscv64-softmmu && cd .. + cd qemu-6.1.0 && sudo make install -j + qemu-system-riscv64 --version + - name: Run usertests + run: | + cd os && make run TEST=1 + + + + \ No newline at end of file diff --git a/os/Makefile b/os/Makefile index 741c81db..0601e393 100644 --- a/os/Makefile +++ b/os/Makefile @@ -37,6 +37,9 @@ OBJCOPY := rust-objcopy --binary-architecture=riscv64 # Disassembly DISASM ?= -x +# Run usertests or usershell +TEST ?= + build: env switch-check $(KERNEL_BIN) fs-img switch-check: @@ -61,7 +64,7 @@ $(KERNEL_BIN): kernel @$(OBJCOPY) $(KERNEL_ELF) --strip-all -O binary $@ fs-img: $(APPS) - @cd ../user && make build + @cd ../user && make build TEST=$(TEST) @rm -f $(FS_IMG) @cd ../easy-fs-fuse && cargo run --release -- -s ../user/src/bin/ -t ../user/target/riscv64gc-unknown-none-elf/release/ diff --git a/os/src/sync/up.rs b/os/src/sync/up.rs index 55c8d40a..3600271a 100644 --- a/os/src/sync/up.rs +++ b/os/src/sync/up.rs @@ -101,6 +101,7 @@ impl UPIntrFreeCell { inner: RefCell::new(value), } } + /// Panic if the data has been borrowed. pub fn exclusive_access(&self) -> UPIntrRefMut<'_, T> { INTR_MASKING_INFO.get_mut().enter(); diff --git a/os/src/task/id.rs b/os/src/task/id.rs index e336c500..c1771813 100644 --- a/os/src/task/id.rs +++ b/os/src/task/id.rs @@ -46,6 +46,8 @@ lazy_static! { unsafe { UPIntrFreeCell::new(RecycleAllocator::new()) }; } +pub const IDLE_PID: usize = 0; + pub struct PidHandle(pub usize); pub fn pid_alloc() -> PidHandle { diff --git a/os/src/task/mod.rs b/os/src/task/mod.rs index c3053f06..6b4082b4 100644 --- a/os/src/task/mod.rs +++ b/os/src/task/mod.rs @@ -17,7 +17,7 @@ use process::ProcessControlBlock; use switch::__switch; pub use context::TaskContext; -pub use id::{kstack_alloc, pid_alloc, KernelStack, PidHandle}; +pub use id::{kstack_alloc, pid_alloc, KernelStack, PidHandle, IDLE_PID}; pub use manager::{add_task, pid2process, remove_from_pid2process}; pub use processor::{ current_kstack_top, current_process, current_task, current_trap_cx, current_trap_cx_user_va, @@ -26,6 +26,7 @@ pub use processor::{ pub use signal::SignalFlags; pub use task::{TaskControlBlock, TaskStatus}; + pub fn suspend_current_and_run_next() { // There must be an application running. let task = take_current_task().unwrap(); @@ -72,7 +73,12 @@ pub fn exit_current_and_run_next(exit_code: i32) { // however, if this is the main thread of current process // the process should terminate at once if tid == 0 { - remove_from_pid2process(process.getpid()); + let pid = process.getpid(); + if pid == IDLE_PID { + println!("[kernel] Idle process exit ..."); + crate::sbi::shutdown(); + } + remove_from_pid2process(pid); let mut process_inner = process.inner_exclusive_access(); // mark this process as a zombie process process_inner.is_zombie = true; diff --git a/rust-toolchain b/rust-toolchain index abcacd9b..281657a9 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -nightly-2022-04-11 +nightly-2022-04-12 diff --git a/user/Makefile b/user/Makefile index e2eaf994..c09b5e96 100644 --- a/user/Makefile +++ b/user/Makefile @@ -8,9 +8,15 @@ BINS := $(patsubst $(APP_DIR)/%.rs, $(TARGET_DIR)/%.bin, $(APPS)) OBJDUMP := rust-objdump --arch-name=riscv64 OBJCOPY := rust-objcopy --binary-architecture=riscv64 +CP := cp + +TEST ?= elf: $(APPS) @cargo build --release +ifeq ($(TEST), 1) + @$(CP) $(TARGET_DIR)/usertests $(TARGET_DIR)/initproc +endif binary: elf $(foreach elf, $(ELFS), $(OBJCOPY) $(elf) --strip-all -O binary $(patsubst $(TARGET_DIR)/%, $(TARGET_DIR)/%.bin, $(elf));) diff --git a/user/src/bin/usertests.rs b/user/src/bin/usertests.rs index 4fd49a4f..89f3ce51 100644 --- a/user/src/bin/usertests.rs +++ b/user/src/bin/usertests.rs @@ -4,7 +4,7 @@ #[macro_use] extern crate user_lib; -static TESTS: &[&str] = &[ +static SUCC_TESTS: &[&str] = &[ "exit\0", "fantastic_text\0", "forktest\0", @@ -14,15 +14,17 @@ static TESTS: &[&str] = &[ "matrix\0", "sleep\0", "sleep_simple\0", - "stack_overflow\0", "yield\0", ]; +static FAIL_TESTS: &[&str] = &[ + "stack_overflow\0", +]; + use user_lib::{exec, fork, waitpid}; -#[no_mangle] -pub fn main() -> i32 { - for test in TESTS { +fn run_tests(tests: &[&str], judge: F) { + for test in tests { println!("Usertests: Running {}", test); let pid = fork(); if pid == 0 { @@ -32,12 +34,19 @@ pub fn main() -> i32 { let mut exit_code: i32 = Default::default(); let wait_pid = waitpid(pid as usize, &mut exit_code); assert_eq!(pid, wait_pid); + judge(exit_code); println!( "\x1b[32mUsertests: Test {} in Process {} exited with code {}\x1b[0m", test, pid, exit_code ); } } +} + +#[no_mangle] +pub fn main() -> i32 { + run_tests(SUCC_TESTS, |code| assert!(code == 0)); + run_tests(FAIL_TESTS, |code| assert!(code != 0)); println!("Usertests passed!"); 0 }