synchronization primitives #57

Merged
sb10q merged 1 commits from pca006132/zynq-rs:sync into master 2020-08-04 13:57:58 +08:00
7 changed files with 39 additions and 34 deletions

View File

@ -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();
}
}

View File

@ -7,6 +7,7 @@ edition = "2018"
[features]
target_zc706 = []
target_cora_z7_10 = []
power_saving = []
default = ["target_zc706"]
[dependencies]

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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 {

View File

@ -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();
}
}

View File

@ -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 {}
}