exit
This commit is contained in:
parent
badd35b3f9
commit
a168c989cf
@ -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.
|
||||||
|
@ -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.
|
||||||
|
@ -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;
|
||||||
|
@ -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.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user