@ -7,16 +7,18 @@ extern crate user_lib;
extern crate alloc ;
extern crate core ;
use user_lib ::{ thread_create , waittid , exit , sleep } ;
use alloc ::vec ::Vec ;
use core ::sync ::atomic ::{ AtomicUsize , Ordering } ;
use user_lib ::{ exit , sleep , thread_create , waittid } ;
const N : usize = 2 ;
const THREAD_NUM : usize = 10 ;
#[ derive(Debug, Clone, Copy, PartialEq, Eq) ]
enum FlagState {
Out , Want , In ,
Out ,
Want ,
In ,
}
static mut TURN : usize = 0 ;
@ -25,7 +27,7 @@ static mut FLAG: [FlagState; THREAD_NUM] = [FlagState::Out; THREAD_NUM];
static GUARD : AtomicUsize = AtomicUsize ::new ( 0 ) ;
fn critical_test_enter ( ) {
assert_eq! ( GUARD . fetch_add ( 1 , Ordering ::SeqCst ) , 0 ) ;
assert_eq! ( GUARD . fetch_add ( 1 , Ordering ::SeqCst ) , 0 ) ;
}
fn critical_test_claim ( ) {
@ -33,7 +35,7 @@ fn critical_test_claim() {
}
fn critical_test_exit ( ) {
assert_eq! ( GUARD . fetch_sub ( 1 , Ordering ::SeqCst ) , 1 ) ;
assert_eq! ( GUARD . fetch_sub ( 1 , Ordering ::SeqCst ) , 1 ) ;
}
fn eisenberg_enter_critical ( id : usize ) {
@ -43,7 +45,7 @@ fn eisenberg_enter_critical(id: usize) {
vstore! ( & FLAG [ id ] , FlagState ::Want ) ;
loop {
/* check if any with higher priority is `Want` or `In` */
let mut prior_thread :Option < usize > = None ;
let mut prior_thread : Option < usize > = None ;
let turn = vload! ( & TURN ) ;
let ring_id = if id < turn { id + THREAD_NUM } else { id } ;
// FLAG.iter() may lead to some errors, use for-loop instead
@ -56,8 +58,11 @@ fn eisenberg_enter_critical(id: usize) {
if prior_thread . is_none ( ) {
break ;
}
println! ( " Thread[ {} ]: prior thread {} exist, sleep and retry " ,
id , prior_thread . unwrap ( ) ) ;
println! (
" Thread[{}]: prior thread {} exist, sleep and retry " ,
id ,
prior_thread . unwrap ( )
) ;
sleep ( 1 ) ;
}
/* now tentatively claim the resource */
@ -86,7 +91,7 @@ fn eisenberg_exit_critical(id: usize) {
/* find next one who wants to enter and give the turn to it */
let mut next = id ;
let ring_id = id + THREAD_NUM ;
for i in ( id + 1 ) .. ring_id {
for i in ( id + 1 ) .. ring_id {
let idx = i % THREAD_NUM ;
if vload! ( & FLAG [ idx ] ) = = FlagState ::Want {
next = idx ;
@ -119,7 +124,7 @@ pub fn main() -> i32 {
let mut v = Vec ::new ( ) ;
// TODO: really shuffle
assert_eq! ( THREAD_NUM , 10 ) ;
let shuffle :[ usize ; 10 ] = [ 0 , 7 , 4 , 6 , 2 , 9 , 8 , 1 , 3 , 5 ] ;
let shuffle : [ usize ; 10 ] = [ 0 , 7 , 4 , 6 , 2 , 9 , 8 , 1 , 3 , 5 ] ;
for i in 0 .. THREAD_NUM {
v . push ( thread_create ( thread_fn as usize , shuffle [ i ] ) ) ;
}
@ -130,4 +135,4 @@ pub fn main() -> i32 {
}
println! ( " main thread exited. " ) ;
0
}
}