mirror of
https://github.com/italicsjenga/agb.git
synced 2024-12-24 08:41:34 +11:00
Take advantage of the fact that CriticalSection is Copy
This commit is contained in:
parent
1edd7f4166
commit
f2e565f512
|
@ -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;
|
||||||
},
|
},
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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());
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)]
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue