    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
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134

    use crate::sync::{Condvar, Mutex, MutexBlocking, MutexSpin, Semaphore};
    use crate::task::{block_current_and_run_next, current_process, current_task};
    use crate::timer::{add_timer, get_time_ms};
    use alloc::sync::Arc;

    pub fn sys_sleep(ms: usize) -> isize {
        let expire_ms = get_time_ms() + ms;
        let task = current_task().unwrap();
        add_timer(expire_ms, task);
        block_current_and_run_next();
        0
    }

    pub fn sys_mutex_create(blocking: bool) -> isize {
        let process = current_process();
        let mutex: Option<Arc<dyn Mutex>> = if !blocking {
            Some(Arc::new(MutexSpin::new()))
        } else {
            Some(Arc::new(MutexBlocking::new()))
        };
        let mut process_inner = process.inner_exclusive_access();
        if let Some(id) = process_inner
            .mutex_list
            .iter()
            .enumerate()
            .find(|(_, item)| item.is_none())
            .map(|(id, _)| id)
        {
            process_inner.mutex_list[id] = mutex;
            id as isize
        } else {
            process_inner.mutex_list.push(mutex);
            process_inner.mutex_list.len() as isize - 1
        }
    }

    pub fn sys_mutex_lock(mutex_id: usize) -> isize {
        let process = current_process();
        let process_inner = process.inner_exclusive_access();
        let mutex = Arc::clone(process_inner.mutex_list[mutex_id].as_ref().unwrap());
        drop(process_inner);
        drop(process);
        mutex.lock();
        0
    }

    pub fn sys_mutex_unlock(mutex_id: usize) -> isize {
        let process = current_process();
        let process_inner = process.inner_exclusive_access();
        let mutex = Arc::clone(process_inner.mutex_list[mutex_id].as_ref().unwrap());
        drop(process_inner);
        drop(process);
        mutex.unlock();
        0
    }

    pub fn sys_semaphore_create(res_count: usize) -> isize {
        let process = current_process();
        let mut process_inner = process.inner_exclusive_access();
        let id = if let Some(id) = process_inner
            .semaphore_list
            .iter()
            .enumerate()
            .find(|(_, item)| item.is_none())
            .map(|(id, _)| id)
        {
            process_inner.semaphore_list[id] = Some(Arc::new(Semaphore::new(res_count)));
            id
        } else {
            process_inner
                .semaphore_list
                .push(Some(Arc::new(Semaphore::new(res_count))));
            process_inner.semaphore_list.len() - 1
        };
        id as isize
    }

    pub fn sys_semaphore_up(sem_id: usize) -> isize {
        let process = current_process();
        let process_inner = process.inner_exclusive_access();
        let sem = Arc::clone(process_inner.semaphore_list[sem_id].as_ref().unwrap());
        drop(process_inner);
        sem.up();
        0
    }

    pub fn sys_semaphore_down(sem_id: usize) -> isize {
        let process = current_process();
        let process_inner = process.inner_exclusive_access();
        let sem = Arc::clone(process_inner.semaphore_list[sem_id].as_ref().unwrap());
        drop(process_inner);
        sem.down();
        0
    }

    pub fn sys_condvar_create(_arg: usize) -> isize {
        let process = current_process();
        let mut process_inner = process.inner_exclusive_access();
        let id = if let Some(id) = process_inner
            .condvar_list
            .iter()
            .enumerate()
            .find(|(_, item)| item.is_none())
            .map(|(id, _)| id)
        {
            process_inner.condvar_list[id] = Some(Arc::new(Condvar::new()));
            id
        } else {
            process_inner
                .condvar_list
                .push(Some(Arc::new(Condvar::new())));
            process_inner.condvar_list.len() - 1
        };
        id as isize
    }

    pub fn sys_condvar_signal(condvar_id: usize) -> isize {
        let process = current_process();
        let process_inner = process.inner_exclusive_access();
        let condvar = Arc::clone(process_inner.condvar_list[condvar_id].as_ref().unwrap());
        drop(process_inner);
        condvar.signal();
        0
    }

    pub fn sys_condvar_wait(condvar_id: usize, mutex_id: usize) -> isize {
        let process = current_process();
        let process_inner = process.inner_exclusive_access();
        let condvar = Arc::clone(process_inner.condvar_list[condvar_id].as_ref().unwrap());
        let mutex = Arc::clone(process_inner.mutex_list[mutex_id].as_ref().unwrap());
        drop(process_inner);
        condvar.wait(mutex);
        0
    }