#![no_std]
#![no_main]
#[macro_use]
extern crate user_lib;
extern crate alloc;
use user_lib::{
enable_deadlock_detect, exit, semaphore_create, semaphore_down, semaphore_up, sleep,
thread_create, waittid,
};
const THREAD_N: usize = 4;
const RES_TYPE: usize = 2;
const RES_NUM: [usize; RES_TYPE] = [2, 2];
const ALLOC: [usize; THREAD_N] = [2, 1, 1, 2];
const REQUEST: [Option<usize>; THREAD_N] = [Some(1), None, Some(2), None];
fn try_sem_down(sem_id: usize, thread_idx: usize) {
if semaphore_down(sem_id) == -0xdead {
semaphore_up(ALLOC[thread_idx]);
exit(-1);
}
}
fn deadlock_test(arg: usize) {
let id = arg; assert_eq!(semaphore_down(ALLOC[id]), 0);
semaphore_down(0);
if let Some(sem_id) = REQUEST[id] {
try_sem_down(sem_id, id);
semaphore_up(sem_id);
}
semaphore_up(ALLOC[id]);
exit(0);
}
#[unsafe(no_mangle)]
extern "C" fn main() -> i32 {
enable_deadlock_detect(true);
semaphore_create(THREAD_N);
for _ in 0..THREAD_N {
semaphore_down(0);
}
for n in RES_NUM {
semaphore_create(n);
}
let mut tids = [0usize; THREAD_N];
for i in 0..THREAD_N {
tids[i] = thread_create(deadlock_test as *const () as usize, i) as usize;
}
sleep(1000);
for _ in 0..THREAD_N {
semaphore_up(0);
}
let mut failed = 0;
for tid in tids {
if waittid(tid) != 0 {
failed += 1;
}
}
assert_eq!(failed, 0);
println!("deadlock test semaphore 2 OK!");
0
}