implement myproc as an associated function of the Proc struct

This commit is contained in:
Garen Tyler 2023-11-03 18:31:07 -06:00
parent 73e3ab9ebc
commit 0e753e8ba5
Signed by: garentyler
GPG Key ID: D7A048C454CB7054
9 changed files with 129 additions and 88 deletions

View File

@ -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;
}

View File

@ -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::<Stat>() as u64,

View File

@ -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<usize> {
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<usize> {
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;

View File

@ -1,4 +1,5 @@
pub mod context;
pub mod cpu;
#[allow(clippy::module_inception)]
pub mod proc;
pub mod trapframe;

View File

@ -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.

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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<Syscall> 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::<u64>() as u64 > (*p).sz
if addr >= proc.sz
|| addr + size_of::<u64>() 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<usize, ()> {
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<usize, ()> {
}
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::<Syscall>::try_into(num as usize) {
let num = (*proc.trapframe).a7;
(*proc.trapframe).a0 = match TryInto::<Syscall>::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
}
};

View File

@ -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);
}