synchronization primitives #57
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 {}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue