add condvar in kernel and app

This commit is contained in:
Yu Chen 2021-12-13 15:30:27 +08:00
parent a3ec647496
commit b3bce3bef2
8 changed files with 243 additions and 34 deletions

39
os/src/sync/condvar.rs Normal file
View 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();
}
}

View file

@ -1,7 +1,9 @@
mod up;
mod mutex;
mod semaphore;
mod condvar;
pub use up::UPSafeCell;
pub use mutex::{Mutex, MutexSpin, MutexBlocking};
pub use semaphore::Semaphore;
pub use condvar::Condvar;

View file

@ -21,6 +21,9 @@ const SYSCALL_MUTEX_UNLOCK: usize = 1012;
const SYSCALL_SEMAPHORE_CREATE: usize = 1020;
const SYSCALL_SEMAPHORE_UP: usize = 1021;
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 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_UP => sys_semaphore_up(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),
}
}

View file

@ -1,5 +1,5 @@
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 alloc::sync::Arc;
@ -88,3 +88,41 @@ pub fn sys_semaphore_down(sem_id: usize) -> isize {
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
}

View file

@ -4,7 +4,7 @@ use crate::mm::{
translated_refmut,
};
use crate::trap::{TrapContext, trap_handler};
use crate::sync::{UPSafeCell, Mutex, Semaphore};
use crate::sync::{UPSafeCell, Mutex, Semaphore, Condvar};
use core::cell::RefMut;
use super::id::RecycleAllocator;
use super::TaskControlBlock;
@ -34,6 +34,7 @@ pub struct ProcessControlBlockInner {
pub task_res_allocator: RecycleAllocator,
pub mutex_list: Vec<Option<Arc<dyn Mutex>>>,
pub semaphore_list: Vec<Option<Arc<Semaphore>>>,
pub condvar_list: Vec<Option<Arc<Condvar>>>,
}
impl ProcessControlBlockInner {
@ -99,6 +100,7 @@ impl ProcessControlBlock {
task_res_allocator: RecycleAllocator::new(),
mutex_list: Vec::new(),
semaphore_list: Vec::new(),
condvar_list: Vec::new(),
})}
});
// create a main thread, we should allocate ustack and trap_cx here
@ -213,6 +215,7 @@ impl ProcessControlBlock {
task_res_allocator: RecycleAllocator::new(),
mutex_list: Vec::new(),
semaphore_list: Vec::new(),
condvar_list: Vec::new(),
})}
});
// add child