mirror of
https://github.com/italicsjenga/agb.git
synced 2024-12-23 08:11:33 +11:00
Fix the CI issues with static mut access (#763)
- [x] no changelog update needed
This commit is contained in:
commit
1f6766e286
|
@ -4,7 +4,7 @@ use alloc::boxed::Box;
|
||||||
use critical_section::{CriticalSection, RawRestoreState};
|
use critical_section::{CriticalSection, RawRestoreState};
|
||||||
use portable_atomic::{AtomicBool, AtomicUsize, Ordering};
|
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)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum Interrupt {
|
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::VBlank),
|
||||||
InterruptRoot::new(Interrupt::HBlank),
|
InterruptRoot::new(Interrupt::HBlank),
|
||||||
InterruptRoot::new(Interrupt::VCounter),
|
InterruptRoot::new(Interrupt::VCounter),
|
||||||
|
@ -138,11 +138,12 @@ static mut INTERRUPT_TABLE: [InterruptRoot; 14] = [
|
||||||
InterruptRoot::new(Interrupt::Dma3),
|
InterruptRoot::new(Interrupt::Dma3),
|
||||||
InterruptRoot::new(Interrupt::Keypad),
|
InterruptRoot::new(Interrupt::Keypad),
|
||||||
InterruptRoot::new(Interrupt::Gamepak),
|
InterruptRoot::new(Interrupt::Gamepak),
|
||||||
];
|
]);
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
extern "C" fn __RUST_INTERRUPT_HANDLER(interrupt: u16) -> u16 {
|
#[export_name = "__RUST_INTERRUPT_HANDLER"]
|
||||||
for (i, root) in unsafe { INTERRUPT_TABLE.iter().enumerate() } {
|
extern "C" fn interrupt_handler(interrupt: u16) -> u16 {
|
||||||
|
for (i, root) in unsafe { &mut *INTERRUPT_TABLE.get() }.iter().enumerate() {
|
||||||
if (1 << i) & interrupt != 0 {
|
if (1 << i) & interrupt != 0 {
|
||||||
root.trigger_interrupts();
|
root.trigger_interrupts();
|
||||||
}
|
}
|
||||||
|
@ -219,8 +220,8 @@ impl InterruptRoot {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn interrupt_to_root(interrupt: Interrupt) -> &'static InterruptRoot {
|
unsafe fn interrupt_to_root(interrupt: Interrupt) -> &'static InterruptRoot {
|
||||||
unsafe { &INTERRUPT_TABLE[interrupt as usize] }
|
&(unsafe { &mut *INTERRUPT_TABLE.get() })[interrupt as usize]
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
|
@ -259,7 +260,7 @@ pub unsafe fn add_interrupt_handler(
|
||||||
) -> InterruptHandler {
|
) -> InterruptHandler {
|
||||||
fn do_with_inner(interrupt: Interrupt, inner: Pin<Box<InterruptInner>>) -> InterruptHandler {
|
fn do_with_inner(interrupt: Interrupt, inner: Pin<Box<InterruptInner>>) -> InterruptHandler {
|
||||||
critical_section::with(|_| {
|
critical_section::with(|_| {
|
||||||
let root = interrupt_to_root(interrupt);
|
let root = unsafe { interrupt_to_root(interrupt) };
|
||||||
root.add();
|
root.add();
|
||||||
let mut c = root.next.get();
|
let mut c = root.next.get();
|
||||||
if c.is_null() {
|
if c.is_null() {
|
||||||
|
@ -373,7 +374,7 @@ mod tests {
|
||||||
#[test_case]
|
#[test_case]
|
||||||
fn test_interrupt_table_length(_gba: &mut crate::Gba) {
|
fn test_interrupt_table_length(_gba: &mut crate::Gba) {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
unsafe { INTERRUPT_TABLE.len() },
|
unsafe { (*INTERRUPT_TABLE.get()).len() },
|
||||||
Interrupt::Gamepak as usize + 1,
|
Interrupt::Gamepak as usize + 1,
|
||||||
"interrupt table should be able to store gamepak interrupt"
|
"interrupt table should be able to store gamepak interrupt"
|
||||||
);
|
);
|
||||||
|
|
|
@ -190,6 +190,7 @@ mod sync;
|
||||||
pub mod syscall;
|
pub mod syscall;
|
||||||
/// Interactions with the internal timers
|
/// Interactions with the internal timers
|
||||||
pub mod timer;
|
pub mod timer;
|
||||||
|
pub(crate) mod util;
|
||||||
|
|
||||||
mod no_game;
|
mod no_game;
|
||||||
|
|
||||||
|
@ -326,6 +327,8 @@ impl Gba {
|
||||||
/// You can run the tests using `cargo test`, but it will work better through `mgba-test-runner` by
|
/// 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`.
|
/// running something along the lines of `CARGO_TARGET_THUMBV4T_NONE_EABI_RUNNER=mgba-test-runner cargo test`.
|
||||||
pub mod test_runner {
|
pub mod test_runner {
|
||||||
|
use util::SyncUnsafeCell;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
@ -373,7 +376,7 @@ pub mod test_runner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static mut TEST_GBA: Option<Gba> = None;
|
static TEST_GBA: SyncUnsafeCell<Option<Gba>> = SyncUnsafeCell::new(None);
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub fn test_runner(tests: &[&dyn Testable]) {
|
pub fn test_runner(tests: &[&dyn Testable]) {
|
||||||
|
@ -384,7 +387,7 @@ pub mod test_runner {
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let gba = unsafe { TEST_GBA.as_mut() }.unwrap();
|
let gba = unsafe { &mut *TEST_GBA.get() }.as_mut().unwrap();
|
||||||
|
|
||||||
for test in tests {
|
for test in tests {
|
||||||
test.run(gba);
|
test.run(gba);
|
||||||
|
@ -414,7 +417,7 @@ pub mod test_runner {
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub fn agb_start_tests(gba: Gba, test_main: impl Fn()) -> ! {
|
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();
|
test_main();
|
||||||
#[allow(clippy::empty_loop)]
|
#[allow(clippy::empty_loop)]
|
||||||
loop {}
|
loop {}
|
||||||
|
|
16
agb/src/util.rs
Normal file
16
agb/src/util.rs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
use core::cell::UnsafeCell;
|
||||||
|
|
||||||
|
pub struct SyncUnsafeCell<T>(UnsafeCell<T>);
|
||||||
|
|
||||||
|
unsafe impl<T> Sync for SyncUnsafeCell<T> {}
|
||||||
|
unsafe impl<T> Send for SyncUnsafeCell<T> {}
|
||||||
|
|
||||||
|
impl<T> SyncUnsafeCell<T> {
|
||||||
|
pub const fn new(t: T) -> Self {
|
||||||
|
Self(UnsafeCell::new(t))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn get(&self) -> *mut T {
|
||||||
|
self.0.get()
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
#[allow(non_upper_case_globals)]
|
#[allow(non_upper_case_globals)]
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
|
#[allow(improper_ctypes)]
|
||||||
mod ffi {
|
mod ffi {
|
||||||
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
|
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue