Take advantage of the fact that CriticalSection is Copy

This commit is contained in:
Gwilym Kuiper 2022-06-11 20:33:32 +01:00
parent 1edd7f4166
commit f2e565f512
9 changed files with 37 additions and 37 deletions

View file

@ -10,8 +10,8 @@ fn main(_gba: agb::Gba) -> ! {
let count = Mutex::new(RefCell::new(0)); let count = Mutex::new(RefCell::new(0));
let _a = agb::interrupt::add_interrupt_handler( let _a = agb::interrupt::add_interrupt_handler(
agb::interrupt::Interrupt::VBlank, agb::interrupt::Interrupt::VBlank,
|key: &CriticalSection| { |key: CriticalSection| {
let mut count = count.borrow(*key).borrow_mut(); let mut count = count.borrow(key).borrow_mut();
agb::println!("Hello, world, frame = {}", *count); agb::println!("Hello, world, frame = {}", *count);
*count += 1; *count += 1;
}, },

View file

@ -31,8 +31,8 @@ fn main(mut gba: agb::Gba) -> ! {
let back = Mutex::new(RefCell::new(BackCosines { cosines, row: 0 })); let back = Mutex::new(RefCell::new(BackCosines { cosines, row: 0 }));
let _a = agb::interrupt::add_interrupt_handler(Interrupt::HBlank, |key: &CriticalSection| { let _a = agb::interrupt::add_interrupt_handler(Interrupt::HBlank, |key: CriticalSection| {
let mut backc = back.borrow(*key).borrow_mut(); let mut backc = back.borrow(key).borrow_mut();
let deflection = backc.cosines[backc.row % 32]; let deflection = backc.cosines[backc.row % 32];
unsafe { ((0x0400_0010) as *mut u16).write_volatile(deflection) } unsafe { ((0x0400_0010) as *mut u16).write_volatile(deflection) }
backc.row += 1; backc.row += 1;
@ -43,7 +43,7 @@ fn main(mut gba: agb::Gba) -> ! {
loop { loop {
vblank.wait_for_vblank(); vblank.wait_for_vblank();
free(|key| { free(|key| {
let mut backc = back.borrow(*key).borrow_mut(); let mut backc = back.borrow(key).borrow_mut();
backc.row = 0; backc.row = 0;
time += 1; time += 1;
for (r, a) in backc.cosines.iter_mut().enumerate() { for (r, a) in backc.cosines.iter_mut().enumerate() {

View file

@ -61,7 +61,7 @@ impl BlockAllocator {
#[cfg(test)] #[cfg(test)]
pub unsafe fn number_of_blocks(&self) -> u32 { pub unsafe fn number_of_blocks(&self) -> u32 {
free(|key| { free(|key| {
let mut state = self.state.borrow(*key).borrow_mut(); let mut state = self.state.borrow(key).borrow_mut();
let mut count = 0; let mut count = 0;
@ -76,7 +76,7 @@ impl BlockAllocator {
} }
/// Requests a brand new block from the inner bump allocator /// Requests a brand new block from the inner bump allocator
fn new_block(&self, layout: Layout, cs: &CriticalSection) -> Option<NonNull<u8>> { fn new_block(&self, layout: Layout, cs: CriticalSection) -> Option<NonNull<u8>> {
let overall_layout = Block::either_layout(layout); let overall_layout = Block::either_layout(layout);
self.inner_allocator.alloc_critical(overall_layout, cs) self.inner_allocator.alloc_critical(overall_layout, cs)
} }
@ -84,7 +84,7 @@ impl BlockAllocator {
/// Merges blocks together to create a normalised list /// Merges blocks together to create a normalised list
unsafe fn normalise(&self) { unsafe fn normalise(&self) {
free(|key| { free(|key| {
let mut state = self.state.borrow(*key).borrow_mut(); let mut state = self.state.borrow(key).borrow_mut();
let mut list_ptr = &mut state.first_free_block; let mut list_ptr = &mut state.first_free_block;
@ -121,7 +121,7 @@ impl BlockAllocator {
.unwrap(); .unwrap();
free(|key| { free(|key| {
let mut state = self.state.borrow(*key).borrow_mut(); let mut state = self.state.borrow(key).borrow_mut();
let mut current_block = state.first_free_block; let mut current_block = state.first_free_block;
let mut list_ptr = &mut state.first_free_block; let mut list_ptr = &mut state.first_free_block;
// This iterates the free list until it either finds a block that // This iterates the free list until it either finds a block that
@ -164,7 +164,7 @@ impl BlockAllocator {
pub unsafe fn dealloc_no_normalise(&self, ptr: *mut u8, layout: Layout) { pub unsafe fn dealloc_no_normalise(&self, ptr: *mut u8, layout: Layout) {
let new_layout = Block::either_layout(layout).pad_to_align(); let new_layout = Block::either_layout(layout).pad_to_align();
free(|key| { free(|key| {
let mut state = self.state.borrow(*key).borrow_mut(); let mut state = self.state.borrow(key).borrow_mut();
// note that this is a reference to a pointer // note that this is a reference to a pointer
let mut list_ptr = &mut state.first_free_block; let mut list_ptr = &mut state.first_free_block;

View file

@ -26,13 +26,13 @@ impl BumpAllocator {
} }
impl BumpAllocator { impl BumpAllocator {
pub fn alloc_critical(&self, layout: Layout, cs: &CriticalSection) -> Option<NonNull<u8>> { pub fn alloc_critical(&self, layout: Layout, cs: CriticalSection) -> Option<NonNull<u8>> {
let mut current_ptr = self.current_ptr.borrow(*cs).borrow_mut(); let mut current_ptr = self.current_ptr.borrow(cs).borrow_mut();
let ptr = if let Some(c) = *current_ptr { let ptr = if let Some(c) = *current_ptr {
c.as_ptr() as usize c.as_ptr() as usize
} else { } else {
(self.start_end.borrow(*cs).start)() (self.start_end.borrow(cs).start)()
}; };
let alignment_bitmask = layout.align() - 1; let alignment_bitmask = layout.align() - 1;
@ -43,7 +43,7 @@ impl BumpAllocator {
let resulting_ptr = ptr + amount_to_add; let resulting_ptr = ptr + amount_to_add;
let new_current_ptr = resulting_ptr + layout.size(); let new_current_ptr = resulting_ptr + layout.size();
if new_current_ptr as usize >= (self.start_end.borrow(*cs).end)() { if new_current_ptr as usize >= (self.start_end.borrow(cs).end)() {
return None; return None;
} }

View file

@ -56,7 +56,7 @@ impl ObjectControllerRef {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
{ {
let a = crate::interrupt::free(|c| { let a = crate::interrupt::free(|c| {
let mut b = OBJECT_REFS_CURRENT.borrow(*c).borrow_mut(); let mut b = OBJECT_REFS_CURRENT.borrow(c).borrow_mut();
let a = *b; let a = *b;
*b += 1; *b += 1;
a a
@ -76,7 +76,7 @@ impl ObjectControllerRef {
impl Drop for ObjectControllerRef { impl Drop for ObjectControllerRef {
fn drop(&mut self) { fn drop(&mut self) {
crate::interrupt::free(|c| { crate::interrupt::free(|c| {
let mut b = OBJECT_REFS_CURRENT.borrow(*c).borrow_mut(); let mut b = OBJECT_REFS_CURRENT.borrow(c).borrow_mut();
*b -= 1; *b -= 1;
}) })
} }

View file

@ -59,7 +59,7 @@ type HashType = u32;
/// A hash map implemented very simply using robin hood hashing. /// A hash map implemented very simply using robin hood hashing.
/// ///
/// HashMap uses FxHasher internally, which is a very fast hashing algorithm used /// `HashMap` uses `FxHasher` internally, which is a very fast hashing algorithm used
/// by rustc and firefox in non-adversarial places. It is incredibly fast, and good /// by rustc and firefox in non-adversarial places. It is incredibly fast, and good
/// enough for most cases. /// enough for most cases.
/// ///
@ -76,7 +76,7 @@ type HashType = u32;
/// aborts, memory leaks and non-termination. /// aborts, memory leaks and non-termination.
/// ///
/// The API surface provided is incredibly similar to the /// The API surface provided is incredibly similar to the
/// [std::collections::HashMap](https://doc.rust-lang.org/std/collections/struct.HashMap.html) /// [`std::collections::HashMap`](https://doc.rust-lang.org/std/collections/struct.HashMap.html)
/// implementation with fewer guarantees, and better optimised for the GameBoy Advance. /// implementation with fewer guarantees, and better optimised for the GameBoy Advance.
/// ///
/// [`Eq`]: https://doc.rust-lang.org/core/cmp/trait.Eq.html /// [`Eq`]: https://doc.rust-lang.org/core/cmp/trait.Eq.html

View file

@ -157,17 +157,17 @@ extern "C" fn __RUST_INTERRUPT_HANDLER(interrupt: u16) -> u16 {
struct InterruptInner { struct InterruptInner {
next: Cell<*const InterruptInner>, next: Cell<*const InterruptInner>,
root: *const InterruptRoot, root: *const InterruptRoot,
closure: *const dyn Fn(&CriticalSection), closure: *const dyn Fn(CriticalSection),
_pin: PhantomPinned, _pin: PhantomPinned,
} }
unsafe fn create_interrupt_inner( unsafe fn create_interrupt_inner(
c: impl Fn(&CriticalSection), c: impl Fn(CriticalSection),
root: *const InterruptRoot, root: *const InterruptRoot,
) -> Pin<Box<InterruptInner>> { ) -> Pin<Box<InterruptInner>> {
let c = Box::new(c); let c = Box::new(c);
let c: &dyn Fn(&CriticalSection) = Box::leak(c); let c: &dyn Fn(CriticalSection) = Box::leak(c);
let c: &dyn Fn(&CriticalSection) = core::mem::transmute(c); let c: &dyn Fn(CriticalSection) = core::mem::transmute(c);
Box::pin(InterruptInner { Box::pin(InterruptInner {
next: Cell::new(core::ptr::null()), next: Cell::new(core::ptr::null()),
root, root,
@ -216,7 +216,7 @@ impl InterruptRoot {
while !c.is_null() { while !c.is_null() {
let closure_ptr = unsafe { &*c }.closure; let closure_ptr = unsafe { &*c }.closure;
let closure_ref = unsafe { &*closure_ptr }; let closure_ref = unsafe { &*closure_ptr };
closure_ref(unsafe { &CriticalSection::new() }); closure_ref(unsafe { CriticalSection::new() });
c = unsafe { &*c }.next.get(); c = unsafe { &*c }.next.get();
} }
} }
@ -241,7 +241,7 @@ fn interrupt_to_root(interrupt: Interrupt) -> &'static InterruptRoot {
/// ``` /// ```
pub fn add_interrupt_handler<'a>( pub fn add_interrupt_handler<'a>(
interrupt: Interrupt, interrupt: Interrupt,
handler: impl Fn(&CriticalSection) + Send + Sync + 'a, handler: impl Fn(CriticalSection) + Send + Sync + 'a,
) -> InterruptHandler<'a> { ) -> InterruptHandler<'a> {
fn do_with_inner<'a>( fn do_with_inner<'a>(
interrupt: Interrupt, interrupt: Interrupt,
@ -282,13 +282,13 @@ pub fn add_interrupt_handler<'a>(
/// [`CriticalSection`]: bare_metal::CriticalSection /// [`CriticalSection`]: bare_metal::CriticalSection
pub fn free<F, R>(f: F) -> R pub fn free<F, R>(f: F) -> R
where where
F: FnOnce(&CriticalSection) -> R, F: FnOnce(CriticalSection) -> R,
{ {
let enabled = INTERRUPTS_ENABLED.get(); let enabled = INTERRUPTS_ENABLED.get();
disable_interrupts(); disable_interrupts();
let r = f(unsafe { &CriticalSection::new() }); let r = f(unsafe { CriticalSection::new() });
INTERRUPTS_ENABLED.set(enabled); INTERRUPTS_ENABLED.set(enabled);
r r
@ -328,17 +328,17 @@ mod tests {
{ {
let counter = Mutex::new(RefCell::new(0)); let counter = Mutex::new(RefCell::new(0));
let counter_2 = Mutex::new(RefCell::new(0)); let counter_2 = Mutex::new(RefCell::new(0));
let _a = add_interrupt_handler(Interrupt::VBlank, |key: &CriticalSection| { let _a = add_interrupt_handler(Interrupt::VBlank, |key: CriticalSection| {
*counter.borrow(*key).borrow_mut() += 1 *counter.borrow(key).borrow_mut() += 1
}); });
let _b = add_interrupt_handler(Interrupt::VBlank, |key: &CriticalSection| { let _b = add_interrupt_handler(Interrupt::VBlank, |key: CriticalSection| {
*counter_2.borrow(*key).borrow_mut() += 1 *counter_2.borrow(key).borrow_mut() += 1
}); });
let vblank = VBlank::get(); let vblank = VBlank::get();
while free(|key| { while free(|key| {
*counter.borrow(*key).borrow() < 100 || *counter_2.borrow(*key).borrow() < 100 *counter.borrow(key).borrow() < 100 || *counter_2.borrow(key).borrow() < 100
}) { }) {
vblank.wait_for_vblank(); vblank.wait_for_vblank();
} }
@ -375,7 +375,7 @@ pub fn profiler(timer: &mut crate::timer::Timer, period: u16) -> InterruptHandle
timer.set_overflow_amount(period); timer.set_overflow_amount(period);
timer.set_enabled(true); timer.set_enabled(true);
add_interrupt_handler(timer.interrupt(), |_key: &CriticalSection| { add_interrupt_handler(timer.interrupt(), |_key: CriticalSection| {
crate::println!("{:#010x}", crate::program_counter_before_interrupt()); crate::println!("{:#010x}", crate::program_counter_before_interrupt());
}) })
} }

View file

@ -55,7 +55,7 @@ static GLOBAL_RNG: Mutex<RefCell<RandomNumberGenerator>> =
/// Using a global random number generator, provides the next random number /// Using a global random number generator, provides the next random number
pub fn gen() -> i32 { pub fn gen() -> i32 {
free(|cs| GLOBAL_RNG.borrow(*cs).borrow_mut().gen()) free(|cs| GLOBAL_RNG.borrow(cs).borrow_mut().gen())
} }
#[cfg(test)] #[cfg(test)]

View file

@ -216,11 +216,11 @@ impl MixerBuffer {
} }
fn should_calculate(&self) -> bool { fn should_calculate(&self) -> bool {
free(|cs| self.state.borrow(*cs).borrow().should_calculate()) free(|cs| self.state.borrow(cs).borrow().should_calculate())
} }
fn swap(&self, cs: &CriticalSection) { fn swap(&self, cs: CriticalSection) {
let buffer = self.state.borrow(*cs).borrow_mut().playing_advanced(); let buffer = self.state.borrow(cs).borrow_mut().playing_advanced();
let (left_buffer, right_buffer) = self.buffers[buffer] let (left_buffer, right_buffer) = self.buffers[buffer]
.0 .0
@ -282,7 +282,7 @@ impl MixerBuffer {
channel.pos += playback_speed * constants::SOUND_BUFFER_SIZE; channel.pos += playback_speed * constants::SOUND_BUFFER_SIZE;
} }
let write_buffer_index = free(|cs| self.state.borrow(*cs).borrow_mut().active_advanced()); let write_buffer_index = free(|cs| self.state.borrow(cs).borrow_mut().active_advanced());
let write_buffer = &mut self.buffers[write_buffer_index].0; let write_buffer = &mut self.buffers[write_buffer_index].0;
cpu_fast_fill_i8(write_buffer, 0); cpu_fast_fill_i8(write_buffer, 0);