zc706/src/mutex.rs

72 lines
1.9 KiB
Rust

/// 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"
);
}
}
}