//! Spinner half of init's SMP self-test: one thread per hart, each //! incrementing its own counter in the page given in slot 0. #![no_std] #![no_main] #![forbid(unsafe_code)] extern crate libkos; use core::sync::atomic::{AtomicUsize, Ordering}; use libkos::syscall; use types::address::VirtualAddress; use types::bounded::CapSlot; use types::mapping::PagePerms; /// Counter page layout (words): 0 next free counter index, 1..=THREADS counters. const COUNTERS_VA: VirtualAddress = VirtualAddress::from_raw(0x0100_0000); const THREADS: usize = 4; fn main() { let page = CapSlot::const_new(0); let Ok(window) = libkos::window::map(page, COUNTERS_VA, PagePerms::ReadWrite) else { libkos::println!("smptest: cannot map the counter page"); syscall::exit(); }; let words = window.atomics(types::address::ByteOffset::ZERO, 1 + THREADS); for _ in 1..THREADS { if !libkos::thread::spawn(words, spin) { break; } } spin(words); } libkos::entry!(main); fn spin(word: &'static [AtomicUsize]) -> ! { let mine = 1 + word[0].fetch_add(1, Ordering::Relaxed) % THREADS; loop { // Yield so a spinner sharing init's hart cannot starve it. for _ in 0..1024 { word[mine].fetch_add(1, Ordering::Relaxed); } syscall::yield_now(); } }