This commit is contained in:
Garen Tyler 2023-11-03 20:36:10 -06:00
parent badd35b3f9
commit a168c989cf
Signed by: garentyler
GPG Key ID: D7A048C454CB7054
4 changed files with 75 additions and 57 deletions

View File

@ -112,47 +112,7 @@ void reparent(struct proc *p);
// Exit the current process. Does not return. // Exit the current process. Does not return.
// An exited process remains in the zombie state // An exited process remains in the zombie state
// until its parent calls wait(). // until its parent calls wait().
void void exit(int status);
exit(int status)
{
struct proc *p = myproc();
if(p == initproc)
panic("init exiting");
// Close all open files.
for(int fd = 0; fd < NOFILE; fd++){
if(p->ofile[fd]){
struct file *f = p->ofile[fd];
fileclose(f);
p->ofile[fd] = 0;
}
}
begin_op();
iput(p->cwd);
end_op();
p->cwd = 0;
acquire(&wait_lock);
// Give any children to init.
reparent(p);
// Parent might be sleeping in wait().
wakeup(p->parent);
acquire(&p->lock);
p->xstate = status;
p->state = ZOMBIE;
release(&wait_lock);
// Jump into the scheduler, never to return.
sched();
panic("zombie exit");
}
// Wait for a child process to exit and return its pid. // Wait for a child process to exit and return its pid.
// Return -1 if this process has no children. // Return -1 if this process has no children.

View File

@ -1,9 +1,14 @@
#![allow(clippy::comparison_chain)] #![allow(clippy::comparison_chain)]
use super::{context::Context, cpu::Cpu, scheduler::wakeup, trapframe::Trapframe}; use super::{context::Context, cpu::Cpu, scheduler::{wakeup, sched}, trapframe::Trapframe};
use crate::{ use crate::{
arch::riscv::{Pagetable, PTE_W, PTE_R, PTE_X, PGSIZE, memlayout::{TRAMPOLINE, TRAPFRAME}}, arch::riscv::{Pagetable, PTE_W, PTE_R, PTE_X, PGSIZE, memlayout::{TRAMPOLINE, TRAPFRAME}},
fs::{file::{File, Inode, filedup}, idup}, fs::{
file::{File, Inode, filedup, fileclose},
idup,
iput,
log::LogOperation,
},
mem::{ mem::{
kalloc::{kfree, kalloc}, kalloc::{kfree, kalloc},
memset, memset,
@ -11,6 +16,7 @@ use crate::{
}, },
sync::spinlock::Spinlock, sync::spinlock::Spinlock,
string::safestrcpy, string::safestrcpy,
println,
}; };
use core::{ use core::{
ffi::{c_char, c_void}, ffi::{c_char, c_void},
@ -35,7 +41,7 @@ extern "C" {
pub fn userinit(); pub fn userinit();
pub fn forkret(); pub fn forkret();
// pub fn fork() -> i32; // pub fn fork() -> i32;
pub fn exit(status: i32) -> !; // pub fn exit(status: i32) -> !;
pub fn wait(addr: u64) -> i32; pub fn wait(addr: u64) -> i32;
pub fn procdump(); pub fn procdump();
pub fn proc_mapstacks(kpgtbl: Pagetable); pub fn proc_mapstacks(kpgtbl: Pagetable);
@ -299,6 +305,60 @@ impl Process {
Ok(pid) Ok(pid)
} }
/// Pass p's abandoned children to init.
/// Caller must hold wait_lock.
pub unsafe fn reparent(&self) {
for p in proc.iter_mut() {
if p.parent == addr_of!(*self).cast_mut() {
p.parent = initproc;
wakeup(initproc.cast());
}
}
}
/// Exit the current process. Does not return.
/// 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 {
panic!("init exiting");
}
// Close all open files.
for file in self.ofile.iter_mut() {
if !file.is_null() {
fileclose(*file);
*file = null_mut();
}
}
{
let _operation = LogOperation::new();
iput(self.cwd);
}
self.cwd = null_mut();
{
let _guard = wait_lock.lock();
// Give any children to init.
self.reparent();
// Parent might be sleeping in wait().
wakeup(self.parent.cast());
self.lock.lock_unguarded();
self.xstate = status;
self.state = ProcessState::Zombie;
}
// Jump into the scheduler, never to return.
sched();
loop {
unreachable!();
}
}
/// Kill the process with the given pid. /// Kill the process with the given pid.
/// Returns true if the process was killed. /// Returns true if the process was killed.
/// The victim won't exit until it tries to return /// The victim won't exit until it tries to return
@ -376,16 +436,14 @@ pub unsafe extern "C" fn proc_freepagetable(pagetable: Pagetable, size: u64) {
Process::free_pagetable(pagetable, size as usize) Process::free_pagetable(pagetable, size as usize)
} }
/// Pass p's abandoned children to init.
/// Caller must hold wait_lock.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn reparent(p: *mut Process) { pub unsafe extern "C" fn reparent(p: *mut Process) {
for pp in proc.iter_mut().map(|p: &mut Process| addr_of_mut!(*p)) { (*p).reparent()
if (*pp).parent == p { }
(*pp).parent = initproc;
wakeup(initproc.cast()); #[no_mangle]
} pub unsafe extern "C" fn exit(status: i32) -> ! {
} Process::current().unwrap().exit(status)
} }
/// Kill the process with the given pid. /// Kill the process with the given pid.

View File

@ -59,9 +59,9 @@ impl Syscall {
match self { match self {
Syscall::Fork => Process::fork().unwrap_or(-1) as i64 as u64, Syscall::Fork => Process::fork().unwrap_or(-1) as i64 as u64,
Syscall::Exit => { Syscall::Exit => {
let mut n = 0i32; let mut status = 0i32;
argint(0, addr_of_mut!(n)); argint(0, addr_of_mut!(status));
process::exit(n) Process::current().unwrap().exit(status)
} }
Syscall::Wait => { Syscall::Wait => {
let mut p = 0u64; let mut p = 0u64;

View File

@ -232,7 +232,7 @@ pub unsafe extern "C" fn usertrap() {
// System call // System call
if proc.is_killed() { if proc.is_killed() {
exit(-1); proc.exit(-1);
} }
// sepc points to the ecall instruction, but // sepc points to the ecall instruction, but
@ -259,7 +259,7 @@ pub unsafe extern "C" fn usertrap() {
} }
if proc.is_killed() { if proc.is_killed() {
exit(-1); proc.exit(-1);
} }
// Give up the CPU if this is a timer interrupt. // Give up the CPU if this is a timer interrupt.