mirror of
https://github.com/rcore-os/rCore-Tutorial-v3.git
synced 2024-11-22 09:26:26 +04:00
add condvar in kernel and app
This commit is contained in:
parent
1c0bbf4404
commit
713e78ea91
39
os/src/sync/condvar.rs
Normal file
39
os/src/sync/condvar.rs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
use alloc::{sync::Arc, collections::VecDeque};
|
||||||
|
use crate::task::{add_task, TaskControlBlock, current_task, block_current_and_run_next};
|
||||||
|
use crate::sync::{Mutex, UPSafeCell};
|
||||||
|
|
||||||
|
pub struct Condvar {
|
||||||
|
pub inner: UPSafeCell<CondvarInner>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct CondvarInner {
|
||||||
|
pub wait_queue: VecDeque<Arc<TaskControlBlock>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Condvar {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
inner: unsafe { UPSafeCell::new(
|
||||||
|
CondvarInner {
|
||||||
|
wait_queue: VecDeque::new(),
|
||||||
|
}
|
||||||
|
)},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn signal(&self) {
|
||||||
|
let mut inner = self.inner.exclusive_access();
|
||||||
|
if let Some(task) = inner.wait_queue.pop_front() {
|
||||||
|
add_task(task);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn wait(&self, mutex:Arc<dyn Mutex>) {
|
||||||
|
mutex.unlock();
|
||||||
|
let mut inner = self.inner.exclusive_access();
|
||||||
|
inner.wait_queue.push_back(current_task().unwrap());
|
||||||
|
drop(inner);
|
||||||
|
block_current_and_run_next();
|
||||||
|
mutex.lock();
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,9 @@
|
|||||||
mod up;
|
mod up;
|
||||||
mod mutex;
|
mod mutex;
|
||||||
mod semaphore;
|
mod semaphore;
|
||||||
|
mod condvar;
|
||||||
|
|
||||||
pub use up::UPSafeCell;
|
pub use up::UPSafeCell;
|
||||||
pub use mutex::{Mutex, MutexSpin, MutexBlocking};
|
pub use mutex::{Mutex, MutexSpin, MutexBlocking};
|
||||||
pub use semaphore::Semaphore;
|
pub use semaphore::Semaphore;
|
||||||
|
pub use condvar::Condvar;
|
@ -21,6 +21,9 @@ const SYSCALL_MUTEX_UNLOCK: usize = 1012;
|
|||||||
const SYSCALL_SEMAPHORE_CREATE: usize = 1020;
|
const SYSCALL_SEMAPHORE_CREATE: usize = 1020;
|
||||||
const SYSCALL_SEMAPHORE_UP: usize = 1021;
|
const SYSCALL_SEMAPHORE_UP: usize = 1021;
|
||||||
const SYSCALL_SEMAPHORE_DOWN: usize = 1022;
|
const SYSCALL_SEMAPHORE_DOWN: usize = 1022;
|
||||||
|
const SYSCALL_CONDVAR_CREATE: usize = 1030;
|
||||||
|
const SYSCALL_CONDVAR_SIGNAL: usize = 1031;
|
||||||
|
const SYSCALL_CONDVAR_WAIT: usize = 1032;
|
||||||
|
|
||||||
mod fs;
|
mod fs;
|
||||||
mod process;
|
mod process;
|
||||||
@ -57,6 +60,9 @@ pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize {
|
|||||||
SYSCALL_SEMAPHORE_CREATE => sys_semaphore_create(args[0]),
|
SYSCALL_SEMAPHORE_CREATE => sys_semaphore_create(args[0]),
|
||||||
SYSCALL_SEMAPHORE_UP => sys_semaphore_up(args[0]),
|
SYSCALL_SEMAPHORE_UP => sys_semaphore_up(args[0]),
|
||||||
SYSCALL_SEMAPHORE_DOWN => sys_semaphore_down(args[0]),
|
SYSCALL_SEMAPHORE_DOWN => sys_semaphore_down(args[0]),
|
||||||
|
SYSCALL_CONDVAR_CREATE => sys_condvar_create(args[0]),
|
||||||
|
SYSCALL_CONDVAR_SIGNAL => sys_condvar_signal(args[0]),
|
||||||
|
SYSCALL_CONDVAR_WAIT => sys_condvar_wait(args[0], args[1]),
|
||||||
_ => panic!("Unsupported syscall_id: {}", syscall_id),
|
_ => panic!("Unsupported syscall_id: {}", syscall_id),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::task::{current_task, current_process, block_current_and_run_next};
|
use crate::task::{current_task, current_process, block_current_and_run_next};
|
||||||
use crate::sync::{Mutex, MutexSpin, MutexBlocking, Semaphore};
|
use crate::sync::{Mutex, MutexSpin, MutexBlocking, Semaphore, Condvar};
|
||||||
use crate::timer::{get_time_ms, add_timer};
|
use crate::timer::{get_time_ms, add_timer};
|
||||||
use alloc::sync::Arc;
|
use alloc::sync::Arc;
|
||||||
|
|
||||||
@ -88,3 +88,41 @@ pub fn sys_semaphore_down(sem_id: usize) -> isize {
|
|||||||
sem.down();
|
sem.down();
|
||||||
0
|
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
|
||||||
|
}
|
@ -4,7 +4,7 @@ use crate::mm::{
|
|||||||
translated_refmut,
|
translated_refmut,
|
||||||
};
|
};
|
||||||
use crate::trap::{TrapContext, trap_handler};
|
use crate::trap::{TrapContext, trap_handler};
|
||||||
use crate::sync::{UPSafeCell, Mutex, Semaphore};
|
use crate::sync::{UPSafeCell, Mutex, Semaphore, Condvar};
|
||||||
use core::cell::RefMut;
|
use core::cell::RefMut;
|
||||||
use super::id::RecycleAllocator;
|
use super::id::RecycleAllocator;
|
||||||
use super::TaskControlBlock;
|
use super::TaskControlBlock;
|
||||||
@ -34,6 +34,7 @@ pub struct ProcessControlBlockInner {
|
|||||||
pub task_res_allocator: RecycleAllocator,
|
pub task_res_allocator: RecycleAllocator,
|
||||||
pub mutex_list: Vec<Option<Arc<dyn Mutex>>>,
|
pub mutex_list: Vec<Option<Arc<dyn Mutex>>>,
|
||||||
pub semaphore_list: Vec<Option<Arc<Semaphore>>>,
|
pub semaphore_list: Vec<Option<Arc<Semaphore>>>,
|
||||||
|
pub condvar_list: Vec<Option<Arc<Condvar>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProcessControlBlockInner {
|
impl ProcessControlBlockInner {
|
||||||
@ -99,6 +100,7 @@ impl ProcessControlBlock {
|
|||||||
task_res_allocator: RecycleAllocator::new(),
|
task_res_allocator: RecycleAllocator::new(),
|
||||||
mutex_list: Vec::new(),
|
mutex_list: Vec::new(),
|
||||||
semaphore_list: Vec::new(),
|
semaphore_list: Vec::new(),
|
||||||
|
condvar_list: Vec::new(),
|
||||||
})}
|
})}
|
||||||
});
|
});
|
||||||
// create a main thread, we should allocate ustack and trap_cx here
|
// create a main thread, we should allocate ustack and trap_cx here
|
||||||
@ -213,6 +215,7 @@ impl ProcessControlBlock {
|
|||||||
task_res_allocator: RecycleAllocator::new(),
|
task_res_allocator: RecycleAllocator::new(),
|
||||||
mutex_list: Vec::new(),
|
mutex_list: Vec::new(),
|
||||||
semaphore_list: Vec::new(),
|
semaphore_list: Vec::new(),
|
||||||
|
condvar_list: Vec::new(),
|
||||||
})}
|
})}
|
||||||
});
|
});
|
||||||
// add child
|
// add child
|
||||||
|
56
user/src/bin/test_condvar.rs
Normal file
56
user/src/bin/test_condvar.rs
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate user_lib;
|
||||||
|
|
||||||
|
extern crate alloc;
|
||||||
|
|
||||||
|
use user_lib::{condvar_create, condvar_signal, condvar_wait, mutex_blocking_create, mutex_lock, mutex_unlock};
|
||||||
|
use user_lib::{thread_create, waittid, sleep};
|
||||||
|
use user_lib::exit;
|
||||||
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
|
static mut A: usize = 0;
|
||||||
|
|
||||||
|
const CONDVAR_ID: usize = 0;
|
||||||
|
const MUTEX_ID: usize = 0;
|
||||||
|
|
||||||
|
unsafe fn first() -> ! {
|
||||||
|
sleep(10);
|
||||||
|
println!("First work, Change A --> 1 and wakeup Second");
|
||||||
|
mutex_lock(MUTEX_ID);
|
||||||
|
A=1;
|
||||||
|
condvar_signal(CONDVAR_ID);
|
||||||
|
mutex_unlock(MUTEX_ID);
|
||||||
|
exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn second() -> ! {
|
||||||
|
println!("Second want to continue,but need to wait A=1");
|
||||||
|
mutex_lock(MUTEX_ID);
|
||||||
|
while A==0 {
|
||||||
|
println!("Second: A is {}", A);
|
||||||
|
condvar_wait(CONDVAR_ID, MUTEX_ID);
|
||||||
|
}
|
||||||
|
mutex_unlock(MUTEX_ID);
|
||||||
|
println!("A is {}, Second can work now", A);
|
||||||
|
exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub fn main() -> i32 {
|
||||||
|
// create condvar & mutex
|
||||||
|
assert_eq!(condvar_create() as usize, CONDVAR_ID);
|
||||||
|
assert_eq!(mutex_blocking_create() as usize, MUTEX_ID);
|
||||||
|
// create threads
|
||||||
|
let mut threads = Vec::new();
|
||||||
|
threads.push(thread_create(first as usize, 0));
|
||||||
|
threads.push(thread_create(second as usize, 0));
|
||||||
|
// wait for all threads to complete
|
||||||
|
for thread in threads.iter() {
|
||||||
|
waittid(*thread as usize);
|
||||||
|
}
|
||||||
|
println!("test_condvar passed!");
|
||||||
|
0
|
||||||
|
}
|
114
user/src/lib.rs
114
user/src/lib.rs
@ -6,16 +6,16 @@
|
|||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
pub mod console;
|
pub mod console;
|
||||||
mod syscall;
|
|
||||||
mod lang_items;
|
mod lang_items;
|
||||||
|
mod syscall;
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate bitflags;
|
extern crate bitflags;
|
||||||
|
|
||||||
use syscall::*;
|
|
||||||
use buddy_system_allocator::LockedHeap;
|
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
use buddy_system_allocator::LockedHeap;
|
||||||
|
use syscall::*;
|
||||||
|
|
||||||
const USER_HEAP_SIZE: usize = 32768;
|
const USER_HEAP_SIZE: usize = 32768;
|
||||||
|
|
||||||
@ -38,16 +38,16 @@ pub extern "C" fn _start(argc: usize, argv: usize) -> ! {
|
|||||||
}
|
}
|
||||||
let mut v: Vec<&'static str> = Vec::new();
|
let mut v: Vec<&'static str> = Vec::new();
|
||||||
for i in 0..argc {
|
for i in 0..argc {
|
||||||
let str_start = unsafe {
|
let str_start =
|
||||||
((argv + i * core::mem::size_of::<usize>()) as *const usize).read_volatile()
|
unsafe { ((argv + i * core::mem::size_of::<usize>()) as *const usize).read_volatile() };
|
||||||
};
|
let len = (0usize..)
|
||||||
let len = (0usize..).find(|i| unsafe {
|
.find(|i| unsafe { ((str_start + *i) as *const u8).read_volatile() == 0 })
|
||||||
((str_start + *i) as *const u8).read_volatile() == 0
|
.unwrap();
|
||||||
}).unwrap();
|
|
||||||
v.push(
|
v.push(
|
||||||
core::str::from_utf8(unsafe {
|
core::str::from_utf8(unsafe {
|
||||||
core::slice::from_raw_parts(str_start as *const u8, len)
|
core::slice::from_raw_parts(str_start as *const u8, len)
|
||||||
}).unwrap()
|
})
|
||||||
|
.unwrap(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
exit(main(argc, v.as_slice()));
|
exit(main(argc, v.as_slice()));
|
||||||
@ -69,22 +69,48 @@ bitflags! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dup(fd: usize) -> isize { sys_dup(fd) }
|
pub fn dup(fd: usize) -> isize {
|
||||||
pub fn open(path: &str, flags: OpenFlags) -> isize { sys_open(path, flags.bits) }
|
sys_dup(fd)
|
||||||
pub fn close(fd: usize) -> isize { sys_close(fd) }
|
}
|
||||||
pub fn pipe(pipe_fd: &mut [usize]) -> isize { sys_pipe(pipe_fd) }
|
pub fn open(path: &str, flags: OpenFlags) -> isize {
|
||||||
pub fn read(fd: usize, buf: &mut [u8]) -> isize { sys_read(fd, buf) }
|
sys_open(path, flags.bits)
|
||||||
pub fn write(fd: usize, buf: &[u8]) -> isize { sys_write(fd, buf) }
|
}
|
||||||
pub fn exit(exit_code: i32) -> ! { sys_exit(exit_code); }
|
pub fn close(fd: usize) -> isize {
|
||||||
pub fn yield_() -> isize { sys_yield() }
|
sys_close(fd)
|
||||||
pub fn get_time() -> isize { sys_get_time() }
|
}
|
||||||
pub fn getpid() -> isize { sys_getpid() }
|
pub fn pipe(pipe_fd: &mut [usize]) -> isize {
|
||||||
pub fn fork() -> isize { sys_fork() }
|
sys_pipe(pipe_fd)
|
||||||
pub fn exec(path: &str, args: &[*const u8]) -> isize { sys_exec(path, args) }
|
}
|
||||||
|
pub fn read(fd: usize, buf: &mut [u8]) -> isize {
|
||||||
|
sys_read(fd, buf)
|
||||||
|
}
|
||||||
|
pub fn write(fd: usize, buf: &[u8]) -> isize {
|
||||||
|
sys_write(fd, buf)
|
||||||
|
}
|
||||||
|
pub fn exit(exit_code: i32) -> ! {
|
||||||
|
sys_exit(exit_code);
|
||||||
|
}
|
||||||
|
pub fn yield_() -> isize {
|
||||||
|
sys_yield()
|
||||||
|
}
|
||||||
|
pub fn get_time() -> isize {
|
||||||
|
sys_get_time()
|
||||||
|
}
|
||||||
|
pub fn getpid() -> isize {
|
||||||
|
sys_getpid()
|
||||||
|
}
|
||||||
|
pub fn fork() -> isize {
|
||||||
|
sys_fork()
|
||||||
|
}
|
||||||
|
pub fn exec(path: &str, args: &[*const u8]) -> isize {
|
||||||
|
sys_exec(path, args)
|
||||||
|
}
|
||||||
pub fn wait(exit_code: &mut i32) -> isize {
|
pub fn wait(exit_code: &mut i32) -> isize {
|
||||||
loop {
|
loop {
|
||||||
match sys_waitpid(-1, exit_code as *mut _) {
|
match sys_waitpid(-1, exit_code as *mut _) {
|
||||||
-2 => { yield_(); }
|
-2 => {
|
||||||
|
yield_();
|
||||||
|
}
|
||||||
// -1 or a real pid
|
// -1 or a real pid
|
||||||
exit_pid => return exit_pid,
|
exit_pid => return exit_pid,
|
||||||
}
|
}
|
||||||
@ -94,7 +120,9 @@ pub fn wait(exit_code: &mut i32) -> isize {
|
|||||||
pub fn waitpid(pid: usize, exit_code: &mut i32) -> isize {
|
pub fn waitpid(pid: usize, exit_code: &mut i32) -> isize {
|
||||||
loop {
|
loop {
|
||||||
match sys_waitpid(pid as isize, exit_code as *mut _) {
|
match sys_waitpid(pid as isize, exit_code as *mut _) {
|
||||||
-2 => { yield_(); }
|
-2 => {
|
||||||
|
yield_();
|
||||||
|
}
|
||||||
// -1 or a real pid
|
// -1 or a real pid
|
||||||
exit_pid => return exit_pid,
|
exit_pid => return exit_pid,
|
||||||
}
|
}
|
||||||
@ -104,21 +132,35 @@ pub fn sleep(sleep_ms: usize) {
|
|||||||
sys_sleep(sleep_ms);
|
sys_sleep(sleep_ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn thread_create(entry: usize, arg: usize) -> isize { sys_thread_create(entry, arg) }
|
pub fn thread_create(entry: usize, arg: usize) -> isize {
|
||||||
pub fn gettid() -> isize { sys_gettid() }
|
sys_thread_create(entry, arg)
|
||||||
|
}
|
||||||
|
pub fn gettid() -> isize {
|
||||||
|
sys_gettid()
|
||||||
|
}
|
||||||
pub fn waittid(tid: usize) -> isize {
|
pub fn waittid(tid: usize) -> isize {
|
||||||
loop {
|
loop {
|
||||||
match sys_waittid(tid) {
|
match sys_waittid(tid) {
|
||||||
-2 => { yield_(); }
|
-2 => {
|
||||||
|
yield_();
|
||||||
|
}
|
||||||
exit_code => return exit_code,
|
exit_code => return exit_code,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mutex_create() -> isize { sys_mutex_create(false) }
|
pub fn mutex_create() -> isize {
|
||||||
pub fn mutex_blocking_create() -> isize { sys_mutex_create(true) }
|
sys_mutex_create(false)
|
||||||
pub fn mutex_lock(mutex_id: usize) { sys_mutex_lock(mutex_id); }
|
}
|
||||||
pub fn mutex_unlock(mutex_id: usize) { sys_mutex_unlock(mutex_id); }
|
pub fn mutex_blocking_create() -> isize {
|
||||||
|
sys_mutex_create(true)
|
||||||
|
}
|
||||||
|
pub fn mutex_lock(mutex_id: usize) {
|
||||||
|
sys_mutex_lock(mutex_id);
|
||||||
|
}
|
||||||
|
pub fn mutex_unlock(mutex_id: usize) {
|
||||||
|
sys_mutex_unlock(mutex_id);
|
||||||
|
}
|
||||||
pub fn semaphore_create(res_count: usize) -> isize {
|
pub fn semaphore_create(res_count: usize) -> isize {
|
||||||
sys_semaphore_create(res_count)
|
sys_semaphore_create(res_count)
|
||||||
}
|
}
|
||||||
@ -128,4 +170,12 @@ pub fn semaphore_up(sem_id: usize) {
|
|||||||
pub fn semaphore_down(sem_id: usize) {
|
pub fn semaphore_down(sem_id: usize) {
|
||||||
sys_semaphore_down(sem_id);
|
sys_semaphore_down(sem_id);
|
||||||
}
|
}
|
||||||
|
pub fn condvar_create() -> isize {
|
||||||
|
sys_condvar_create(0)
|
||||||
|
}
|
||||||
|
pub fn condvar_signal(condvar_id: usize) {
|
||||||
|
sys_condvar_signal(condvar_id);
|
||||||
|
}
|
||||||
|
pub fn condvar_wait(condvar_id: usize, mutex_id: usize) {
|
||||||
|
sys_condvar_wait(condvar_id, mutex_id);
|
||||||
|
}
|
||||||
|
@ -21,6 +21,9 @@ const SYSCALL_MUTEX_UNLOCK: usize = 1012;
|
|||||||
const SYSCALL_SEMAPHORE_CREATE: usize = 1020;
|
const SYSCALL_SEMAPHORE_CREATE: usize = 1020;
|
||||||
const SYSCALL_SEMAPHORE_UP: usize = 1021;
|
const SYSCALL_SEMAPHORE_UP: usize = 1021;
|
||||||
const SYSCALL_SEMAPHORE_DOWN: usize = 1022;
|
const SYSCALL_SEMAPHORE_DOWN: usize = 1022;
|
||||||
|
const SYSCALL_CONDVAR_CREATE: usize = 1030;
|
||||||
|
const SYSCALL_CONDVAR_SIGNAL: usize = 1031;
|
||||||
|
const SYSCALL_CONDVAR_WAIT: usize = 1032;
|
||||||
|
|
||||||
fn syscall(id: usize, args: [usize; 3]) -> isize {
|
fn syscall(id: usize, args: [usize; 3]) -> isize {
|
||||||
let mut ret: isize;
|
let mut ret: isize;
|
||||||
@ -128,3 +131,15 @@ pub fn sys_semaphore_up(sem_id: usize) -> isize {
|
|||||||
pub fn sys_semaphore_down(sem_id: usize) -> isize {
|
pub fn sys_semaphore_down(sem_id: usize) -> isize {
|
||||||
syscall(SYSCALL_SEMAPHORE_DOWN, [sem_id, 0, 0])
|
syscall(SYSCALL_SEMAPHORE_DOWN, [sem_id, 0, 0])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn sys_condvar_create(_arg: usize) -> isize {
|
||||||
|
syscall(SYSCALL_CONDVAR_CREATE, [_arg, 0, 0])
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sys_condvar_signal(condvar_id: usize) -> isize {
|
||||||
|
syscall(SYSCALL_CONDVAR_SIGNAL, [condvar_id, 0, 0])
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sys_condvar_wait(condvar_id: usize, mutex_id:usize) -> isize {
|
||||||
|
syscall(SYSCALL_CONDVAR_WAIT, [condvar_id, mutex_id, 0])
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user