72 lines
1.7 KiB
Rust
72 lines
1.7 KiB
Rust
#![no_std]
|
|
#![no_main]
|
|
|
|
#[macro_use]
|
|
extern crate user_lib;
|
|
extern crate alloc;
|
|
|
|
use alloc::vec::Vec;
|
|
use core::sync::atomic::{AtomicBool, Ordering};
|
|
use user_lib::{exit, get_time, thread_create, waittid, yield_};
|
|
|
|
static mut A: usize = 0;
|
|
static OCCUPIED: AtomicBool = AtomicBool::new(false);
|
|
const PER_THREAD_DEFAULT: usize = 10000;
|
|
const THREAD_COUNT_DEFAULT: usize = 16;
|
|
static mut PER_THREAD: usize = 0;
|
|
|
|
unsafe fn critical_section(t: &mut usize) {
|
|
let a = &mut A as *mut usize;
|
|
let cur = a.read_volatile();
|
|
for _ in 0..500 {
|
|
*t = (*t) * (*t) % 10007;
|
|
}
|
|
a.write_volatile(cur + 1);
|
|
}
|
|
|
|
fn lock() {
|
|
while OCCUPIED
|
|
.compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed)
|
|
.is_err()
|
|
{
|
|
yield_();
|
|
}
|
|
}
|
|
|
|
fn unlock() {
|
|
OCCUPIED.store(false, Ordering::Relaxed);
|
|
}
|
|
|
|
unsafe fn f() -> ! {
|
|
let mut t = 2usize;
|
|
for _ in 0..PER_THREAD {
|
|
lock();
|
|
critical_section(&mut t);
|
|
unlock();
|
|
}
|
|
exit(t as i32)
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub fn main(argc: usize, argv: &[&str]) -> i32 {
|
|
let mut thread_count = THREAD_COUNT_DEFAULT;
|
|
let mut per_thread = PER_THREAD_DEFAULT;
|
|
if argc >= 2 {
|
|
thread_count = argv[1].parse().unwrap();
|
|
if argc >= 3 {
|
|
per_thread = argv[2].parse().unwrap();
|
|
}
|
|
}
|
|
unsafe { PER_THREAD = per_thread; }
|
|
let start = get_time();
|
|
let mut v = Vec::new();
|
|
for _ in 0..thread_count {
|
|
v.push(thread_create(f as usize, 0) as usize);
|
|
}
|
|
for tid in v.into_iter() {
|
|
waittid(tid);
|
|
}
|
|
println!("time cost is {}ms", get_time() - start);
|
|
assert_eq!(unsafe { A }, unsafe { PER_THREAD } * thread_count);
|
|
0
|
|
}
|