diff --git a/kernel/proc.c b/kernel/proc.c index b9196c9..7e40fdc 100644 --- a/kernel/proc.c +++ b/kernel/proc.c @@ -54,24 +54,3 @@ userinit(void) release(&p->lock); } - -// A fork child's very first scheduling by scheduler() -// will swtch to forkret. -void -forkret(void) -{ - static int first = 1; - - // Still holding p->lock from scheduler. - release(&myproc()->lock); - - if (first) { - // File system initialization must be run in the context of a - // regular process (e.g., because it calls sleep), and thus cannot - // be run from main(). - first = 0; - fsinit(ROOTDEV); - } - - usertrapret(); -} diff --git a/kernel/rustkernel/src/arch/riscv/trap.rs b/kernel/rustkernel/src/arch/riscv/trap.rs index 742eaef..da2d9c4 100644 --- a/kernel/rustkernel/src/arch/riscv/trap.rs +++ b/kernel/rustkernel/src/arch/riscv/trap.rs @@ -100,7 +100,7 @@ pub unsafe fn devintr() -> i32 { /// Return to user space #[no_mangle] -pub unsafe extern "C" fn usertrapret() { +pub unsafe extern "C" fn usertrapret() -> ! { let proc = Process::current().unwrap(); // We're about to switch the destination of traps from @@ -147,7 +147,7 @@ pub unsafe extern "C" fn usertrapret() { TRAMPOLINE + (addr_of!(userret) as usize) - (addr_of!(trampoline) as usize); let trampoline_userret = trampoline_userret as *const (); // Rust's most dangerous function: core::mem::transmute - let trampoline_userret = core::mem::transmute::<*const (), fn(u64)>(trampoline_userret); + let trampoline_userret = core::mem::transmute::<*const (), fn(u64) -> !>(trampoline_userret); trampoline_userret(satp) } diff --git a/kernel/rustkernel/src/arch/trap.rs b/kernel/rustkernel/src/arch/trap.rs index 8c0454c..e899fb0 100644 --- a/kernel/rustkernel/src/arch/trap.rs +++ b/kernel/rustkernel/src/arch/trap.rs @@ -1,7 +1,7 @@ //! Architecture-agnostic trap handling. #[cfg(target_arch = "riscv64")] -pub use super::riscv::trap::trapinithart as inithart; +pub use super::riscv::trap::{trapinithart as inithart, usertrapret}; use super::interrupt; use crate::proc::cpu::Cpu; diff --git a/kernel/rustkernel/src/fs/mod.rs b/kernel/rustkernel/src/fs/mod.rs index 23e42c0..4d8cf41 100644 --- a/kernel/rustkernel/src/fs/mod.rs +++ b/kernel/rustkernel/src/fs/mod.rs @@ -83,6 +83,7 @@ pub struct DirectoryEntry { pub name: [u8; DIRSIZ], } +pub static mut FS_INITIALIZED: bool = false; extern "C" { pub fn fsinit(dev: i32); } diff --git a/kernel/rustkernel/src/proc/process.rs b/kernel/rustkernel/src/proc/process.rs index 3ce7323..3d5ce69 100644 --- a/kernel/rustkernel/src/proc/process.rs +++ b/kernel/rustkernel/src/proc/process.rs @@ -9,15 +9,17 @@ use super::{ use crate::{ arch::{ mem::{kstack, Pagetable, PAGE_SIZE, PTE_R, PTE_W, PTE_X, TRAMPOLINE, TRAPFRAME}, - trap::InterruptBlocker, + trap::{usertrapret, InterruptBlocker}, virtual_memory::{ copyout, mappages, uvmalloc, uvmcopy, uvmcreate, uvmdealloc, uvmfree, uvmunmap, }, }, fs::{ file::{fileclose, filedup, File}, + fsinit, inode::{idup, iput, Inode}, log::LogOperation, + FS_INITIALIZED, }, mem::{ kalloc::{kalloc, kfree}, @@ -150,6 +152,9 @@ impl Process { pub fn is_current(&self) -> bool { addr_of!(*self).cast_mut() == Cpu::current().proc } + pub fn is_initproc(&self) -> bool { + addr_of!(*self).cast_mut() == unsafe { initproc } + } pub fn alloc_pid() -> i32 { NEXT_PID.fetch_add(1, Ordering::SeqCst) @@ -200,7 +205,7 @@ impl Process { 0, core::mem::size_of::() as u32, ); - p.context.ra = forkret as usize as u64; + p.context.ra = Process::forkret as usize as u64; p.context.sp = p.kernel_stack + PAGE_SIZE as u64; Ok(p) @@ -340,6 +345,23 @@ impl Process { Ok(pid) } + /// A fork child's very first scheduling by + /// scheduler() will swtch to forkret. + pub unsafe fn forkret() -> ! { + // Still holding p->lock from scheduler. + Process::current().unwrap().lock.unlock(); + + if !FS_INITIALIZED { + // File system initialization must be run in the context of a + // regular process (e.g., because it calls sleep), and thus + // cannot be run from main(). + FS_INITIALIZED = true; + fsinit(crate::ROOTDEV as i32); + } + + usertrapret() + } + /// Pass p's abandoned children to init. /// Caller must hold wait_lock. pub unsafe fn reparent(&self) { @@ -355,7 +377,7 @@ impl Process { /// An exited process remains in the zombie state /// until its parent calls wait(). pub unsafe fn exit(&mut self, status: i32) -> ! { - if addr_of_mut!(*self) == initproc { + if self.is_initproc() { panic!("init exiting"); }