implement allocproc in rust
This commit is contained in:
parent
3de7d1c829
commit
1c3e73ba3f
@ -56,47 +56,7 @@ procinit(void)
|
|||||||
// If found, initialize state required to run in the kernel,
|
// If found, initialize state required to run in the kernel,
|
||||||
// and return with p->lock held.
|
// and return with p->lock held.
|
||||||
// If there are no free procs, or a memory allocation fails, return 0.
|
// If there are no free procs, or a memory allocation fails, return 0.
|
||||||
struct proc* allocproc(void)
|
struct proc *allocproc(void);
|
||||||
{
|
|
||||||
struct proc *p;
|
|
||||||
|
|
||||||
for(p = proc; p < &proc[NPROC]; p++) {
|
|
||||||
acquire(&p->lock);
|
|
||||||
if(p->state == UNUSED) {
|
|
||||||
goto found;
|
|
||||||
} else {
|
|
||||||
release(&p->lock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
found:
|
|
||||||
p->pid = allocpid();
|
|
||||||
p->state = USED;
|
|
||||||
|
|
||||||
// Allocate a trapframe page.
|
|
||||||
if((p->trapframe = (struct trapframe *)kalloc()) == 0){
|
|
||||||
freeproc(p);
|
|
||||||
release(&p->lock);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// An empty user page table.
|
|
||||||
p->pagetable = proc_pagetable(p);
|
|
||||||
if(p->pagetable == 0){
|
|
||||||
freeproc(p);
|
|
||||||
release(&p->lock);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set up new context to start executing at forkret,
|
|
||||||
// which returns to user space.
|
|
||||||
memset(&p->context, 0, sizeof(p->context));
|
|
||||||
p->context.ra = (uint64)forkret;
|
|
||||||
p->context.sp = p->kstack + PGSIZE;
|
|
||||||
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a user page table for a given process, with no user memory,
|
// Create a user page table for a given process, with no user memory,
|
||||||
// but with trampoline and trapframe pages.
|
// but with trampoline and trapframe pages.
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
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},
|
arch::riscv::{Pagetable, PTE_W, PGSIZE},
|
||||||
fs::file::{File, Inode},
|
fs::file::{File, Inode},
|
||||||
mem::kalloc::kfree,
|
mem::{kalloc::{kfree, kalloc}, memset},
|
||||||
sync::spinlock::Spinlock,
|
sync::spinlock::Spinlock,
|
||||||
};
|
};
|
||||||
use core::{
|
use core::{
|
||||||
@ -36,7 +36,7 @@ extern "C" {
|
|||||||
pub fn proc_mapstacks(kpgtbl: Pagetable);
|
pub fn proc_mapstacks(kpgtbl: Pagetable);
|
||||||
pub fn proc_pagetable(p: *mut Process) -> Pagetable;
|
pub fn proc_pagetable(p: *mut Process) -> Pagetable;
|
||||||
pub fn proc_freepagetable(pagetable: Pagetable, sz: u64);
|
pub fn proc_freepagetable(pagetable: Pagetable, sz: u64);
|
||||||
pub fn allocproc() -> *mut Process;
|
// pub fn allocproc() -> *mut Process;
|
||||||
pub fn uvmalloc(pagetable: Pagetable, oldsz: u64, newsz: u64, xperm: i32) -> u64;
|
pub fn uvmalloc(pagetable: Pagetable, oldsz: u64, newsz: u64, xperm: i32) -> u64;
|
||||||
pub fn uvmdealloc(pagetable: Pagetable, oldsz: u64, newsz: u64) -> u64;
|
pub fn uvmdealloc(pagetable: Pagetable, oldsz: u64, newsz: u64) -> u64;
|
||||||
}
|
}
|
||||||
@ -57,6 +57,7 @@ pub enum ProcessState {
|
|||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||||
pub enum ProcessError {
|
pub enum ProcessError {
|
||||||
|
MaxProcesses,
|
||||||
Allocation,
|
Allocation,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,6 +133,53 @@ impl Process {
|
|||||||
pub fn alloc_pid() -> i32 {
|
pub fn alloc_pid() -> i32 {
|
||||||
NEXT_PID.fetch_add(1, Ordering::SeqCst)
|
NEXT_PID.fetch_add(1, Ordering::SeqCst)
|
||||||
}
|
}
|
||||||
|
/// Look in the process table for an UNUSED proc.
|
||||||
|
/// If found, initialize state required to run in the kernel,
|
||||||
|
/// and return with p.lock held.
|
||||||
|
/// If there are no free procs, or a memory allocation fails, return an error.
|
||||||
|
pub unsafe fn alloc() -> Result<&'static mut Process, ProcessError> {
|
||||||
|
let mut index: Option<usize> = None;
|
||||||
|
for (i, p) in &mut proc.iter_mut().enumerate() {
|
||||||
|
p.lock.lock_unguarded();
|
||||||
|
if p.state == ProcessState::Unused {
|
||||||
|
index = Some(i);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
p.lock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let Some(index) = index else {
|
||||||
|
return Err(ProcessError::MaxProcesses);
|
||||||
|
};
|
||||||
|
|
||||||
|
let p: &mut Process = &mut proc[index];
|
||||||
|
p.pid = Process::alloc_pid();
|
||||||
|
p.state = ProcessState::Used;
|
||||||
|
|
||||||
|
// Allocate a trapframe page.
|
||||||
|
p.trapframe = kalloc() as *mut Trapframe;
|
||||||
|
if p.trapframe.is_null() {
|
||||||
|
p.free();
|
||||||
|
p.lock.unlock();
|
||||||
|
return Err(ProcessError::Allocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
// An empty user page table.
|
||||||
|
p.pagetable = proc_pagetable(addr_of_mut!(*p));
|
||||||
|
if p.pagetable.is_null() {
|
||||||
|
p.free();
|
||||||
|
p.lock.unlock();
|
||||||
|
return Err(ProcessError::Allocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up new context to start executing at forkret,
|
||||||
|
// which returns to userspace.
|
||||||
|
memset(addr_of_mut!(p.context).cast(), 0, core::mem::size_of::<Context>() as u32);
|
||||||
|
p.context.ra = forkret as usize as u64;
|
||||||
|
p.context.sp = p.kstack + PGSIZE;
|
||||||
|
|
||||||
|
Ok(p)
|
||||||
|
}
|
||||||
|
|
||||||
/// Free a proc structure and the data hanging from it, including user pages.
|
/// Free a proc structure and the data hanging from it, including user pages.
|
||||||
/// self.lock must be held.
|
/// self.lock must be held.
|
||||||
@ -223,6 +271,15 @@ pub extern "C" fn allocpid() -> i32 {
|
|||||||
Process::alloc_pid()
|
Process::alloc_pid()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn allocproc() -> *mut Process {
|
||||||
|
if let Ok(process) = Process::alloc() {
|
||||||
|
process as *mut Process
|
||||||
|
} else {
|
||||||
|
null_mut()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Free a proc structure and the data hanging from it, including user pages.
|
/// Free a proc structure and the data hanging from it, including user pages.
|
||||||
/// p->lock must be held.
|
/// p->lock must be held.
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user