#![no_std] #![no_main] #[macro_use] extern crate user_lib; extern crate alloc; use alloc::vec::Vec; use core::cell::UnsafeCell; use lazy_static::*; use user_lib::{ condvar_create, condvar_signal, condvar_wait, exit, mutex_create, mutex_lock, mutex_unlock, thread_create, waittid, }; 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 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 }