forked from M-Labs/zynq-rs
parent
1f4add397b
commit
606fef6d5c
@ -0,0 +1,71 @@ |
||||
/// 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" |
||||
); |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue