Implement mpsc using semaphores.

This commit is contained in:
Yifan Wu 2021-10-10 17:20:53 -07:00
parent 9bc1e8d2e9
commit 45c33f2ce2
8 changed files with 187 additions and 2 deletions

View file

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

45
os/src/sync/semaphore.rs Normal file
View file

@ -0,0 +1,45 @@
use alloc::{sync::Arc, collections::VecDeque};
use crate::task::{add_task, TaskControlBlock, current_task, block_current_and_run_next};
use crate::sync::UPSafeCell;
pub struct Semaphore {
pub inner: UPSafeCell<SemaphoreInner>,
}
pub struct SemaphoreInner {
pub count: isize,
pub wait_queue: VecDeque<Arc<TaskControlBlock>>,
}
impl Semaphore {
pub fn new(res_count: usize) -> Self {
Self {
inner: unsafe { UPSafeCell::new(
SemaphoreInner {
count: res_count as isize,
wait_queue: VecDeque::new(),
}
)},
}
}
pub fn up(&self) {
let mut inner = self.inner.exclusive_access();
inner.count += 1;
if inner.count <= 0 {
if let Some(task) = inner.wait_queue.pop_front() {
add_task(task);
}
}
}
pub fn down(&self) {
let mut inner = self.inner.exclusive_access();
inner.count -= 1;
if inner.count < 0 {
inner.wait_queue.push_back(current_task().unwrap());
drop(inner);
block_current_and_run_next();
}
}
}

View file

@ -18,6 +18,9 @@ const SYSCALL_WAITTID: usize = 1002;
const SYSCALL_MUTEX_CREATE: usize = 1010;
const SYSCALL_MUTEX_LOCK: usize = 1011;
const SYSCALL_MUTEX_UNLOCK: usize = 1012;
const SYSCALL_SEMAPHORE_CREATE: usize = 1020;
const SYSCALL_SEMAPHORE_UP: usize = 1021;
const SYSCALL_SEMAPHORE_DOWN: usize = 1022;
mod fs;
mod process;
@ -51,6 +54,9 @@ pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize {
SYSCALL_MUTEX_CREATE => sys_mutex_create(args[0] == 1),
SYSCALL_MUTEX_LOCK => sys_mutex_lock(args[0]),
SYSCALL_MUTEX_UNLOCK => sys_mutex_unlock(args[0]),
SYSCALL_SEMAPHORE_CREATE => sys_semaphore_creare(args[0]),
SYSCALL_SEMAPHORE_UP => sys_semaphore_up(args[0]),
SYSCALL_SEMAPHORE_DOWN => sys_semaphore_down(args[0]),
_ => 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::{MutexSpin, MutexBlocking};
use crate::sync::{MutexSpin, MutexBlocking, Semaphore};
use crate::timer::{get_time_ms, add_timer};
use alloc::sync::Arc;
@ -51,3 +51,39 @@ pub fn sys_mutex_unlock(mutex_id: usize) -> isize {
mutex.unlock();
0
}
pub fn sys_semaphore_creare(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
}

View file

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