Skip to content

Commit

Permalink
Revert "kernel: common: use built in AtomicUsize"
Browse files Browse the repository at this point in the history
This reverts commit 7f20daa.

There are RISC-V platforms that don't support atomics (such as
OpenTitan) so let's revert this commit until RV32 has atomic load and
store support when the Atomic (A) extension isn't supported. That is
wait until something like this for RISC-V is merged:
rust-lang/rust#51953

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
  • Loading branch information
alistair23 committed Jan 23, 2020
1 parent a8f30ae commit d2afd39
Showing 1 changed file with 39 additions and 9 deletions.
48 changes: 39 additions & 9 deletions kernel/src/common/deferred_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,51 @@
//! in the chip scheduler if the hardware doesn't support interrupts where
//! they are needed.
use core::cell::UnsafeCell;
use core::convert::Into;
use core::convert::TryFrom;
use core::convert::TryInto;
use core::intrinsics;
use core::marker::Copy;
use core::sync::atomic::AtomicUsize;
use core::sync::atomic::Ordering;
use core::marker::Sync;

/// AtomicUsize with no CAS operations that works on targets that have "no atomic
/// support" according to their specification. This makes it work on thumbv6
/// platforms.
///
/// Borrowed from https://github.com/japaric/heapless/blob/master/src/ring_buffer/mod.rs
/// See: https://github.com/japaric/heapless/commit/37c8b5b63780ed8811173dc1ec8859cd99efa9ad
struct AtomicUsize {
v: UnsafeCell<usize>,
}

impl AtomicUsize {
crate const fn new(v: usize) -> AtomicUsize {
AtomicUsize {
v: UnsafeCell::new(v),
}
}

crate fn load_relaxed(&self) -> usize {
unsafe { intrinsics::atomic_load_relaxed(self.v.get()) }
}

crate fn store_relaxed(&self, val: usize) {
unsafe { intrinsics::atomic_store_relaxed(self.v.get(), val) }
}

crate fn fetch_or_relaxed(&self, val: usize) {
unsafe { intrinsics::atomic_store_relaxed(self.v.get(), self.load_relaxed() | val) }
}
}

unsafe impl Sync for AtomicUsize {}

static DEFERRED_CALL: AtomicUsize = AtomicUsize::new(0);

/// Are there any pending `DeferredCall`s?
pub fn has_tasks() -> bool {
DEFERRED_CALL.load(Ordering::Relaxed) != 0
DEFERRED_CALL.load_relaxed() != 0
}

/// Represents a way to generate an asynchronous call without a hardware
Expand All @@ -33,21 +66,18 @@ impl<T: Into<usize> + TryFrom<usize> + Copy> DeferredCall<T> {

/// Set the `DeferredCall` as pending
pub fn set(&self) {
// DEFERRED_CALL.fetch_or(1 << self.0.into() as usize, Ordering::Relaxed);
let val = DEFERRED_CALL.load(Ordering::Relaxed);
let new_val = val | (1 << self.0.into());
DEFERRED_CALL.store(new_val, Ordering::Relaxed);
DEFERRED_CALL.fetch_or_relaxed(1 << self.0.into() as usize);
}

/// Gets and clears the next pending `DeferredCall`
pub fn next_pending() -> Option<T> {
let val = DEFERRED_CALL.load(Ordering::Relaxed);
let val = DEFERRED_CALL.load_relaxed();
if val == 0 {
None
} else {
let bit = val.trailing_zeros() as usize;
let new_val = val & !(1 << bit);
DEFERRED_CALL.store(new_val, Ordering::Relaxed);
DEFERRED_CALL.store_relaxed(new_val);
bit.try_into().ok()
}
}
Expand Down

0 comments on commit d2afd39

Please sign in to comment.