#![feature(test)]
#![feature(thread_local)]
#![no_std]
#![no_main]
#![test_runner(common::test_case_runner)]
#![feature(custom_test_frameworks)]
#![reexport_test_harness_main = "test_main"]
extern crate hermit;
use core::ptr;
use core::sync::atomic::AtomicU32;
use core::sync::atomic::Ordering::Relaxed;
use common::*;
mod common;
use alloc::vec;
use hermit::errno::{EAGAIN, ETIMEDOUT};
use hermit::{sys_futex_wait, sys_futex_wake, sys_join, sys_spawn2, sys_usleep, timespec};
const USER_STACK_SIZE: usize = 1_048_576;
const NORMAL_PRIO: u8 = 2;
extern "C" fn thread_func(i: usize) {
println!("this is thread number {}", i);
sys_usleep(2000000);
println!("---------------THREAD DONE!---------- {}", i);
}
#[test_case]
pub fn thread_test() {
let mut children = vec![];
let threadnum = 5;
for i in 0..threadnum {
println!("SPAWNING THREAD {}", i);
let id = sys_spawn2(thread_func, i, NORMAL_PRIO, USER_STACK_SIZE, -1);
children.push(id);
}
println!("SPAWNED THREADS");
for child in children {
sys_join(child);
}
}
extern "C" fn waker_func(futex: usize) {
let futex = unsafe { &*(futex as *const AtomicU32) };
sys_usleep(100_000);
futex.store(1, Relaxed);
let ret = sys_futex_wake(futex as *const AtomicU32 as *mut u32, i32::MAX);
assert_eq!(ret, 1);
}
#[test_case]
pub fn test_futex() {
let futex = AtomicU32::new(0);
let futex_ptr = &futex as *const AtomicU32 as *mut u32;
let ret = sys_futex_wait(futex_ptr, 1, ptr::null(), 0);
assert_eq!(ret, -EAGAIN);
let timeout = timespec {
tv_sec: 0,
tv_nsec: 100_000_000,
};
let ret = sys_futex_wait(futex_ptr, 0, &timeout, 1);
assert_eq!(ret, -ETIMEDOUT);
let waker = sys_spawn2(
waker_func,
futex_ptr as usize,
NORMAL_PRIO,
USER_STACK_SIZE,
-1,
);
assert!(waker >= 0);
let ret = sys_futex_wait(futex_ptr, 0, ptr::null(), 0);
assert_eq!(ret, 0);
assert_eq!(futex.load(Relaxed), 1);
let ret = sys_join(waker);
assert_eq!(ret, 0);
}
#[test_case]
pub fn test_thread_local() {
#[repr(C, align(0x10))]
struct AlignedByte(u8);
#[thread_local]
static mut BYTE: u8 = 0x42;
#[thread_local]
static mut CAFECAFE: u64 = 0xCAFECAFE;
#[thread_local]
static mut DEADBEEF: u64 = 0xDEADBEEF;
#[thread_local]
static mut ALIGNED_BYTE: AlignedByte = AlignedByte(0x53);
unsafe {
assert_eq!(0x42, BYTE);
assert_eq!(0xCAFECAFE, CAFECAFE);
assert_eq!(0xDEADBEEF, DEADBEEF);
assert_eq!(0x53, ALIGNED_BYTE.0);
}
}
#[no_mangle]
extern "C" fn runtime_entry(_argc: i32, _argv: *const *const u8, _env: *const *const u8) -> ! {
test_main();
common::exit(false)
}