Skip to content

Commit

Permalink
Implement atomic fetch_or and fetch_and for thumbv6
Browse files Browse the repository at this point in the history
  • Loading branch information
timvisee authored and ithinuel committed Nov 26, 2023
1 parent 5684713 commit 9f96b42
Showing 1 changed file with 36 additions and 9 deletions.
45 changes: 36 additions & 9 deletions core/src/bbbuffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,8 @@ impl<'a, const N: usize> BBBuffer<N> {
/// ```
pub fn try_split(&'a self) -> Result<(Producer<'a, N>, Consumer<'a, N>)> {
// Set producer/consumer taken bit, error and reset if one was already set
let prev = self
.split_prod_cons
.fetch_or(BIT_PRODUCER | BIT_CONSUMER, AcqRel);
let prev = atomic::fetch_or(&self.split_prod_cons, BIT_PRODUCER | BIT_CONSUMER, AcqRel);

if prev > 0 {
self.split_prod_cons.store(prev, Release);
return Err(Error::AlreadySplit);
Expand Down Expand Up @@ -157,7 +156,7 @@ impl<'a, const N: usize> BBBuffer<N> {
/// while splitting.
pub fn try_take_producer(&'a self) -> Result<Producer<'a, N>> {
// Set producer taken bit, error if already set
if self.split_prod_cons.fetch_or(BIT_PRODUCER, AcqRel) & BIT_PRODUCER > 0 {
if atomic::fetch_or(&self.split_prod_cons, BIT_PRODUCER, AcqRel) & BIT_PRODUCER > 0 {
return Err(Error::AlreadySplit);
}

Expand Down Expand Up @@ -191,7 +190,7 @@ impl<'a, const N: usize> BBBuffer<N> {
/// while splitting.
pub fn try_take_consumer(&'a self) -> Result<Consumer<'a, N>> {
// Set producer taken bit, error if already set
if self.split_prod_cons.fetch_or(BIT_CONSUMER, AcqRel) & BIT_CONSUMER > 0 {
if atomic::fetch_or(&self.split_prod_cons, BIT_CONSUMER, AcqRel) & BIT_CONSUMER > 0 {
return Err(Error::AlreadySplit);
}

Expand Down Expand Up @@ -376,7 +375,7 @@ impl<'a, const N: usize> BBBuffer<N> {
self.last.store(0, Release);

// Mark the buffer as ready to retake producer
self.split_prod_cons.fetch_and(!BIT_PRODUCER, Release);
atomic::fetch_and(&self.split_prod_cons, !BIT_PRODUCER, Release);

Ok(())
}
Expand Down Expand Up @@ -447,7 +446,7 @@ impl<'a, const N: usize> BBBuffer<N> {
self.last.store(0, Release);

// Mark the buffer as ready to retake consumer
self.split_prod_cons.fetch_and(!BIT_CONSUMER, Release);
atomic::fetch_and(&self.split_prod_cons, !BIT_CONSUMER, Release);

Ok(())
}
Expand Down Expand Up @@ -1329,7 +1328,7 @@ impl<'a, const N: usize> DerefMut for GrantR<'a, N> {
#[cfg(feature = "thumbv6")]
mod atomic {
use core::sync::atomic::{
AtomicBool, AtomicUsize,
AtomicBool, AtomicU8, AtomicUsize,
Ordering::{self, Acquire, Release},
};
use cortex_m::interrupt::free;
Expand All @@ -1352,6 +1351,24 @@ mod atomic {
})
}

#[inline(always)]
pub fn fetch_and(atomic: &AtomicU8, val: u8, _order: Ordering) -> u8 {
free(|_| {
let prev = atomic.load(Acquire);
atomic.store(prev & val, Release);
prev
})
}

#[inline(always)]
pub fn fetch_or(atomic: &AtomicU8, val: u8, _order: Ordering) -> u8 {
free(|_| {
let prev = atomic.load(Acquire);
atomic.store(prev | val, Release);
prev
})
}

#[inline(always)]
pub fn swap(atomic: &AtomicBool, val: bool, _order: Ordering) -> bool {
free(|_| {
Expand All @@ -1364,7 +1381,7 @@ mod atomic {

#[cfg(not(feature = "thumbv6"))]
mod atomic {
use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use core::sync::atomic::{AtomicBool, AtomicU8, AtomicUsize, Ordering};

#[inline(always)]
pub fn fetch_add(atomic: &AtomicUsize, val: usize, order: Ordering) -> usize {
Expand All @@ -1376,6 +1393,16 @@ mod atomic {
atomic.fetch_sub(val, order)
}

#[inline(always)]
pub fn fetch_and(atomic: &AtomicU8, val: u8, order: Ordering) -> u8 {
atomic.fetch_and(val, order)
}

#[inline(always)]
pub fn fetch_or(atomic: &AtomicU8, val: u8, order: Ordering) -> u8 {
atomic.fetch_or(val, order)
}

#[inline(always)]
pub fn swap(atomic: &AtomicBool, val: bool, order: Ordering) -> bool {
atomic.swap(val, order)
Expand Down

0 comments on commit 9f96b42

Please sign in to comment.