updates from ch8

This commit is contained in:
Yifan Wu 2023-01-13 09:59:46 +08:00
parent 3183b81f87
commit fe2f776fe8
15 changed files with 582 additions and 251 deletions

55
user/src/bin/adder.rs Normal file
View file

@ -0,0 +1,55 @@
#![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};
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 {
critical_section(&mut t);
}
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
}

View 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
}

View 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
}

View 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
}

View file

@ -0,0 +1,90 @@
//! 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;
let j = 1 - id;
TURN = j;
// 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[j]) && vload!(&TURN) == j {}
}
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
}

View 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, 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;
let j = 1 - id;
TURN = j;
// Tell the compiler not to reorder memory operations
// across this fence.
compiler_fence(Ordering::SeqCst);
while FLAG[j] && TURN == j {
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
}

View file

@ -0,0 +1,68 @@
#![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};
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 vload!(&OCCUPIED) {}
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
}

View file

@ -0,0 +1,70 @@
#![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_};
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
}

View file

@ -10,7 +10,7 @@ extern crate core;
use alloc::vec::Vec; use alloc::vec::Vec;
use core::sync::atomic::{AtomicUsize, Ordering}; use core::sync::atomic::{AtomicUsize, Ordering};
use user_lib::{exit, sleep, thread_create, waittid}; use user_lib::{exit, sleep, thread_create, waittid};
const N: usize = 3; const N: usize = 1000;
static mut TURN: usize = 0; static mut TURN: usize = 0;
static mut FLAG: [bool; 2] = [false; 2]; static mut FLAG: [bool; 2] = [false; 2];
@ -29,27 +29,30 @@ fn critical_test_exit() {
} }
fn peterson_enter_critical(id: usize, peer_id: usize) { fn peterson_enter_critical(id: usize, peer_id: usize) {
println!("Thread[{}] try enter", id); // println!("Thread[{}] try enter", id);
vstore!(&FLAG[id], true); vstore!(&FLAG[id], true);
vstore!(&TURN, peer_id); vstore!(&TURN, peer_id);
memory_fence!(); memory_fence!();
while vload!(&FLAG[peer_id]) && vload!(&TURN) == peer_id { while vload!(&FLAG[peer_id]) && vload!(&TURN) == peer_id {
println!("Thread[{}] enter fail", id); // println!("Thread[{}] enter fail", id);
sleep(1); 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) { fn peterson_exit_critical(id: usize) {
vstore!(&FLAG[id], false); vstore!(&FLAG[id], false);
println!("Thread[{}] exit", id); // println!("Thread[{}] exit", id);
} }
pub fn thread_fn(id: usize) -> ! { pub fn thread_fn(id: usize) -> ! {
println!("Thread[{}] init.", id); // println!("Thread[{}] init.", id);
let peer_id: usize = id ^ 1; 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); peterson_enter_critical(id, peer_id);
critical_test_enter(); critical_test_enter();
for _ in 0..3 { for _ in 0..3 {
@ -74,4 +77,4 @@ pub fn main() -> i32 {
} }
println!("main thread exited."); println!("main thread exited.");
0 0
} }

View file

@ -1,42 +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};
static mut A: usize = 0;
const PER_THREAD: usize = 1000;
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() -> 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);
}
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 }, PER_THREAD * THREAD_COUNT);
0
}

View file

@ -1,51 +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 = 1000;
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);
}
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 }, PER_THREAD * THREAD_COUNT);
0
}

View file

@ -1,51 +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 = 1000;
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);
}
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 }, PER_THREAD * THREAD_COUNT);
0
}

View file

@ -1,46 +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 = 1000;
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);
}
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 }, PER_THREAD * THREAD_COUNT);
0
}

View file

@ -1,46 +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 = 1000;
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);
}
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 }, PER_THREAD * THREAD_COUNT);
0
}

View file

@ -27,10 +27,10 @@ static SUCC_TESTS: &[(&str, &str, &str, &str, i32)] = &[
("phil_din_mutex\0", "\0", "\0", "\0", 0), ("phil_din_mutex\0", "\0", "\0", "\0", 0),
("pipe_large_test\0", "\0", "\0", "\0", 0), ("pipe_large_test\0", "\0", "\0", "\0", 0),
("pipetest\0", "\0", "\0", "\0", 0), ("pipetest\0", "\0", "\0", "\0", 0),
("race_adder_arg\0", "3\0", "\0", "\0", 0), ("adder_peterson_spin\0", "\0", "\0", "\0", 0),
("race_adder_atomic\0", "\0", "\0", "\0", 0), ("adder_peterson_yield\0", "\0", "\0", "\0", 0),
("race_adder_mutex_blocking\0", "\0", "\0", "\0", 0), ("adder_mutex_blocking\0", "\0", "\0", "\0", 0),
("race_adder_mutex_spin\0", "\0", "\0", "\0", 0), ("adder_mutex_spin\0", "\0", "\0", "\0", 0),
("run_pipe_test\0", "\0", "\0", "\0", 0), ("run_pipe_test\0", "\0", "\0", "\0", 0),
("sleep_simple\0", "\0", "\0", "\0", 0), ("sleep_simple\0", "\0", "\0", "\0", 0),
("sleep\0", "\0", "\0", "\0", 0), ("sleep\0", "\0", "\0", "\0", 0),
@ -49,8 +49,9 @@ static FAIL_TESTS: &[(&str, &str, &str, &str, i32)] = &[
("priv_inst\0", "\0", "\0", "\0", -4), ("priv_inst\0", "\0", "\0", "\0", -4),
("store_fault\0", "\0", "\0", "\0", -11), ("store_fault\0", "\0", "\0", "\0", -11),
("until_timeout\0", "\0", "\0", "\0", -6), ("until_timeout\0", "\0", "\0", "\0", -6),
("race_adder\0", "\0", "\0", "\0", -6), ("adder\0", "\0", "\0", "\0", -6),
("huge_write_mt\0", "\0", "\0", "\0", -6), ("adder_simple_spin\0", "\0", "\0", "\0", -6),
("adder_simple_yield\0", "\0", "\0", "\0", -6),
]; ];
use user_lib::{exec, fork, waitpid}; use user_lib::{exec, fork, waitpid};