This commit is contained in:
Garen Tyler 2023-11-03 20:14:57 -06:00
parent 6342f66cd3
commit badd35b3f9
Signed by: garentyler
GPG Key ID: D7A048C454CB7054
6 changed files with 52 additions and 63 deletions

View File

@ -80,7 +80,6 @@ void printint(int n);
// proc.c // proc.c
void exit(int); void exit(int);
int fork(void);
void proc_mapstacks(pagetable_t); void proc_mapstacks(pagetable_t);
pagetable_t proc_pagetable(struct proc *); pagetable_t proc_pagetable(struct proc *);
void proc_freepagetable(pagetable_t, uint64); void proc_freepagetable(pagetable_t, uint64);

View File

@ -105,57 +105,6 @@ userinit(void)
release(&p->lock); release(&p->lock);
} }
// Create a new process, copying the parent.
// Sets up child kernel stack to return as if from fork() system call.
int
fork(void)
{
int i, pid;
struct proc *np;
struct proc *p = myproc();
// Allocate process.
if((np = allocproc()) == 0){
return -1;
}
// Copy user memory from parent to child.
if(uvmcopy(p->pagetable, np->pagetable, p->sz) < 0){
freeproc(np);
release(&np->lock);
return -1;
}
np->sz = p->sz;
// copy saved user registers.
*(np->trapframe) = *(p->trapframe);
// Cause fork to return 0 in the child.
np->trapframe->a0 = 0;
// increment reference counts on open file descriptors.
for(i = 0; i < NOFILE; i++)
if(p->ofile[i])
np->ofile[i] = filedup(p->ofile[i]);
np->cwd = idup(p->cwd);
safestrcpy(np->name, p->name, sizeof(p->name));
pid = np->pid;
release(&np->lock);
acquire(&wait_lock);
np->parent = p;
release(&wait_lock);
acquire(&np->lock);
np->state = RUNNABLE;
release(&np->lock);
return pid;
}
// Pass p's abandoned children to init. // Pass p's abandoned children to init.
// Caller must hold wait_lock. // Caller must hold wait_lock.
void reparent(struct proc *p); void reparent(struct proc *p);

View File

@ -91,7 +91,7 @@ extern "C" {
pub fn iinit(); pub fn iinit();
pub fn ialloc(dev: u32, kind: i16) -> *mut DiskInode; pub fn ialloc(dev: u32, kind: i16) -> *mut DiskInode;
pub fn iupdate(ip: *mut DiskInode); pub fn iupdate(ip: *mut DiskInode);
pub fn idup(ip: *mut DiskInode) -> *mut DiskInode; pub fn idup(ip: *mut Inode) -> *mut Inode;
pub fn ilock(ip: *mut Inode); pub fn ilock(ip: *mut Inode);
pub fn iunlock(ip: *mut Inode); pub fn iunlock(ip: *mut Inode);
pub fn iput(ip: *mut Inode); pub fn iput(ip: *mut Inode);

View File

@ -3,13 +3,14 @@
use super::{context::Context, cpu::Cpu, scheduler::wakeup, trapframe::Trapframe}; use super::{context::Context, cpu::Cpu, scheduler::wakeup, 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}, fs::{file::{File, Inode, filedup}, idup},
mem::{ mem::{
kalloc::{kfree, kalloc}, kalloc::{kfree, kalloc},
memset, memset,
virtual_memory::{uvmcreate, uvmfree, uvmunmap, mappages}, virtual_memory::{uvmcreate, uvmfree, uvmunmap, mappages, uvmalloc, uvmdealloc, uvmcopy},
}, },
sync::spinlock::Spinlock, sync::spinlock::Spinlock,
string::safestrcpy,
}; };
use core::{ use core::{
ffi::{c_char, c_void}, ffi::{c_char, c_void},
@ -33,16 +34,11 @@ extern "C" {
pub fn procinit(); pub fn procinit();
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);
// pub fn proc_pagetable(p: *mut Process) -> Pagetable;
// pub fn proc_freepagetable(pagetable: Pagetable, sz: u64);
// pub fn allocproc() -> *mut Process;
pub fn uvmalloc(pagetable: Pagetable, oldsz: u64, newsz: u64, xperm: i32) -> u64;
pub fn uvmdealloc(pagetable: Pagetable, oldsz: u64, newsz: u64) -> u64;
} }
pub static NEXT_PID: AtomicI32 = AtomicI32::new(1); pub static NEXT_PID: AtomicI32 = AtomicI32::new(1);
@ -258,6 +254,51 @@ impl Process {
uvmfree(pagetable, size as u64) uvmfree(pagetable, size as u64)
} }
/// Create a new process, copying the parent.
/// Sets up child kernel stack to return as if from fork() syscall.
pub unsafe fn fork() -> Result<i32, ProcessError> {
let parent = Process::current().unwrap();
let child = Process::alloc()?;
// Copy user memory from parent to child.
if uvmcopy(parent.pagetable, child.pagetable, parent.sz) < 0 {
child.free();
child.lock.unlock();
return Err(ProcessError::Allocation);
}
child.sz = parent.sz;
// Copy saved user registers.
*child.trapframe = *parent.trapframe;
// Cause fork to return 0 in the child.
(*child.trapframe).a0 = 0;
// Increment reference counts on open file descriptors.
for (i, file) in parent.ofile.iter().enumerate() {
if !file.is_null() {
child.ofile[i] = filedup(parent.ofile[i]);
}
}
child.cwd = idup(parent.cwd);
safestrcpy(addr_of!(child.name[0]).cast_mut().cast(), addr_of!(parent.name[0]).cast_mut().cast(), parent.name.len() as i32);
let pid = child.pid;
child.lock.unlock();
{
let _guard = wait_lock.lock();
child.parent = addr_of!(*parent).cast_mut();
}
{
let _guard = child.lock.lock();
child.state = ProcessState::Runnable;
}
Ok(pid)
}
/// 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

View File

@ -12,7 +12,7 @@
/// return-to-user path via usertrapret() doesn't return through /// return-to-user path via usertrapret() doesn't return through
/// the entire kernel call stack. /// the entire kernel call stack.
#[repr(C)] #[repr(C)]
#[derive(Default)] #[derive(Copy, Clone, Default)]
pub struct Trapframe { pub struct Trapframe {
/// Kernel page table. /// Kernel page table.
pub kernel_satp: u64, pub kernel_satp: u64,

View File

@ -57,7 +57,7 @@ pub enum Syscall {
impl Syscall { impl Syscall {
pub unsafe fn call(&self) -> u64 { pub unsafe fn call(&self) -> u64 {
match self { match self {
Syscall::Fork => process::fork() as u64, Syscall::Fork => Process::fork().unwrap_or(-1) as i64 as u64,
Syscall::Exit => { Syscall::Exit => {
let mut n = 0i32; let mut n = 0i32;
argint(0, addr_of_mut!(n)); argint(0, addr_of_mut!(n));