123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- use sbi_spec::binary::HartMask;
- use std::{
- sync::Mutex,
- thread::{self, JoinHandle},
- time::Duration,
- };
- const N_THREADS: usize = 8;
- static THREADS: [Mutex<Option<JoinHandle<()>>>; N_THREADS] =
- [const { Mutex::new(None) }; N_THREADS];
- fn main() {
- emulation_init();
- primary_hart_main();
- emulation_finish();
- }
- fn primary_hart_main() {
- println!("Primary hart is starting");
-
-
-
- sbi::send_ipi(HartMask::all());
- println!("Primary hart finished");
- }
- fn secondary_hart_main(hart_id: u128) {
- println!("Secondary hart {} is waiting for interrupt", hart_id);
-
-
- wfi();
-
- println!("Secondary hart {} received interrupt", hart_id);
- }
- mod sbi {
- use super::{N_THREADS, unpark_thread};
- use sbi_spec::binary::{HartMask, SbiRet};
-
- pub fn send_ipi(hart_mask: HartMask<u128>) -> SbiRet<u128> {
- let (mask, base) = hart_mask.into_inner();
-
- if hart_mask == HartMask::all() {
- for hart_id in 0..N_THREADS as u128 {
- unpark_thread(hart_id);
- }
- return SbiRet::success(0);
- }
-
- for bit_offset in 0..128 {
- if (mask & (1 << bit_offset)) != 0 {
- let hart_id = base + bit_offset;
- println!("Hart id {}", hart_id);
- if hart_id < N_THREADS as u128 {
- unpark_thread(hart_id);
- }
- }
- }
- SbiRet::success(0)
- }
- }
- fn emulation_init() {
- println!("Emulation start");
-
- for i in 0..N_THREADS {
- *THREADS[i].lock().unwrap() = Some(thread::spawn(move || secondary_hart_main(i as u128)));
- }
-
- thread::sleep(Duration::from_micros(10));
- }
- fn wfi() {
- thread::park();
- }
- fn emulation_finish() {
-
- thread::sleep(Duration::from_micros(10));
-
- for (i, thread) in THREADS.iter().enumerate() {
- if let Some(thread) = thread.lock().unwrap().take() {
- println!("Hart {} stopped", i);
- thread.join().unwrap();
- }
- }
- println!("All harts stopped, emulation finished");
- }
- fn unpark_thread(id: u128) {
- assert!(id < N_THREADS as u128, "Invalid hart ID");
-
- if let Some(thread) = &*THREADS[id as usize].lock().unwrap() {
- thread.thread().unpark();
- }
- }
|