      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
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145

    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 {
        kprintln!("[KERN] syscall::sync::sys_sleep begin");
        let expire_ms = get_time_ms() + ms;
        let task = current_task().unwrap();
        add_timer(expire_ms, task);
        block_current_and_run_next();
        kprintln!("[KERN] syscall::sync::sys_sleep end");
        0
    }

    pub fn sys_mutex_create(blocking: bool) -> isize {
        kprintln!("[KERN] syscall::sync::sys_mutex_create begin");
        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 {
        kprintln!("[KERN] syscall::sync::sys_mutex_lock begin");
        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 {
        kprintln!("[KERN] syscall::sync::sys_mutex_unlock begin");
        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 {
        kprintln!("[KERN] syscall::sync::sys_semaphore_create begin");
        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 {
        kprintln!("[KERN] syscall::sync::sys_semaphore_up begin");
        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 {
        kprintln!("[KERN] syscall::sync::sys_semaphore_down begin");
        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 {
        kprintln!("[KERN] syscall::sync::sys_condvar_create begin");
        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 {
        kprintln!("[KERN] syscall::sync::sys_condvar_signal begin");
        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 {
        kprintln!("[KERN] syscall::sync::sys_condvar_wait begin");
        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_with_mutex(mutex);
        0
    }