Implement sys_read && allocate pid and kernel stack dynamically.
This commit is contained in:
parent
a9066d75e5
commit
58dbb3ffa5
7 changed files with 162 additions and 19 deletions
|
@ -3,6 +3,7 @@ mod switch;
|
|||
mod task;
|
||||
mod manager;
|
||||
mod processor;
|
||||
mod pid;
|
||||
|
||||
use crate::loader::{get_num_app, get_app_data};
|
||||
use crate::trap::TrapContext;
|
||||
|
@ -14,6 +15,7 @@ use alloc::vec::Vec;
|
|||
use alloc::sync::Arc;
|
||||
use spin::Mutex;
|
||||
use manager::fetch_task;
|
||||
use pid::{PidHandle, pid_alloc, KernelStack};
|
||||
|
||||
pub use context::TaskContext;
|
||||
pub use processor::{
|
||||
|
|
104
os/src/task/pid.rs
Normal file
104
os/src/task/pid.rs
Normal 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());
|
||||
}
|
||||
}
|
|
@ -2,12 +2,14 @@ use crate::mm::{MemorySet, MapPermission, PhysPageNum, KERNEL_SPACE, VirtAddr};
|
|||
use crate::trap::{TrapContext, trap_handler};
|
||||
use crate::config::{TRAP_CONTEXT, kernel_stack_position};
|
||||
use super::TaskContext;
|
||||
use super::{PidHandle, pid_alloc, KernelStack};
|
||||
|
||||
pub struct TaskControlBlock {
|
||||
// immutable
|
||||
pub trap_cx_ppn: PhysPageNum,
|
||||
pub base_size: usize,
|
||||
//pub pid: usize,
|
||||
pub pid: PidHandle,
|
||||
pub kernel_stack: KernelStack,
|
||||
// mutable
|
||||
pub task_cx_ptr: usize,
|
||||
pub task_status: TaskStatus,
|
||||
|
@ -32,23 +34,20 @@ impl TaskControlBlock {
|
|||
.unwrap()
|
||||
.ppn();
|
||||
let task_status = TaskStatus::Ready;
|
||||
// map a kernel-stack in kernel space
|
||||
let (kernel_stack_bottom, kernel_stack_top) = kernel_stack_position(app_id);
|
||||
KERNEL_SPACE
|
||||
.lock()
|
||||
.insert_framed_area(
|
||||
kernel_stack_bottom.into(),
|
||||
kernel_stack_top.into(),
|
||||
MapPermission::R | MapPermission::W,
|
||||
);
|
||||
let task_cx_ptr = (kernel_stack_top - core::mem::size_of::<TaskContext>()) as *mut TaskContext;
|
||||
unsafe { *task_cx_ptr = TaskContext::goto_trap_return(); }
|
||||
// alloc a pid and a kernel stack in kernel space
|
||||
let pid_handle = pid_alloc();
|
||||
let kernel_stack = KernelStack::new(&pid_handle);
|
||||
let kernel_stack_top = kernel_stack.get_top();
|
||||
// push a task context which goes to trap_return to the top of kernel stack
|
||||
let task_cx_ptr = kernel_stack.push_on_top(TaskContext::goto_trap_return());
|
||||
let task_control_block = Self {
|
||||
trap_cx_ppn,
|
||||
base_size: user_sp,
|
||||
pid: pid_handle,
|
||||
kernel_stack,
|
||||
task_cx_ptr: task_cx_ptr as usize,
|
||||
task_status,
|
||||
memory_set,
|
||||
trap_cx_ppn,
|
||||
base_size: user_sp,
|
||||
};
|
||||
// prepare TrapContext in user space
|
||||
let trap_cx = task_control_block.get_trap_cx();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue