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::{Sender, Receiver},
sync_channel, sync_channel,
regs::{MPIDR, SP}, regs::{MPIDR, SP},
spin_lock_yield, notify_spin_lock,
asm asm
}; };
use libregister::{RegisterR, RegisterW}; use libregister::{RegisterR, RegisterW};
@ -64,7 +65,7 @@ pub unsafe extern "C" fn IRQ() {
SP.write(&mut __stack1_start as *mut _ as u32); SP.write(&mut __stack1_start as *mut _ as u32);
asm::enable_irq(); asm::enable_irq();
CORE1_RESTART.store(false, Ordering::Relaxed); CORE1_RESTART.store(false, Ordering::Relaxed);
asm::sev(); notify_spin_lock();
main_core1(); main_core1();
} }
} }
@ -78,7 +79,7 @@ pub fn restart_core1() {
CORE1_RESTART.store(true, Ordering::Relaxed); CORE1_RESTART.store(true, Ordering::Relaxed);
interrupt_controller.send_sgi(gic::InterruptId(0), gic::CPUCore::Core1.into()); interrupt_controller.send_sgi(gic::InterruptId(0), gic::CPUCore::Core1.into());
while CORE1_RESTART.load(Ordering::Relaxed) { while CORE1_RESTART.load(Ordering::Relaxed) {
asm::wfe(); spin_lock_yield();
} }
} }

View File

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

View File

@ -18,3 +18,19 @@ pub use uncached::UncachedSlice;
pub use fpu::enable_fpu; pub use fpu::enable_fpu;
global_asm!(include_str!("exceptions.s")); 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::ops::{Deref, DerefMut};
use core::sync::atomic::{AtomicU32, Ordering}; use core::sync::atomic::{AtomicU32, Ordering};
use core::cell::UnsafeCell; use core::cell::UnsafeCell;
use super::asm::*; use super::{
spin_lock_yield, notify_spin_lock,
/// [Power-saving features](http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dht0008a/ch01s03s02.html) asm::{dmb, enter_critical, exit_critical}
#[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();
}
const LOCKED: u32 = 1; const LOCKED: u32 = 1;
const UNLOCKED: u32 = 0; const UNLOCKED: u32 = 0;
@ -45,7 +35,7 @@ impl<T> Mutex<T> {
while self.locked.compare_and_swap(UNLOCKED, LOCKED, Ordering::Acquire) != UNLOCKED { while self.locked.compare_and_swap(UNLOCKED, LOCKED, Ordering::Acquire) != UNLOCKED {
unsafe { unsafe {
exit_critical(irq); exit_critical(irq);
wait_for_update(); spin_lock_yield();
irq = enter_critical(); irq = enter_critical();
} }
} }
@ -68,7 +58,7 @@ impl<T> Mutex<T> {
dmb(); dmb();
self.locked.store(UNLOCKED, Ordering::Release); 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::{ use core::{
task::{Context, Poll}, task::{Context, Poll},
pin::Pin, pin::Pin,
future::Future future::Future,
sync::atomic::{AtomicI32, Ordering}
}; };
use core::sync::atomic::{AtomicI32, Ordering};
pub struct Semaphore { pub struct Semaphore {
value: AtomicI32, value: AtomicI32,
@ -31,7 +31,7 @@ impl Semaphore {
pub fn wait(&self) { pub fn wait(&self) {
while self.try_wait().is_none() { while self.try_wait().is_none() {
wfe(); spin_lock_yield();
} }
} }
@ -59,7 +59,7 @@ impl Semaphore {
let value = self.value.load(Ordering::Relaxed); let value = self.value.load(Ordering::Relaxed);
if value < self.max { if value < self.max {
if self.value.compare_and_swap(value, value + 1, Ordering::SeqCst) == value { if self.value.compare_and_swap(value, value + 1, Ordering::SeqCst) == value {
sev(); notify_spin_lock();
return; return;
} }
} else { } else {

View File

@ -6,7 +6,7 @@ use core::{
task::{Context, Poll}, task::{Context, Poll},
}; };
use alloc::boxed::Box; use alloc::boxed::Box;
use super::asm::*; use super::{spin_lock_yield, notify_spin_lock};
pub struct Sender<'a, T> where T: Clone { pub struct Sender<'a, T> where T: Clone {
list: &'a [AtomicPtr<T>], list: &'a [AtomicPtr<T>],
@ -35,9 +35,7 @@ impl<'a, T> Sender<'a, T> where T: Clone {
let prev = entry.swap(ptr, Ordering::Relaxed); let prev = entry.swap(ptr, Ordering::Relaxed);
// we allow other end get it first // we allow other end get it first
self.write.store((write + 1) % self.list.len(), Ordering::Release); self.write.store((write + 1) % self.list.len(), Ordering::Release);
// wake up other core, actually I wonder if the dsb is really needed... notify_spin_lock();
dsb();
sev();
if !prev.is_null() { if !prev.is_null() {
unsafe { unsafe {
drop_in_place(prev); drop_in_place(prev);
@ -51,7 +49,7 @@ impl<'a, T> Sender<'a, T> where T: Clone {
let mut content = content; let mut content = content;
while let Err(back) = self.try_send(content) { while let Err(back) = self.try_send(content) {
content = back; content = back;
wfe(); spin_lock_yield();
} }
} }
@ -116,9 +114,7 @@ impl<'a, T> Receiver<'a, T> where T: Clone {
}; };
let result = data.clone(); let result = data.clone();
self.read.store((read + 1) % self.list.len(), Ordering::Release); self.read.store((read + 1) % self.list.len(), Ordering::Release);
// wake up other core, still idk if the dsb is needed... notify_spin_lock();
dsb();
sev();
Ok(result) Ok(result)
} }
} }
@ -128,7 +124,7 @@ impl<'a, T> Receiver<'a, T> where T: Clone {
if let Ok(data) = self.try_recv() { if let Ok(data) = self.try_recv() {
return data; return data;
} }
wfe(); spin_lock_yield();
} }
} }

View File

@ -4,7 +4,7 @@ use libregister::{
VolatileCell, VolatileCell,
RegisterR, RegisterW, RegisterRW, 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}; use libboard_zynq::{slcr, mpcore};
extern "C" { extern "C" {
@ -29,7 +29,7 @@ pub unsafe extern "C" fn Reset() -> ! {
} }
1 => { 1 => {
while !CORE1_ENABLED.get() { while !CORE1_ENABLED.get() {
asm::wfe(); spin_lock_yield();
} }
SP.write(&mut __stack1_start as *mut _ as u32); SP.write(&mut __stack1_start as *mut _ as u32);
boot_core1(); 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_rst1(false));
slcr.a9_cpu_rst_ctrl.modify(|_, w| w.a9_clkstop1(false)); slcr.a9_cpu_rst_ctrl.modify(|_, w| w.a9_clkstop1(false));
}); });
notify_spin_lock();
Core1 {} Core1 {}
} }