From 3da5c218137abd2d6e107fd858a86ff43fd1dfa2 Mon Sep 17 00:00:00 2001 From: Corwin Date: Sun, 22 Sep 2024 16:22:08 +0100 Subject: [PATCH] use SyncUnsafeCell rather than static muts --- agb/src/interrupt.rs | 16 ++++++++-------- agb/src/lib.rs | 8 +++++--- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/agb/src/interrupt.rs b/agb/src/interrupt.rs index 34b8324a..64fd66d4 100644 --- a/agb/src/interrupt.rs +++ b/agb/src/interrupt.rs @@ -4,7 +4,7 @@ use alloc::boxed::Box; use critical_section::{CriticalSection, RawRestoreState}; use portable_atomic::{AtomicBool, AtomicUsize, Ordering}; -use crate::{display::DISPLAY_STATUS, memory_mapped::MemoryMapped}; +use crate::{display::DISPLAY_STATUS, memory_mapped::MemoryMapped, util::SyncUnsafeCell}; #[derive(Clone, Copy)] pub enum Interrupt { @@ -123,7 +123,7 @@ impl InterruptRoot { } } -static mut INTERRUPT_TABLE: [InterruptRoot; 14] = [ +static INTERRUPT_TABLE: SyncUnsafeCell<[InterruptRoot; 14]> = SyncUnsafeCell::new([ InterruptRoot::new(Interrupt::VBlank), InterruptRoot::new(Interrupt::HBlank), InterruptRoot::new(Interrupt::VCounter), @@ -138,12 +138,12 @@ static mut INTERRUPT_TABLE: [InterruptRoot; 14] = [ InterruptRoot::new(Interrupt::Dma3), InterruptRoot::new(Interrupt::Keypad), InterruptRoot::new(Interrupt::Gamepak), -]; +]); #[no_mangle] #[export_name = "__RUST_INTERRUPT_HANDLER"] extern "C" fn interrupt_handler(interrupt: u16) -> u16 { - for (i, root) in unsafe { INTERRUPT_TABLE.iter().enumerate() } { + for (i, root) in unsafe { &mut *INTERRUPT_TABLE.get() }.iter().enumerate() { if (1 << i) & interrupt != 0 { root.trigger_interrupts(); } @@ -220,8 +220,8 @@ impl InterruptRoot { } } -fn interrupt_to_root(interrupt: Interrupt) -> &'static InterruptRoot { - unsafe { &INTERRUPT_TABLE[interrupt as usize] } +unsafe fn interrupt_to_root(interrupt: Interrupt) -> &'static InterruptRoot { + &(unsafe { &mut *INTERRUPT_TABLE.get() })[interrupt as usize] } #[must_use] @@ -260,7 +260,7 @@ pub unsafe fn add_interrupt_handler( ) -> InterruptHandler { fn do_with_inner(interrupt: Interrupt, inner: Pin>) -> InterruptHandler { critical_section::with(|_| { - let root = interrupt_to_root(interrupt); + let root = unsafe { interrupt_to_root(interrupt) }; root.add(); let mut c = root.next.get(); if c.is_null() { @@ -374,7 +374,7 @@ mod tests { #[test_case] fn test_interrupt_table_length(_gba: &mut crate::Gba) { assert_eq!( - unsafe { INTERRUPT_TABLE.len() }, + unsafe { (*INTERRUPT_TABLE.get()).len() }, Interrupt::Gamepak as usize + 1, "interrupt table should be able to store gamepak interrupt" ); diff --git a/agb/src/lib.rs b/agb/src/lib.rs index 3b4af52f..b657221f 100644 --- a/agb/src/lib.rs +++ b/agb/src/lib.rs @@ -327,6 +327,8 @@ impl Gba { /// You can run the tests using `cargo test`, but it will work better through `mgba-test-runner` by /// running something along the lines of `CARGO_TARGET_THUMBV4T_NONE_EABI_RUNNER=mgba-test-runner cargo test`. pub mod test_runner { + use util::SyncUnsafeCell; + use super::*; #[doc(hidden)] @@ -374,7 +376,7 @@ pub mod test_runner { } } - static mut TEST_GBA: Option = None; + static TEST_GBA: SyncUnsafeCell> = SyncUnsafeCell::new(None); #[doc(hidden)] pub fn test_runner(tests: &[&dyn Testable]) { @@ -385,7 +387,7 @@ pub mod test_runner { ) .unwrap(); - let gba = unsafe { TEST_GBA.as_mut() }.unwrap(); + let gba = unsafe { &mut *TEST_GBA.get() }.as_mut().unwrap(); for test in tests { test.run(gba); @@ -415,7 +417,7 @@ pub mod test_runner { #[doc(hidden)] pub fn agb_start_tests(gba: Gba, test_main: impl Fn()) -> ! { - unsafe { TEST_GBA = Some(gba) }; + *unsafe { &mut *TEST_GBA.get() } = Some(gba); test_main(); #[allow(clippy::empty_loop)] loop {}