Implement mpsc using semaphores.
This commit is contained in:
parent
9bc1e8d2e9
commit
45c33f2ce2
8 changed files with 187 additions and 2 deletions
69
user/src/bin/mpsc_sem.rs
Normal file
69
user/src/bin/mpsc_sem.rs
Normal file
|
@ -0,0 +1,69 @@
|
|||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
#[macro_use]
|
||||
extern crate user_lib;
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
use user_lib::{semaphore_create, semaphore_up, semaphore_down};
|
||||
use user_lib::{thread_create, waittid};
|
||||
use user_lib::exit;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
const SEM_MUTEX: usize = 0;
|
||||
const SEM_EMPTY: usize = 1;
|
||||
const SEM_EXISTED: usize = 2;
|
||||
const BUFFER_SIZE: usize = 8;
|
||||
static mut BUFFER: [usize; BUFFER_SIZE] = [0; BUFFER_SIZE];
|
||||
static mut FRONT: usize = 0;
|
||||
static mut TAIL: usize = 0;
|
||||
const PRODUCER_COUNT: usize = 4;
|
||||
const NUMBER_PER_PRODUCER: usize = 100;
|
||||
|
||||
unsafe fn producer(id: *const usize) -> ! {
|
||||
let id = *id;
|
||||
for _ in 0..NUMBER_PER_PRODUCER {
|
||||
semaphore_down(SEM_EMPTY);
|
||||
semaphore_down(SEM_MUTEX);
|
||||
BUFFER[FRONT] = id;
|
||||
FRONT = (FRONT + 1) % BUFFER_SIZE;
|
||||
semaphore_up(SEM_MUTEX);
|
||||
semaphore_up(SEM_EXISTED);
|
||||
}
|
||||
exit(0)
|
||||
}
|
||||
|
||||
unsafe fn consumer() -> ! {
|
||||
for _ in 0..PRODUCER_COUNT * NUMBER_PER_PRODUCER {
|
||||
semaphore_down(SEM_EXISTED);
|
||||
semaphore_down(SEM_MUTEX);
|
||||
print!("{} ", BUFFER[TAIL]);
|
||||
TAIL = (TAIL + 1) % BUFFER_SIZE;
|
||||
semaphore_up(SEM_MUTEX);
|
||||
semaphore_up(SEM_EMPTY);
|
||||
}
|
||||
println!("");
|
||||
exit(0)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn main() -> i32 {
|
||||
// create semaphores
|
||||
assert_eq!(semaphore_create(1) as usize, SEM_MUTEX);
|
||||
assert_eq!(semaphore_create(BUFFER_SIZE) as usize, SEM_EMPTY);
|
||||
assert_eq!(semaphore_create(0) as usize, SEM_EXISTED);
|
||||
// create threads
|
||||
let ids: Vec<_> = (0..PRODUCER_COUNT).collect();
|
||||
let mut threads = Vec::new();
|
||||
for i in 0..PRODUCER_COUNT {
|
||||
threads.push(thread_create(producer as usize, &ids.as_slice()[i] as *const _ as usize));
|
||||
}
|
||||
threads.push(thread_create(consumer as usize, 0));
|
||||
// wait for all threads to complete
|
||||
for thread in threads.iter() {
|
||||
waittid(*thread as usize);
|
||||
}
|
||||
println!("mpsc_sem passed!");
|
||||
0
|
||||
}
|
|
@ -119,4 +119,13 @@ pub fn mutex_create() -> isize { sys_mutex_create(false) }
|
|||
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 {
|
||||
sys_semaphore_create(res_count)
|
||||
}
|
||||
pub fn semaphore_up(sem_id: usize) {
|
||||
sys_semaphore_up(sem_id);
|
||||
}
|
||||
pub fn semaphore_down(sem_id: usize) {
|
||||
sys_semaphore_down(sem_id);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
fn syscall(id: usize, args: [usize; 3]) -> isize {
|
||||
let mut ret: isize;
|
||||
|
@ -113,3 +116,15 @@ pub fn sys_mutex_lock(id: usize) -> isize {
|
|||
pub fn sys_mutex_unlock(id: usize) -> isize {
|
||||
syscall(SYSCALL_MUTEX_UNLOCK, [id, 0, 0])
|
||||
}
|
||||
|
||||
pub fn sys_semaphore_create(res_count: usize) -> isize {
|
||||
syscall(SYSCALL_SEMAPHORE_CREATE, [res_count, 0, 0])
|
||||
}
|
||||
|
||||
pub fn sys_semaphore_up(sem_id: usize) -> isize {
|
||||
syscall(SYSCALL_SEMAPHORE_UP, [sem_id, 0, 0])
|
||||
}
|
||||
|
||||
pub fn sys_semaphore_down(sem_id: usize) -> isize {
|
||||
syscall(SYSCALL_SEMAPHORE_DOWN, [sem_id, 0, 0])
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue