# mod.rs - source
Source of the Rust file `src/task/mod.rs`.
Keywords: rust, rustlang, rust-lang

      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
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103

    mod context;
    mod manager;
    mod pid;
    mod processor;
    mod signal;
    mod switch;
    #[allow(clippy::module_inception)]
    mod task;

    use crate::fs::{open_file, OpenFlags};
    use alloc::sync::Arc;
    pub use context::TaskContext;
    use lazy_static::*;
    use manager::fetch_task;
    use manager::remove_from_pid2task;
    use switch::__switch;
    use task::{TaskControlBlock, TaskStatus};

    pub use manager::{add_task, pid2task};
    pub use pid::{pid_alloc, KernelStack, PidHandle};
    pub use processor::{
        current_task, current_trap_cx, current_user_token, run_tasks, schedule, take_current_task,
    };
    pub use signal::SignalFlags;

    pub fn suspend_current_and_run_next() {
        // There must be an application running.
        let task = take_current_task().unwrap();

        // ---- access current TCB exclusively
        let mut task_inner = task.inner_exclusive_access();
        let task_cx_ptr = &mut task_inner.task_cx as *mut TaskContext;
        // Change status to Ready
        task_inner.task_status = TaskStatus::Ready;
        drop(task_inner);
        // ---- release current PCB

        // push back to ready queue.
        add_task(task);
        // jump to scheduling cycle
        schedule(task_cx_ptr);
    }

    pub fn exit_current_and_run_next(exit_code: i32) {
        // take from Processor
        let task = take_current_task().unwrap();
        // remove from pid2task
        remove_from_pid2task(task.getpid());
        // **** access current TCB exclusively
        let mut inner = task.inner_exclusive_access();
        // Change status to Zombie
        inner.task_status = TaskStatus::Zombie;
        // Record exit code
        inner.exit_code = exit_code;
        // do not move to its parent but under initproc

        // ++++++ access initproc TCB exclusively
        {
            let mut initproc_inner = INITPROC.inner_exclusive_access();
            for child in inner.children.iter() {
                child.inner_exclusive_access().parent = Some(Arc::downgrade(&INITPROC));
                initproc_inner.children.push(child.clone());
            }
        }
        // ++++++ release parent PCB

        inner.children.clear();
        // deallocate user space
        inner.memory_set.recycle_data_pages();
        // drop file descriptors
        inner.fd_table.clear();
        drop(inner);
        // **** release current PCB
        // drop task manually to maintain rc correctly
        drop(task);
        // we do not have to save task context
        let mut _unused = TaskContext::zero_init();
        schedule(&mut _unused as *mut _);
    }

    lazy_static! {
        pub static ref INITPROC: Arc<TaskControlBlock> = Arc::new({
            let inode = open_file("initproc", OpenFlags::RDONLY).unwrap();
            let v = inode.read_all();
            TaskControlBlock::new(v.as_slice())
        });
    }

    pub fn add_initproc() {
        add_task(INITPROC.clone());
    }

    pub fn check_signals_of_current() -> Option<(i32, &'static str)> {
        let task = current_task().unwrap();
        let task_inner = task.inner_exclusive_access();
        task_inner.signals.check_error()
    }

    pub fn current_add_signal(signal: SignalFlags) {
        let task = current_task().unwrap();
        let mut task_inner = task.inner_exclusive_access();
        task_inner.signals |= signal;
    }