/// Mutex for SMP-safe locking use crate::cortex_a9::asm; pub struct Mutex { state: u32, } const UNLOCKED_MUTEX: u32 = 0; const LOCKED_MUTEX: u32 = 1; impl Mutex { pub const fn new_unlocked() -> Mutex { Mutex { state: UNLOCKED_MUTEX } } pub const fn new_locked() -> Mutex { Mutex { state: LOCKED_MUTEX } } // inlining causes problems with the labels #[inline(never)] pub fn acquire(&mut self) { unsafe { // code adapted from an example by ARM at // http://infocenter.arm.com (Home > ARM Synchronization // Primitives > Practical uses > Implementing a mutex) asm!(" mutex_acquire_label1: ldrex r2, [$0]; cmp r2, $1; beq mutex_acquire_label2; strexne r2, $1, [$0]; cmpne r2, 1; beq mutex_acquire_label1; dmb; b mutex_acquire_label3; mutex_acquire_label2: wfe; b mutex_acquire_label1; mutex_acquire_label3: ; " :: // inputs "r" (&mut self.state as *mut _ as u32), "r" (LOCKED_MUTEX) : // clobbers "r2" : "volatile" ); } } pub fn release(&mut self) { unsafe { asm!(" dmb; str $1, [$0]; dsb; sev; " :: // inputs "r" (&mut self.state as *mut _ as u32), "r" (UNLOCKED_MUTEX) :: "volatile" ); } } }