diff --git a/user/Cargo.toml b/user/Cargo.toml index 7b1233e00..d1816c64f 100644 --- a/user/Cargo.toml +++ b/user/Cargo.toml @@ -10,6 +10,7 @@ edition = "2018" buddy_system_allocator = "0.6" bitflags = "1.2.1" riscv = { git = "https://github.com/rcore-os/riscv", features = ["inline-asm"] } +lazy_static = { version = "1.4.0", features = ["spin_no_std"] } embedded-graphics = "0.7.1" oorandom ="11" virtio-input-decoder = "0.1.4" diff --git a/user/src/bin/barrier_condvar.rs b/user/src/bin/barrier_condvar.rs new file mode 100644 index 000000000..db0a80ba3 --- /dev/null +++ b/user/src/bin/barrier_condvar.rs @@ -0,0 +1,72 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate user_lib; +extern crate alloc; + +use user_lib::{thread_create, exit, waittid, mutex_create, mutex_lock, mutex_unlock, condvar_create, condvar_signal, condvar_wait}; +use alloc::vec::Vec; +use core::cell::UnsafeCell; +use lazy_static::*; + +const THREAD_NUM: usize = 3; + +struct Barrier { + mutex_id: usize, + condvar_id: usize, + count: UnsafeCell, +} + +impl Barrier { + pub fn new() -> Self { + Self { + mutex_id: mutex_create() as usize, + condvar_id: condvar_create() as usize, + count: UnsafeCell::new(0), + } + } + pub fn block(&self) { + mutex_lock(self.mutex_id); + let mut count = self.count.get(); + // SAFETY: Here, the accesses of the count is in the + // critical section protected by the mutex. + unsafe { *count = *count + 1; } + if unsafe { *count } == THREAD_NUM { + condvar_signal(self.condvar_id); + } else { + condvar_wait(self.condvar_id, self.mutex_id); + condvar_signal(self.condvar_id); + } + mutex_unlock(self.mutex_id); + } +} + +unsafe impl Sync for Barrier {} + +lazy_static! { + static ref BARRIER_AB: Barrier = Barrier::new(); + static ref BARRIER_BC: Barrier = Barrier::new(); +} + +fn thread_fn() { + for _ in 0..300 { print!("a"); } + BARRIER_AB.block(); + for _ in 0..300 { print!("b"); } + BARRIER_BC.block(); + for _ in 0..300 { print!("c"); } + exit(0) +} + +#[no_mangle] +pub fn main() -> i32 { + let mut v: Vec = Vec::new(); + for _ in 0..THREAD_NUM { + v.push(thread_create(thread_fn as usize, 0)); + } + for tid in v.into_iter() { + waittid(tid as usize); + } + println!("\nOK!"); + 0 +} diff --git a/user/src/bin/barrier_fail.rs b/user/src/bin/barrier_fail.rs new file mode 100644 index 000000000..0eb4b17f6 --- /dev/null +++ b/user/src/bin/barrier_fail.rs @@ -0,0 +1,33 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate user_lib; +extern crate alloc; + +use user_lib::{thread_create, exit, waittid}; +use alloc::vec::Vec; + +const THREAD_NUM: usize = 3; + +fn thread_fn() { + for ch in 'a'..='c' { + for _ in 0..300 { + print!("{}", ch); + } + } + exit(0) +} + +#[no_mangle] +pub fn main() -> i32 { + let mut v: Vec = Vec::new(); + for _ in 0..THREAD_NUM { + v.push(thread_create(thread_fn as usize, 0)); + } + for tid in v.into_iter() { + waittid(tid as usize); + } + println!("\nOK!"); + 0 +} diff --git a/user/src/bin/usertests.rs b/user/src/bin/usertests.rs index a631314f0..9ee034067 100644 --- a/user/src/bin/usertests.rs +++ b/user/src/bin/usertests.rs @@ -40,6 +40,8 @@ static SUCC_TESTS: &[(&str, &str, &str, &str, i32)] = &[ ("threads_arg\0", "\0", "\0", "\0", 0), ("threads\0", "\0", "\0", "\0", 0), ("yield\0", "\0", "\0", "\0", 0), + ("barrier_fail\0", "\0", "\0", "\0", 0), + ("barrier_condvar\0", "\0", "\0", "\0", 0), ]; static FAIL_TESTS: &[(&str, &str, &str, &str, i32)] = &[