mirror of
https://github.com/rcore-os/rCore-Tutorial-v3.git
synced 2024-11-23 09:56:24 +04:00
Add adder_* tests.
This commit is contained in:
parent
82b40b6f3d
commit
0fffe23705
@ -12,15 +12,19 @@ static mut A: usize = 0;
|
||||
const PER_THREAD: usize = 10000;
|
||||
const THREAD_COUNT: usize = 16;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
unsafe fn f() -> ! {
|
||||
let mut t = 2usize;
|
||||
for _ in 0..PER_THREAD {
|
||||
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);
|
||||
critical_section(&mut t);
|
||||
}
|
||||
exit(t as i32)
|
||||
}
|
72
user/src/bin/adder_atomic.rs
Normal file
72
user/src/bin/adder_atomic.rs
Normal file
@ -0,0 +1,72 @@
|
||||
#![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
|
||||
}
|
69
user/src/bin/adder_loop.rs
Normal file
69
user/src/bin/adder_loop.rs
Normal file
@ -0,0 +1,69 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
#[macro_use]
|
||||
extern crate user_lib;
|
||||
extern crate alloc;
|
||||
|
||||
use alloc::vec::Vec;
|
||||
use user_lib::{exit, get_time, thread_create, waittid, yield_};
|
||||
|
||||
static mut A: usize = 0;
|
||||
static mut OCCUPIED: bool = 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);
|
||||
}
|
||||
|
||||
unsafe fn lock() {
|
||||
while OCCUPIED {
|
||||
yield_();
|
||||
}
|
||||
OCCUPIED = true;
|
||||
}
|
||||
|
||||
unsafe fn unlock() {
|
||||
OCCUPIED = false;
|
||||
}
|
||||
|
||||
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
|
||||
}
|
59
user/src/bin/adder_mutex_blocking.rs
Normal file
59
user/src/bin/adder_mutex_blocking.rs
Normal file
@ -0,0 +1,59 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
#[macro_use]
|
||||
extern crate user_lib;
|
||||
extern crate alloc;
|
||||
|
||||
use alloc::vec::Vec;
|
||||
use user_lib::{exit, get_time, thread_create, waittid};
|
||||
use user_lib::{mutex_blocking_create, mutex_lock, mutex_unlock};
|
||||
|
||||
static mut A: usize = 0;
|
||||
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);
|
||||
}
|
||||
unsafe fn f() -> ! {
|
||||
let mut t = 2usize;
|
||||
for _ in 0..PER_THREAD {
|
||||
mutex_lock(0);
|
||||
critical_section(&mut t);
|
||||
mutex_unlock(0);
|
||||
}
|
||||
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();
|
||||
assert_eq!(mutex_blocking_create(), 0);
|
||||
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
|
||||
}
|
60
user/src/bin/adder_mutex_spin.rs
Normal file
60
user/src/bin/adder_mutex_spin.rs
Normal file
@ -0,0 +1,60 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
#[macro_use]
|
||||
extern crate user_lib;
|
||||
extern crate alloc;
|
||||
|
||||
use alloc::vec::Vec;
|
||||
use user_lib::{exit, get_time, thread_create, waittid};
|
||||
use user_lib::{mutex_create, mutex_lock, mutex_unlock};
|
||||
|
||||
static mut A: usize = 0;
|
||||
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);
|
||||
}
|
||||
|
||||
unsafe fn f() -> ! {
|
||||
let mut t = 2usize;
|
||||
for _ in 0..PER_THREAD {
|
||||
mutex_lock(0);
|
||||
critical_section(&mut t);
|
||||
mutex_unlock(0);
|
||||
}
|
||||
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();
|
||||
assert_eq!(mutex_create(), 0);
|
||||
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
|
||||
}
|
89
user/src/bin/adder_peterson_spin.rs
Normal file
89
user/src/bin/adder_peterson_spin.rs
Normal file
@ -0,0 +1,89 @@
|
||||
//! It only works on a single CPU!
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(core_intrinsics)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate user_lib;
|
||||
extern crate alloc;
|
||||
|
||||
use alloc::vec::Vec;
|
||||
use user_lib::{exit, get_time, thread_create, waittid};
|
||||
use core::sync::atomic::{compiler_fence, Ordering};
|
||||
|
||||
static mut A: usize = 0;
|
||||
static mut FLAG: [bool; 2] = [false; 2];
|
||||
static mut TURN: usize = 0;
|
||||
const PER_THREAD_DEFAULT: usize = 2000;
|
||||
const THREAD_COUNT_DEFAULT: usize = 2;
|
||||
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);
|
||||
}
|
||||
|
||||
unsafe fn lock(id: usize) {
|
||||
FLAG[id] = true;
|
||||
TURN = 1 - id;
|
||||
// Tell the compiler not to reorder memory operations
|
||||
// across this fence.
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
// Why do we need to use volatile_read here?
|
||||
// Otherwise the compiler will assume that they will never
|
||||
// be changed on this thread. Thus, they will be accessed
|
||||
// only once!
|
||||
while vload!(&FLAG[1 - id]) && vload!(&TURN) == 1 - id {}
|
||||
}
|
||||
|
||||
unsafe fn unlock(id: usize) {
|
||||
FLAG[id] = false;
|
||||
}
|
||||
|
||||
unsafe fn f(id: usize) -> ! {
|
||||
let mut t = 2usize;
|
||||
for _iter in 0..PER_THREAD {
|
||||
lock(id);
|
||||
critical_section(&mut t);
|
||||
unlock(id);
|
||||
}
|
||||
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; }
|
||||
|
||||
// uncomment this if you want to check the assembly
|
||||
// println!(
|
||||
// "addr: lock={:#x}, unlock={:#x}",
|
||||
// lock as usize,
|
||||
// unlock as usize
|
||||
// );
|
||||
let start = get_time();
|
||||
let mut v = Vec::new();
|
||||
assert_eq!(thread_count, 2, "Peterson works when there are only 2 threads.");
|
||||
for id in 0..thread_count {
|
||||
v.push(thread_create(f as usize, id) as usize);
|
||||
}
|
||||
let mut time_cost = Vec::new();
|
||||
for tid in v.iter() {
|
||||
time_cost.push(waittid(*tid));
|
||||
}
|
||||
println!("time cost is {}ms", get_time() - start);
|
||||
assert_eq!(unsafe { A }, unsafe { PER_THREAD } * thread_count);
|
||||
0
|
||||
}
|
88
user/src/bin/adder_peterson_yield.rs
Normal file
88
user/src/bin/adder_peterson_yield.rs
Normal file
@ -0,0 +1,88 @@
|
||||
//! It only works on a single CPU!
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(core_intrinsics)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate user_lib;
|
||||
extern crate alloc;
|
||||
|
||||
use alloc::vec::Vec;
|
||||
use user_lib::{exit, get_time, thread_create, waittid, yield_};
|
||||
use core::sync::atomic::{compiler_fence, Ordering};
|
||||
|
||||
static mut A: usize = 0;
|
||||
static mut FLAG: [bool; 2] = [false; 2];
|
||||
static mut TURN: usize = 0;
|
||||
const PER_THREAD_DEFAULT: usize = 2000;
|
||||
const THREAD_COUNT_DEFAULT: usize = 2;
|
||||
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);
|
||||
}
|
||||
|
||||
unsafe fn lock(id: usize) {
|
||||
FLAG[id] = true;
|
||||
TURN = 1 - id;
|
||||
// Tell the compiler not to reorder memory operations
|
||||
// across this fence.
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
while FLAG[1 - id] && TURN == 1 - id {
|
||||
yield_();
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn unlock(id: usize) {
|
||||
FLAG[id] = false;
|
||||
}
|
||||
|
||||
unsafe fn f(id: usize) -> ! {
|
||||
let mut t = 2usize;
|
||||
for _iter in 0..PER_THREAD {
|
||||
lock(id);
|
||||
critical_section(&mut t);
|
||||
unlock(id);
|
||||
}
|
||||
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; }
|
||||
|
||||
// uncomment this if you want to check the assembly
|
||||
// println!(
|
||||
// "addr: lock={:#x}, unlock={:#x}",
|
||||
// lock as usize,
|
||||
// unlock as usize
|
||||
// );
|
||||
|
||||
let start = get_time();
|
||||
let mut v = Vec::new();
|
||||
assert_eq!(thread_count, 2, "Peterson works when there are only 2 threads.");
|
||||
for id in 0..thread_count {
|
||||
v.push(thread_create(f as usize, id) as usize);
|
||||
}
|
||||
let mut time_cost = Vec::new();
|
||||
for tid in v.iter() {
|
||||
time_cost.push(waittid(*tid));
|
||||
}
|
||||
println!("time cost is {}ms", get_time() - start);
|
||||
assert_eq!(unsafe { A }, unsafe { PER_THREAD } * thread_count);
|
||||
0
|
||||
}
|
@ -10,7 +10,7 @@ extern crate core;
|
||||
use alloc::vec::Vec;
|
||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||
use user_lib::{exit, sleep, thread_create, waittid};
|
||||
const N: usize = 3;
|
||||
const N: usize = 1000;
|
||||
|
||||
static mut TURN: usize = 0;
|
||||
static mut FLAG: [bool; 2] = [false; 2];
|
||||
@ -29,27 +29,30 @@ fn critical_test_exit() {
|
||||
}
|
||||
|
||||
fn peterson_enter_critical(id: usize, peer_id: usize) {
|
||||
println!("Thread[{}] try enter", id);
|
||||
// println!("Thread[{}] try enter", id);
|
||||
vstore!(&FLAG[id], true);
|
||||
vstore!(&TURN, peer_id);
|
||||
memory_fence!();
|
||||
while vload!(&FLAG[peer_id]) && vload!(&TURN) == peer_id {
|
||||
println!("Thread[{}] enter fail", id);
|
||||
// println!("Thread[{}] enter fail", id);
|
||||
sleep(1);
|
||||
println!("Thread[{}] retry enter", id);
|
||||
// println!("Thread[{}] retry enter", id);
|
||||
}
|
||||
println!("Thread[{}] enter", id);
|
||||
// println!("Thread[{}] enter", id);
|
||||
}
|
||||
|
||||
fn peterson_exit_critical(id: usize) {
|
||||
vstore!(&FLAG[id], false);
|
||||
println!("Thread[{}] exit", id);
|
||||
// println!("Thread[{}] exit", id);
|
||||
}
|
||||
|
||||
pub fn thread_fn(id: usize) -> ! {
|
||||
println!("Thread[{}] init.", id);
|
||||
// println!("Thread[{}] init.", id);
|
||||
let peer_id: usize = id ^ 1;
|
||||
for _ in 0..N {
|
||||
for iter in 0..N {
|
||||
if iter % 10 == 0 {
|
||||
println!("[{}] it={}", id, iter);
|
||||
}
|
||||
peterson_enter_critical(id, peer_id);
|
||||
critical_test_enter();
|
||||
for _ in 0..3 {
|
||||
@ -74,4 +77,4 @@ pub fn main() -> i32 {
|
||||
}
|
||||
println!("main thread exited.");
|
||||
0
|
||||
}
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
#[macro_use]
|
||||
extern crate user_lib;
|
||||
extern crate alloc;
|
||||
|
||||
use crate::alloc::string::ToString;
|
||||
use alloc::vec::Vec;
|
||||
use user_lib::{exit, get_time, thread_create, waittid};
|
||||
|
||||
static mut A: usize = 0;
|
||||
const PER_THREAD: usize = 10000;
|
||||
const THREAD_COUNT: usize = 16;
|
||||
|
||||
unsafe fn f() -> ! {
|
||||
let mut t = 2usize;
|
||||
for _ in 0..PER_THREAD {
|
||||
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);
|
||||
}
|
||||
exit(t as i32)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn main(argc: usize, argv: &[&str]) -> i32 {
|
||||
let mut thread_count = THREAD_COUNT;
|
||||
if argc == 2 {
|
||||
thread_count = argv[1].to_string().parse::<usize>().unwrap();
|
||||
} else if argc != 1 {
|
||||
println!("ERROR in argv");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
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 }, PER_THREAD * thread_count);
|
||||
0
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
#![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: usize = 10000;
|
||||
const THREAD_COUNT: usize = 16;
|
||||
|
||||
unsafe fn f() -> ! {
|
||||
let mut t = 2usize;
|
||||
for _ in 0..PER_THREAD {
|
||||
while OCCUPIED
|
||||
.compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed)
|
||||
.is_err()
|
||||
{
|
||||
yield_();
|
||||
}
|
||||
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);
|
||||
OCCUPIED.store(false, Ordering::Relaxed);
|
||||
}
|
||||
exit(t as i32)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn main() -> i32 {
|
||||
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 }, PER_THREAD * THREAD_COUNT);
|
||||
0
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
#[macro_use]
|
||||
extern crate user_lib;
|
||||
extern crate alloc;
|
||||
|
||||
use alloc::vec::Vec;
|
||||
use user_lib::{exit, get_time, thread_create, waittid, yield_};
|
||||
|
||||
static mut A: usize = 0;
|
||||
static mut OCCUPIED: bool = false;
|
||||
const PER_THREAD: usize = 10000;
|
||||
const THREAD_COUNT: usize = 16;
|
||||
|
||||
unsafe fn f() -> ! {
|
||||
let mut t = 2usize;
|
||||
for _ in 0..PER_THREAD {
|
||||
while OCCUPIED {
|
||||
yield_();
|
||||
}
|
||||
OCCUPIED = true;
|
||||
// enter critical section
|
||||
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);
|
||||
// exit critical section
|
||||
OCCUPIED = false;
|
||||
}
|
||||
|
||||
exit(t as i32)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn main() -> i32 {
|
||||
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 }, PER_THREAD * THREAD_COUNT);
|
||||
0
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
#[macro_use]
|
||||
extern crate user_lib;
|
||||
extern crate alloc;
|
||||
|
||||
use alloc::vec::Vec;
|
||||
use user_lib::{exit, get_time, thread_create, waittid};
|
||||
use user_lib::{mutex_blocking_create, mutex_lock, mutex_unlock};
|
||||
|
||||
static mut A: usize = 0;
|
||||
const PER_THREAD: usize = 10000;
|
||||
const THREAD_COUNT: usize = 16;
|
||||
|
||||
unsafe fn f() -> ! {
|
||||
let mut t = 2usize;
|
||||
for _ in 0..PER_THREAD {
|
||||
mutex_lock(0);
|
||||
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);
|
||||
mutex_unlock(0);
|
||||
}
|
||||
exit(t as i32)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn main() -> i32 {
|
||||
let start = get_time();
|
||||
assert_eq!(mutex_blocking_create(), 0);
|
||||
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 }, PER_THREAD * THREAD_COUNT);
|
||||
0
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
#[macro_use]
|
||||
extern crate user_lib;
|
||||
extern crate alloc;
|
||||
|
||||
use alloc::vec::Vec;
|
||||
use user_lib::{exit, get_time, thread_create, waittid};
|
||||
use user_lib::{mutex_create, mutex_lock, mutex_unlock};
|
||||
|
||||
static mut A: usize = 0;
|
||||
const PER_THREAD: usize = 10000;
|
||||
const THREAD_COUNT: usize = 16;
|
||||
|
||||
unsafe fn f() -> ! {
|
||||
let mut t = 2usize;
|
||||
for _ in 0..PER_THREAD {
|
||||
mutex_lock(0);
|
||||
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);
|
||||
mutex_unlock(0);
|
||||
}
|
||||
exit(t as i32)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn main() -> i32 {
|
||||
let start = get_time();
|
||||
assert_eq!(mutex_create(), 0);
|
||||
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 }, PER_THREAD * THREAD_COUNT);
|
||||
0
|
||||
}
|
Loading…
Reference in New Issue
Block a user