    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55

    use super::{ProcessControlBlock, TaskControlBlock};
    use crate::sync::UPSafeCell;
    use alloc::collections::{BTreeMap, VecDeque};
    use alloc::sync::Arc;
    use lazy_static::*;

    pub struct TaskManager {
        ready_queue: VecDeque<Arc<TaskControlBlock>>,
    }

    /// A simple FIFO scheduler.
    impl TaskManager {
        pub fn new() -> Self {
            Self {
                ready_queue: VecDeque::new(),
            }
        }
        pub fn add(&mut self, task: Arc<TaskControlBlock>) {
            self.ready_queue.push_back(task);
        }
        pub fn fetch(&mut self) -> Option<Arc<TaskControlBlock>> {
            self.ready_queue.pop_front()
        }
    }

    lazy_static! {
        pub static ref TASK_MANAGER: UPSafeCell<TaskManager> =
            unsafe { UPSafeCell::new(TaskManager::new()) };
        pub static ref PID2PCB: UPSafeCell<BTreeMap<usize, Arc<ProcessControlBlock>>> =
            unsafe { UPSafeCell::new(BTreeMap::new()) };
    }

    pub fn add_task(task: Arc<TaskControlBlock>) {
        TASK_MANAGER.exclusive_access().add(task);
    }

    pub fn fetch_task() -> Option<Arc<TaskControlBlock>> {
        TASK_MANAGER.exclusive_access().fetch()
    }

    pub fn pid2process(pid: usize) -> Option<Arc<ProcessControlBlock>> {
        let map = PID2PCB.exclusive_access();
        map.get(&pid).map(Arc::clone)
    }

    pub fn insert_into_pid2process(pid: usize, process: Arc<ProcessControlBlock>) {
        PID2PCB.exclusive_access().insert(pid, process);
    }

    pub fn remove_from_pid2process(pid: usize) {
        let mut map = PID2PCB.exclusive_access();
        if map.remove(&pid).is_none() {
            panic!("cannot find pid {} in pid2task!", pid);
        }
    }