Implement sys_read && allocate pid and kernel stack dynamically.

This commit is contained in:
Yifan Wu 2020-12-08 17:17:28 +08:00
parent 1bc53c0b5f
commit eddbc8954c
7 changed files with 162 additions and 19 deletions

104
os/src/task/pid.rs Normal file
View file

@ -0,0 +1,104 @@
use alloc::vec::Vec;
use lazy_static::*;
use spin::Mutex;
use crate::mm::{KERNEL_SPACE, MapPermission, VirtAddr};
use crate::config::{
PAGE_SIZE,
TRAMPOLINE,
KERNEL_STACK_SIZE,
};
struct PidAllocator {
current: usize,
recycled: Vec<usize>,
}
impl PidAllocator {
pub fn new() -> Self {
PidAllocator {
current: 0,
recycled: Vec::new(),
}
}
pub fn alloc(&mut self) -> PidHandle {
if let Some(pid) = self.recycled.pop() {
PidHandle(pid)
} else {
self.current += 1;
PidHandle(self.current - 1)
}
}
pub fn dealloc(&mut self, pid: usize) {
assert!(pid < self.current);
assert!(
self.recycled.iter().find(|ppid| **ppid == pid).is_none(),
"pid {} has been deallocated!", pid
);
self.recycled.push(pid);
}
}
lazy_static! {
static ref PID_ALLOCATOR : Mutex<PidAllocator> = Mutex::new(PidAllocator::new());
}
pub struct PidHandle(pub usize);
impl Drop for PidHandle {
fn drop(&mut self) {
PID_ALLOCATOR.lock().dealloc(self.0);
}
}
pub fn pid_alloc() -> PidHandle {
PID_ALLOCATOR.lock().alloc()
}
/// Return (bottom, top) of a kernel stack in kernel space.
pub fn kernel_stack_position(app_id: usize) -> (usize, usize) {
let top = TRAMPOLINE - app_id * (KERNEL_STACK_SIZE + PAGE_SIZE);
let bottom = top - KERNEL_STACK_SIZE;
(bottom, top)
}
pub struct KernelStack {
pid: usize,
}
impl KernelStack {
pub fn new(pid_handle: &PidHandle) -> Self {
let pid = pid_handle.0;
let (kernel_stack_bottom, kernel_stack_top) = kernel_stack_position(pid);
KERNEL_SPACE
.lock()
.insert_framed_area(
kernel_stack_bottom.into(),
kernel_stack_top.into(),
MapPermission::R | MapPermission::W,
);
KernelStack {
pid: pid_handle.0,
}
}
pub fn push_on_top<T>(&self, value: T) -> *mut T where
T: Sized, {
let (_, kernel_stack_top) = kernel_stack_position(self.pid);
let ptr_mut = (kernel_stack_top - core::mem::size_of::<T>()) as *mut T;
unsafe { *ptr_mut = value; }
ptr_mut
}
pub fn get_top(&self) -> usize {
let (_, kernel_stack_top) = kernel_stack_position(self.pid);
kernel_stack_top
}
}
impl Drop for KernelStack {
fn drop(&mut self) {
let (kernel_stack_bottom, _) = kernel_stack_position(self.pid);
let kernel_stack_bottom_va: VirtAddr = kernel_stack_bottom.into();
KERNEL_SPACE
.lock()
.remove_area_with_start_vpn(kernel_stack_bottom_va.into());
}
}