From 0e753e8ba54c455e2c3fc5752d0ba1eaf594dbd3 Mon Sep 17 00:00:00 2001 From: Garen Tyler Date: Fri, 3 Nov 2023 18:31:07 -0600 Subject: [PATCH] implement myproc as an associated function of the Proc struct --- kernel/rustkernel/src/console/mod.rs | 4 +- kernel/rustkernel/src/fs/file.rs | 6 +-- kernel/rustkernel/src/io/pipe.rs | 14 +++--- kernel/rustkernel/src/proc/mod.rs | 1 + kernel/rustkernel/src/proc/proc.rs | 69 +++++++++++++++++++------- kernel/rustkernel/src/sync/lock.rs | 12 ++--- kernel/rustkernel/src/sync/spinlock.rs | 12 ++--- kernel/rustkernel/src/syscall.rs | 62 ++++++++++++----------- kernel/rustkernel/src/trap.rs | 37 +++++++------- 9 files changed, 129 insertions(+), 88 deletions(-) diff --git a/kernel/rustkernel/src/console/mod.rs b/kernel/rustkernel/src/console/mod.rs index bbe672c..49153de 100644 --- a/kernel/rustkernel/src/console/mod.rs +++ b/kernel/rustkernel/src/console/mod.rs @@ -13,7 +13,7 @@ pub mod uart; use crate::{ fs::file::{devsw, CONSOLE}, - proc::proc::{killed, myproc, procdump, wakeup}, + proc::proc::{killed, procdump, wakeup, Proc}, sync::mutex::Mutex, }; use core::{ffi::c_void, ptr::addr_of_mut}; @@ -114,7 +114,7 @@ pub fn consoleread(user_dst: i32, mut dst: u64, mut n: i32) -> i32 { // Wait until interrupt handler has put // some input into cons.buffer. while console.read_index == console.write_index { - if killed(myproc()) != 0 { + if killed(addr_of_mut!(*Proc::current().unwrap())) != 0 { // cons.lock.unlock(); return -1; } diff --git a/kernel/rustkernel/src/fs/file.rs b/kernel/rustkernel/src/fs/file.rs index 3e833fd..7d87213 100644 --- a/kernel/rustkernel/src/fs/file.rs +++ b/kernel/rustkernel/src/fs/file.rs @@ -4,7 +4,7 @@ use crate::{ fs::{log, stat::Stat}, io::pipe::Pipe, mem::virtual_memory::copyout, - proc::proc::myproc, + proc::proc::Proc, sync::{sleeplock::Sleeplock, spinlock::Spinlock}, }; use core::ptr::{addr_of_mut, null_mut}; @@ -206,7 +206,7 @@ pub unsafe extern "C" fn fileclose(file: *mut File) { /// `addr` is a user virtual address, pointing to a Stat. #[no_mangle] pub unsafe extern "C" fn filestat(file: *mut File, addr: u64) -> i32 { - let p = myproc(); + let proc = Proc::current().unwrap(); let mut stat = Stat::default(); if (*file).kind == FileType::Inode || (*file).kind == FileType::Device { @@ -216,7 +216,7 @@ pub unsafe extern "C" fn filestat(file: *mut File, addr: u64) -> i32 { } if copyout( - (*p).pagetable, + proc.pagetable, addr, addr_of_mut!(stat).cast(), core::mem::size_of::() as u64, diff --git a/kernel/rustkernel/src/io/pipe.rs b/kernel/rustkernel/src/io/pipe.rs index 47f3c6a..0b48dc2 100644 --- a/kernel/rustkernel/src/io/pipe.rs +++ b/kernel/rustkernel/src/io/pipe.rs @@ -4,7 +4,7 @@ use crate::{ kalloc::{kalloc, kfree}, virtual_memory::{copyin, copyout}, }, - proc::proc::{killed, myproc, wakeup}, + proc::proc::{killed, wakeup, Proc}, sync::spinlock::Spinlock, }; use core::ptr::{addr_of, addr_of_mut}; @@ -88,11 +88,11 @@ impl Pipe { } pub unsafe fn write(&self, addr: u64, num_bytes: usize) -> Result { let mut i = 0; - let p = myproc(); + let proc = Proc::current().unwrap(); let guard = self.lock.lock(); while i < num_bytes { - if self.is_read_open == 0 || killed(p) > 0 { + if self.is_read_open == 0 || killed(addr_of_mut!(*proc)) > 0 { return Err(PipeError::ProcessKilled); } if self.bytes_written == self.bytes_read + PIPESIZE as u32 { @@ -101,7 +101,7 @@ impl Pipe { guard.sleep(addr_of!(self.bytes_written).cast_mut().cast()); } else { let mut b = 0u8; - if copyin((*p).pagetable, addr_of_mut!(b), addr + i as u64, 1) == -1 { + if copyin(proc.pagetable, addr_of_mut!(b), addr + i as u64, 1) == -1 { break; } let index = self.bytes_written as usize % PIPESIZE; @@ -116,12 +116,12 @@ impl Pipe { #[allow(clippy::while_immutable_condition)] pub unsafe fn read(&self, addr: u64, num_bytes: usize) -> Result { let mut i = 0; - let p = myproc(); + let proc = Proc::current().unwrap(); let guard = self.lock.lock(); // DOC: pipe-empty while self.bytes_read == self.bytes_written && self.is_write_open > 0 { - if killed(p) > 0 { + if killed(addr_of_mut!(*proc)) > 0 { return Err(PipeError::ProcessKilled); } else { // DOC: piperead-sleep @@ -136,7 +136,7 @@ impl Pipe { } let b = self.data[self.bytes_read as usize % PIPESIZE]; self.as_mut().bytes_read += 1; - if copyout((*p).pagetable, addr + i as u64, addr_of!(b).cast_mut(), 1) == -1 { + if copyout(proc.pagetable, addr + i as u64, addr_of!(b).cast_mut(), 1) == -1 { break; } i += 1; diff --git a/kernel/rustkernel/src/proc/mod.rs b/kernel/rustkernel/src/proc/mod.rs index 44134d1..2132c0b 100644 --- a/kernel/rustkernel/src/proc/mod.rs +++ b/kernel/rustkernel/src/proc/mod.rs @@ -1,4 +1,5 @@ pub mod context; pub mod cpu; +#[allow(clippy::module_inception)] pub mod proc; pub mod trapframe; diff --git a/kernel/rustkernel/src/proc/proc.rs b/kernel/rustkernel/src/proc/proc.rs index cc6d0aa..9edecad 100644 --- a/kernel/rustkernel/src/proc/proc.rs +++ b/kernel/rustkernel/src/proc/proc.rs @@ -96,12 +96,45 @@ pub struct Proc { /// Process name (debugging) pub name: [c_char; 16], } +impl Proc { + pub const fn new() -> Proc { + Proc { + lock: Spinlock::new(), + state: ProcState::Unused, + chan: null_mut(), + killed: 0, + xstate: 0, + pid: 0, + parent: null_mut(), + kstack: 0, + sz: 0, + pagetable: null_mut(), + trapframe: null_mut(), + context: Context::new(), + ofile: [null_mut(); crate::NOFILE], + cwd: null_mut(), + name: [0x00; 16], + } + } + pub fn current() -> Option<&'static mut Proc> { + let _ = crate::trap::InterruptBlocker::new(); + let p = Cpu::current().proc; + if p.is_null() { + None + } else { + unsafe { Some(&mut *p) } + } + } +} /// Return the current struct proc *, or zero if none. #[no_mangle] pub unsafe extern "C" fn myproc() -> *mut Proc { - let _ = crate::trap::InterruptBlocker::new(); - Cpu::current().proc + if let Some(p) = Proc::current() { + p as *mut Proc + } else { + null_mut() + } } #[no_mangle] @@ -149,26 +182,26 @@ pub unsafe extern "C" fn reparent(p: *mut Proc) { /// Grow or shrink user memory by n bytes. /// Return 0 on success, -1 on failure. pub unsafe fn growproc(n: i32) -> i32 { - let p = myproc(); - let mut sz = (*p).sz; + let p = Proc::current().unwrap(); + let mut sz = p.sz; if n > 0 { - sz = uvmalloc((*p).pagetable, sz, sz.wrapping_add(n as u64), PTE_W); + sz = uvmalloc(p.pagetable, sz, sz.wrapping_add(n as u64), PTE_W); if sz == 0 { return -1; } } else if n < 0 { - sz = uvmdealloc((*p).pagetable, sz, sz.wrapping_add(n as u64)); + sz = uvmdealloc(p.pagetable, sz, sz.wrapping_add(n as u64)); } - (*p).sz = sz; + p.sz = sz; 0 } /// Give up the CPU for one scheduling round. pub unsafe fn r#yield() { - let p = myproc(); - let _guard = (*p).lock.lock(); - (*p).state = ProcState::Runnable; + let p = Proc::current().unwrap(); + let _guard = p.lock.lock(); + p.state = ProcState::Runnable; sched(); } @@ -181,19 +214,19 @@ pub unsafe fn r#yield() { /// there's no process. #[no_mangle] pub unsafe extern "C" fn sched() { - let p = myproc(); + let p = Proc::current().unwrap(); let cpu = Cpu::current(); if cpu.interrupt_disable_layers != 1 { panic!("sched locks"); - } else if (*p).state == ProcState::Running { + } else if p.state == ProcState::Running { panic!("sched running"); } else if intr_get() > 0 { panic!("sched interruptible"); } let previous_interrupts_enabled = cpu.previous_interrupts_enabled; - swtch(addr_of_mut!((*p).context), addr_of_mut!(cpu.context)); + swtch(addr_of_mut!(p.context), addr_of_mut!(cpu.context)); cpu.previous_interrupts_enabled = previous_interrupts_enabled; } @@ -209,17 +242,17 @@ pub unsafe extern "C" fn sleep_lock(chan: *mut c_void, lock: *mut Spinlock) { /// Sleep until `wakeup(chan)` is called somewhere else. pub unsafe fn sleep(chan: *mut c_void) { - let p = myproc(); - let _guard = (*p).lock.lock(); + let p = Proc::current().unwrap(); + let _guard = p.lock.lock(); // Go to sleep. - (*p).chan = chan; - (*p).state = ProcState::Sleeping; + p.chan = chan; + p.state = ProcState::Sleeping; sched(); // Tidy up. - (*p).chan = null_mut(); + p.chan = null_mut(); } /// Kill the process with the given pid. diff --git a/kernel/rustkernel/src/sync/lock.rs b/kernel/rustkernel/src/sync/lock.rs index bbaeba9..ffc50f7 100644 --- a/kernel/rustkernel/src/sync/lock.rs +++ b/kernel/rustkernel/src/sync/lock.rs @@ -1,5 +1,5 @@ use super::LockStrategy; -use crate::proc::proc::{myproc, sched, sleep, wakeup, ProcState}; +use crate::proc::proc::{sched, sleep, wakeup, Proc, ProcState}; use core::{ cell::UnsafeCell, ops::Drop, @@ -83,18 +83,18 @@ impl<'l> LockGuard<'l> { /// Sleep until `wakeup(chan)` is called somewhere /// else, yielding access to the lock until then. pub unsafe fn sleep(&self, chan: *mut core::ffi::c_void) { - let p = myproc(); - let _guard = (*p).lock.lock(); + let proc = Proc::current().unwrap(); + let _guard = proc.lock.lock(); let strategy = self.lock.lock_strategy(); self.lock.unlock(); // Put the process to sleep. - (*p).chan = chan; - (*p).state = ProcState::Sleeping; + proc.chan = chan; + proc.state = ProcState::Sleeping; sched(); // Tidy up and reacquire the lock. - (*p).chan = null_mut(); + proc.chan = null_mut(); self.lock.lock_unguarded(strategy); } } diff --git a/kernel/rustkernel/src/sync/spinlock.rs b/kernel/rustkernel/src/sync/spinlock.rs index c8b0f3d..e59f55e 100644 --- a/kernel/rustkernel/src/sync/spinlock.rs +++ b/kernel/rustkernel/src/sync/spinlock.rs @@ -1,5 +1,5 @@ use crate::{ - proc::proc::{myproc, sched, ProcState}, + proc::proc::{sched, Proc, ProcState}, trap::{pop_intr_off, push_intr_off}, }; use core::{ @@ -46,17 +46,17 @@ pub struct SpinlockGuard<'l> { impl<'l> SpinlockGuard<'l> { /// Sleep until `wakeup(chan)` is called somewhere else, yielding the lock until then. pub unsafe fn sleep(&self, chan: *mut core::ffi::c_void) { - let p = myproc(); - let _guard = (*p).lock.lock(); + let proc = Proc::current().unwrap(); + let _guard = proc.lock.lock(); self.lock.unlock(); // Put the process to sleep. - (*p).chan = chan; - (*p).state = ProcState::Sleeping; + proc.chan = chan; + proc.state = ProcState::Sleeping; sched(); // Tidy up and reacquire the lock. - (*p).chan = null_mut(); + proc.chan = null_mut(); self.lock.lock_unguarded(); } } diff --git a/kernel/rustkernel/src/syscall.rs b/kernel/rustkernel/src/syscall.rs index d888e79..1afa2a7 100644 --- a/kernel/rustkernel/src/syscall.rs +++ b/kernel/rustkernel/src/syscall.rs @@ -8,7 +8,7 @@ use crate::{ }, mem::virtual_memory::{copyin, copyinstr}, println, - proc::proc::{self, myproc}, + proc::proc::{self, Proc}, string::strlen, trap::CLOCK_TICKS, NOFILE, @@ -102,7 +102,7 @@ impl Syscall { } Syscall::Chdir => { let mut path = [0u8; crate::MAXPATH]; - let p = myproc(); + let proc = Proc::current().unwrap(); let _operation = LogOperation::new(); @@ -120,8 +120,8 @@ impl Syscall { return -1i64 as u64; } fs::iunlock(inode); - fs::iput((*p).cwd); - (*p).cwd = inode; + fs::iput(proc.cwd); + proc.cwd = inode; 0 } Syscall::Dup => { @@ -138,11 +138,11 @@ impl Syscall { file::filedup(file); file_descriptor as u64 } - Syscall::Getpid => (*myproc()).pid as u64, + Syscall::Getpid => Proc::current().unwrap().pid as u64, Syscall::Sbrk => { let mut n = 0i32; argint(0, addr_of_mut!(n)); - let addr = (*myproc()).sz; + let addr = Proc::current().unwrap().sz; if proc::growproc(n) < 0 { -1i64 as u64 @@ -157,7 +157,7 @@ impl Syscall { let mut ticks = CLOCK_TICKS.lock_spinning(); while *ticks < *ticks + n as usize { - if proc::killed(myproc()) > 0 { + if proc::killed(addr_of!(*Proc::current().unwrap()).cast_mut()) > 0 { return -1i64 as u64; } // Sleep until the value changes. @@ -191,7 +191,7 @@ impl Syscall { let mut file: *mut File = null_mut(); if argfd(0, addr_of_mut!(file_descriptor), addr_of_mut!(file)) >= 0 { - (*myproc()).ofile[file_descriptor as usize] = null_mut(); + Proc::current().unwrap().ofile[file_descriptor as usize] = null_mut(); file::fileclose(file); 0 } else { @@ -269,13 +269,13 @@ impl From for usize { /// Fetch the u64 at addr from the current process. #[no_mangle] pub unsafe extern "C" fn fetchaddr(addr: u64, ip: *mut u64) -> i32 { - let p = myproc(); + let proc = Proc::current().unwrap(); // Both tests needed, in case of overflow. - if addr >= (*p).sz - || addr + size_of::() as u64 > (*p).sz + if addr >= proc.sz + || addr + size_of::() as u64 > proc.sz || copyin( - (*p).pagetable, + proc.pagetable, ip.cast(), addr, size_of::<*mut u64>() as u64, @@ -292,8 +292,9 @@ pub unsafe extern "C" fn fetchaddr(addr: u64, ip: *mut u64) -> i32 { /// Returns length of string, not including null, or -1 for error. #[no_mangle] pub unsafe extern "C" fn fetchstr(addr: u64, buf: *mut u8, max: i32) -> i32 { - let p = myproc(); - if copyinstr((*p).pagetable, buf, addr, max as u64) < 0 { + let proc = Proc::current().unwrap(); + + if copyinstr(proc.pagetable, buf, addr, max as u64) < 0 { -1 } else { strlen(buf.cast()) @@ -303,10 +304,11 @@ pub unsafe extern "C" fn fetchstr(addr: u64, buf: *mut u8, max: i32) -> i32 { /// Allocate a file descriptor for the given file. /// Takes over file reference from caller on success. unsafe fn fdalloc(file: *mut File) -> Result { - let p = myproc(); + let proc = Proc::current().unwrap(); + for file_descriptor in 0..crate::NOFILE { - if (*p).ofile[file_descriptor].is_null() { - (*p).ofile[file_descriptor] = file; + if proc.ofile[file_descriptor].is_null() { + proc.ofile[file_descriptor] = file; return Ok(file_descriptor); } } @@ -314,14 +316,15 @@ unsafe fn fdalloc(file: *mut File) -> Result { } unsafe fn argraw(argument_index: usize) -> u64 { - let p = myproc(); + let proc = Proc::current().unwrap(); + match argument_index { - 0 => (*(*p).trapframe).a0, - 1 => (*(*p).trapframe).a1, - 2 => (*(*p).trapframe).a2, - 3 => (*(*p).trapframe).a3, - 4 => (*(*p).trapframe).a4, - 5 => (*(*p).trapframe).a5, + 0 => (*proc.trapframe).a0, + 1 => (*proc.trapframe).a1, + 2 => (*proc.trapframe).a2, + 3 => (*proc.trapframe).a3, + 4 => (*proc.trapframe).a4, + 5 => (*proc.trapframe).a5, _ => panic!("argraw"), } } @@ -354,7 +357,7 @@ pub unsafe extern "C" fn argfd( return -1; } - let file: *mut File = (*myproc()).ofile[file_descriptor]; + let file: *mut File = Proc::current().unwrap().ofile[file_descriptor]; if file.is_null() { return -1; } @@ -380,13 +383,14 @@ pub unsafe extern "C" fn argstr(n: i32, buf: *mut u8, max: i32) -> i32 { } pub unsafe fn syscall() { - let p = myproc(); - let num = (*(*p).trapframe).a7; + let proc = Proc::current().unwrap(); - (*(*p).trapframe).a0 = match TryInto::::try_into(num as usize) { + let num = (*proc.trapframe).a7; + + (*proc.trapframe).a0 = match TryInto::::try_into(num as usize) { Ok(syscall) => syscall.call(), Err(_) => { - println!("{} unknown syscall {}", (*p).pid, num); + println!("{} unknown syscall {}", proc.pid, num); -1i64 as u64 } }; diff --git a/kernel/rustkernel/src/trap.rs b/kernel/rustkernel/src/trap.rs index d475426..cb4aa53 100644 --- a/kernel/rustkernel/src/trap.rs +++ b/kernel/rustkernel/src/trap.rs @@ -3,12 +3,12 @@ use crate::{ println, proc::{ cpu::Cpu, - proc::{exit, killed, myproc, r#yield, setkilled, wakeup, ProcState}, + proc::{exit, killed, r#yield, setkilled, wakeup, Proc, ProcState}, }, sync::mutex::Mutex, syscall::syscall, }; -use core::ptr::addr_of; +use core::ptr::{addr_of, addr_of_mut}; extern "C" { pub fn kernelvec(); @@ -127,7 +127,7 @@ impl !Send for InterruptBlocker {} /// Return to user space #[no_mangle] pub unsafe extern "C" fn usertrapret() { - let p = myproc(); + let proc = Proc::current().unwrap(); // We're about to switch the destination of traps from // kerneltrap() to usertrap(), so turn off interrupts until @@ -142,12 +142,12 @@ pub unsafe extern "C" fn usertrapret() { // Set up trapframe values that uservec will need when // the process next traps into the kernel. // kernel page table - (*(*p).trapframe).kernel_satp = r_satp(); + (*proc.trapframe).kernel_satp = r_satp(); // process's kernel stack - (*(*p).trapframe).kernel_sp = (*p).kstack + PGSIZE; - (*(*p).trapframe).kernel_trap = usertrap as usize as u64; + (*proc.trapframe).kernel_sp = proc.kstack + PGSIZE; + (*proc.trapframe).kernel_trap = usertrap as usize as u64; // hartid for Cpu::current_id() - (*(*p).trapframe).kernel_hartid = r_tp(); + (*proc.trapframe).kernel_hartid = r_tp(); // Set up the registers that trampoline.S's // sret will use to get to user space. @@ -161,10 +161,10 @@ pub unsafe extern "C" fn usertrapret() { w_sstatus(x); // Set S Exception Program Counter to the saved user pc. - w_sepc((*(*p).trapframe).epc); + w_sepc((*proc.trapframe).epc); // Tell trampoline.S the user page table to switch to. - let satp = make_satp((*p).pagetable); + let satp = make_satp(proc.pagetable); // Jump to userret in trampoline.S at the top of memory, which // switches to the user page table, restores user registers, @@ -195,7 +195,10 @@ pub unsafe extern "C" fn kerneltrap() { if which_dev == 0 { println!("scause {}\nsepc={} stval={}", scause, r_sepc(), r_stval()); panic!("kerneltrap"); - } else if which_dev == 2 && !myproc().is_null() && (*myproc()).state == ProcState::Running { + } else if which_dev == 2 + && Proc::current().is_some() + && Proc::current().unwrap().state == ProcState::Running + { // Give up the CPU if this is a timer interrupt. r#yield(); } @@ -219,21 +222,21 @@ pub unsafe extern "C" fn usertrap() { // since we're now in the kernel. w_stvec(kernelvec as usize as u64); - let p = myproc(); + let proc = Proc::current().unwrap(); // Save user program counter. - (*(*p).trapframe).epc = r_sepc(); + (*proc.trapframe).epc = r_sepc(); if r_scause() == 8 { // System call - if killed(p) > 0 { + if killed(addr_of_mut!(*proc)) > 0 { exit(-1); } // sepc points to the ecall instruction, but // we want to return to the next instruction. - (*(*p).trapframe).epc += 4; + (*proc.trapframe).epc += 4; // An interrupt will change sepc, scause, and sstatus, // so enable only now that we're done with those registers. @@ -247,14 +250,14 @@ pub unsafe extern "C" fn usertrap() { println!( "usertrap(): unexpected scause {} {}\n\tsepc={} stval={}", r_scause(), - (*p).pid, + proc.pid, r_sepc(), r_stval() ); - setkilled(p); + setkilled(addr_of_mut!(*proc)); } - if killed(p) > 0 { + if killed(addr_of_mut!(*proc)) > 0 { exit(-1); }