Skip to main content

os/task/
pid.rs

1use crate::config::{KERNEL_STACK_SIZE, PAGE_SIZE, TRAMPOLINE};
2use crate::mm::{KERNEL_SPACE, MapPermission, VirtAddr};
3use crate::sync::UPSafeCell;
4use alloc::vec::Vec;
5use lazy_static::*;
6
7struct PidAllocator {
8    current: usize,
9    recycled: Vec<usize>,
10}
11
12impl PidAllocator {
13    pub fn new() -> Self {
14        PidAllocator {
15            current: 1,
16            recycled: Vec::new(),
17        }
18    }
19    pub fn alloc(&mut self) -> PidHandle {
20        if let Some(pid) = self.recycled.pop() {
21            PidHandle(pid)
22        } else {
23            self.current += 1;
24            PidHandle(self.current - 1)
25        }
26    }
27    pub fn dealloc(&mut self, pid: usize) {
28        assert!(pid < self.current);
29        assert!(
30            !self.recycled.iter().any(|ppid| *ppid == pid),
31            "pid {} has been deallocated!",
32            pid
33        );
34        self.recycled.push(pid);
35    }
36}
37
38lazy_static! {
39    static ref PID_ALLOCATOR: UPSafeCell<PidAllocator> =
40        unsafe { UPSafeCell::new(PidAllocator::new()) };
41}
42
43pub struct PidHandle(pub usize);
44
45impl Drop for PidHandle {
46    fn drop(&mut self) {
47        //println!("drop pid {}", self.0);
48        PID_ALLOCATOR.exclusive_access().dealloc(self.0);
49    }
50}
51
52pub fn pid_alloc() -> PidHandle {
53    PID_ALLOCATOR.exclusive_access().alloc()
54}
55
56/// Return (bottom, top) of a kernel stack in kernel space.
57pub fn kernel_stack_position(app_id: usize) -> (usize, usize) {
58    let top = TRAMPOLINE - app_id * (KERNEL_STACK_SIZE + PAGE_SIZE);
59    let bottom = top - KERNEL_STACK_SIZE;
60    (bottom, top)
61}
62
63pub struct KernelStack {
64    pid: usize,
65}
66
67impl KernelStack {
68    pub fn new(pid_handle: &PidHandle) -> Self {
69        let pid = pid_handle.0;
70        let (kernel_stack_bottom, kernel_stack_top) = kernel_stack_position(pid);
71        KERNEL_SPACE.exclusive_access().insert_framed_area(
72            kernel_stack_bottom.into(),
73            kernel_stack_top.into(),
74            MapPermission::R | MapPermission::W,
75        );
76        KernelStack { pid: pid_handle.0 }
77    }
78    #[allow(unused)]
79    pub fn push_on_top<T>(&self, value: T) -> *mut T
80    where
81        T: Sized,
82    {
83        let kernel_stack_top = self.get_top();
84        let ptr_mut = (kernel_stack_top - core::mem::size_of::<T>()) as *mut T;
85        unsafe {
86            *ptr_mut = value;
87        }
88        ptr_mut
89    }
90    pub fn get_top(&self) -> usize {
91        let (_, kernel_stack_top) = kernel_stack_position(self.pid);
92        kernel_stack_top
93    }
94}
95
96impl Drop for KernelStack {
97    fn drop(&mut self) {
98        let (kernel_stack_bottom, _) = kernel_stack_position(self.pid);
99        let kernel_stack_bottom_va: VirtAddr = kernel_stack_bottom.into();
100        KERNEL_SPACE
101            .exclusive_access()
102            .remove_area_with_start_vpn(kernel_stack_bottom_va.into());
103    }
104}