synchronization primitives #57
|
@ -30,6 +30,7 @@ use libcortex_a9::{
|
|||
sync_channel::{Sender, Receiver},
|
||||
sync_channel,
|
||||
regs::{MPIDR, SP},
|
||||
spin_lock_yield, notify_spin_lock,
|
||||
asm
|
||||
};
|
||||
use libregister::{RegisterR, RegisterW};
|
||||
|
@ -64,7 +65,7 @@ pub unsafe extern "C" fn IRQ() {
|
|||
SP.write(&mut __stack1_start as *mut _ as u32);
|
||||
asm::enable_irq();
|
||||
CORE1_RESTART.store(false, Ordering::Relaxed);
|
||||
asm::sev();
|
||||
notify_spin_lock();
|
||||
main_core1();
|
||||
}
|
||||
}
|
||||
|
@ -78,7 +79,7 @@ pub fn restart_core1() {
|
|||
CORE1_RESTART.store(true, Ordering::Relaxed);
|
||||
interrupt_controller.send_sgi(gic::InterruptId(0), gic::CPUCore::Core1.into());
|
||||
while CORE1_RESTART.load(Ordering::Relaxed) {
|
||||
asm::wfe();
|
||||
spin_lock_yield();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ edition = "2018"
|
|||
[features]
|
||||
target_zc706 = []
|
||||
target_cora_z7_10 = []
|
||||
power_saving = []
|
||||
default = ["target_zc706"]
|
||||
|
||||
[dependencies]
|
||||
|
|
|
@ -18,3 +18,19 @@ pub use uncached::UncachedSlice;
|
|||
pub use fpu::enable_fpu;
|
||||
|
||||
global_asm!(include_str!("exceptions.s"));
|
||||
|
||||
#[inline]
|
||||
pub fn spin_lock_yield() {
|
||||
#[cfg(feature = "power_saving")]
|
||||
asm::wfe();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn notify_spin_lock() {
|
||||
#[cfg(feature = "power_saving")]
|
||||
{
|
||||
asm::dsb();
|
||||
asm::sev();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,20 +1,10 @@
|
|||
use core::ops::{Deref, DerefMut};
|
||||
use core::sync::atomic::{AtomicU32, Ordering};
|
||||
use core::cell::UnsafeCell;
|
||||
use super::asm::*;
|
||||
|
||||
/// [Power-saving features](http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dht0008a/ch01s03s02.html)
|
||||
#[inline]
|
||||
fn wait_for_update() {
|
||||
wfe();
|
||||
}
|
||||
|
||||
/// [Power-saving features](http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dht0008a/ch01s03s02.html)
|
||||
#[inline]
|
||||
fn signal_update() {
|
||||
dsb();
|
||||
sev();
|
||||
}
|
||||
use super::{
|
||||
spin_lock_yield, notify_spin_lock,
|
||||
asm::{dmb, enter_critical, exit_critical}
|
||||
};
|
||||
|
||||
const LOCKED: u32 = 1;
|
||||
const UNLOCKED: u32 = 0;
|
||||
|
@ -45,7 +35,7 @@ impl<T> Mutex<T> {
|
|||
while self.locked.compare_and_swap(UNLOCKED, LOCKED, Ordering::Acquire) != UNLOCKED {
|
||||
unsafe {
|
||||
exit_critical(irq);
|
||||
wait_for_update();
|
||||
spin_lock_yield();
|
||||
irq = enter_critical();
|
||||
}
|
||||
}
|
||||
|
@ -68,7 +58,7 @@ impl<T> Mutex<T> {
|
|||
dmb();
|
||||
self.locked.store(UNLOCKED, Ordering::Release);
|
||||
|
||||
signal_update();
|
||||
notify_spin_lock();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use super::asm::{sev, wfe};
|
||||
use super::{spin_lock_yield, notify_spin_lock};
|
||||
use core::{
|
||||
task::{Context, Poll},
|
||||
pin::Pin,
|
||||
future::Future
|
||||
future::Future,
|
||||
sync::atomic::{AtomicI32, Ordering}
|
||||
};
|
||||
use core::sync::atomic::{AtomicI32, Ordering};
|
||||
|
||||
pub struct Semaphore {
|
||||
value: AtomicI32,
|
||||
|
@ -31,7 +31,7 @@ impl Semaphore {
|
|||
|
||||
pub fn wait(&self) {
|
||||
while self.try_wait().is_none() {
|
||||
wfe();
|
||||
spin_lock_yield();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,7 @@ impl Semaphore {
|
|||
let value = self.value.load(Ordering::Relaxed);
|
||||
if value < self.max {
|
||||
if self.value.compare_and_swap(value, value + 1, Ordering::SeqCst) == value {
|
||||
sev();
|
||||
notify_spin_lock();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -6,7 +6,7 @@ use core::{
|
|||
task::{Context, Poll},
|
||||
};
|
||||
use alloc::boxed::Box;
|
||||
use super::asm::*;
|
||||
use super::{spin_lock_yield, notify_spin_lock};
|
||||
|
||||
pub struct Sender<'a, T> where T: Clone {
|
||||
list: &'a [AtomicPtr<T>],
|
||||
|
@ -35,9 +35,7 @@ impl<'a, T> Sender<'a, T> where T: Clone {
|
|||
let prev = entry.swap(ptr, Ordering::Relaxed);
|
||||
// we allow other end get it first
|
||||
self.write.store((write + 1) % self.list.len(), Ordering::Release);
|
||||
// wake up other core, actually I wonder if the dsb is really needed...
|
||||
dsb();
|
||||
sev();
|
||||
notify_spin_lock();
|
||||
if !prev.is_null() {
|
||||
unsafe {
|
||||
drop_in_place(prev);
|
||||
|
@ -51,7 +49,7 @@ impl<'a, T> Sender<'a, T> where T: Clone {
|
|||
let mut content = content;
|
||||
while let Err(back) = self.try_send(content) {
|
||||
content = back;
|
||||
wfe();
|
||||
spin_lock_yield();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,9 +114,7 @@ impl<'a, T> Receiver<'a, T> where T: Clone {
|
|||
};
|
||||
let result = data.clone();
|
||||
self.read.store((read + 1) % self.list.len(), Ordering::Release);
|
||||
// wake up other core, still idk if the dsb is needed...
|
||||
dsb();
|
||||
sev();
|
||||
notify_spin_lock();
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
@ -128,7 +124,7 @@ impl<'a, T> Receiver<'a, T> where T: Clone {
|
|||
if let Ok(data) = self.try_recv() {
|
||||
return data;
|
||||
}
|
||||
wfe();
|
||||
spin_lock_yield();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ use libregister::{
|
|||
VolatileCell,
|
||||
RegisterR, RegisterW, RegisterRW,
|
||||
};
|
||||
use libcortex_a9::{asm, regs::*, cache, mmu};
|
||||
use libcortex_a9::{asm, regs::*, cache, mmu, spin_lock_yield, notify_spin_lock};
|
||||
use libboard_zynq::{slcr, mpcore};
|
||||
|
||||
extern "C" {
|
||||
|
@ -29,7 +29,7 @@ pub unsafe extern "C" fn Reset() -> ! {
|
|||
}
|
||||
1 => {
|
||||
while !CORE1_ENABLED.get() {
|
||||
asm::wfe();
|
||||
spin_lock_yield();
|
||||
}
|
||||
SP.write(&mut __stack1_start as *mut _ as u32);
|
||||
boot_core1();
|
||||
|
@ -144,6 +144,7 @@ impl Core1 {
|
|||
slcr.a9_cpu_rst_ctrl.modify(|_, w| w.a9_rst1(false));
|
||||
slcr.a9_cpu_rst_ctrl.modify(|_, w| w.a9_clkstop1(false));
|
||||
});
|
||||
notify_spin_lock();
|
||||
|
||||
Core1 {}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue