summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Emil Fresk <emil.fresk@gmail.com> 2022-01-19 14:59:12 +0100
committerGravatar GitHub <noreply@github.com> 2022-01-19 14:59:12 +0100
commit70cecc414749bcc06fc477bda3cbf83ada667c8e (patch)
tree115527275db30a7f385347b933bb2b1eeef22b78
parent7546c64e791e7d8f67d12b0a9fc74031ec1b8cba (diff)
parentbc9e208089a415f0400f88ba4a8bfd20d955e317 (diff)
downloadheapless-70cecc414749bcc06fc477bda3cbf83ada667c8e.tar.gz
heapless-70cecc414749bcc06fc477bda3cbf83ada667c8e.tar.zst
heapless-70cecc414749bcc06fc477bda3cbf83ada667c8e.zip
Merge pull request #265 from TDHolmes/cas-fixup
Add cas support for risc-v via atomic-polyfill and fix mpmc/pool documentation
Diffstat (limited to '')
-rw-r--r--CHANGELOG.md4
-rw-r--r--Cargo.toml9
-rw-r--r--build.rs33
-rw-r--r--src/mpmc.rs21
-rw-r--r--src/pool/llsc.rs4
-rw-r--r--src/pool/mod.rs9
-rw-r--r--src/pool/singleton/arc.rs4
-rw-r--r--src/spsc.rs17
8 files changed, 73 insertions, 28 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9e604881..cb0939e7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Added `OldestOrdered` iterator for `HistoryBuffer`
+### Changed
+
+- `atomic-polyfill` is now enabled and used for `cas` atomic emulation on `riscv` targets
+
## [v0.7.9] - 2021-12-16
### Fixed
diff --git a/Cargo.toml b/Cargo.toml
index bfedb936..626365ee 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -33,6 +33,12 @@ scoped_threadpool = "0.1.8"
[target.thumbv6m-none-eabi.dependencies]
atomic-polyfill = { version = "0.1.2", optional = true }
+[target.riscv32i-unknown-none-elf.dependencies]
+atomic-polyfill = { version = "0.1.4", optional = true }
+
+[target.riscv32imc-unknown-none-elf.dependencies]
+atomic-polyfill = { version = "0.1.4", optional = true }
+
[dependencies]
hash32 = "0.2.1"
@@ -58,3 +64,6 @@ version = "0.1"
[dependencies.defmt]
version = ">=0.2.0,<0.4"
optional = true
+
+[package.metadata.docs.rs]
+all-features = true
diff --git a/build.rs b/build.rs
index 094b6cd2..0840d6fb 100644
--- a/build.rs
+++ b/build.rs
@@ -21,10 +21,19 @@ fn main() -> Result<(), Box<dyn Error>> {
println!("cargo:rustc-cfg=armv7a");
}
- // built-in targets with no atomic / CAS support as of nightly-2019-12-17
+ // built-in targets with no atomic / CAS support as of nightly-2022-01-13
+ // AND not supported by the atomic-polyfill crate
// see the `no-atomics.sh` / `no-cas.sh` script sitting next to this file
match &target[..] {
- "msp430-none-elf" | "riscv32i-unknown-none-elf" | "riscv32imc-unknown-none-elf" => {}
+ "avr-unknown-gnu-atmega328"
+ | "bpfeb-unknown-none"
+ | "bpfel-unknown-none"
+ | "msp430-none-elf"
+ // | "riscv32i-unknown-none-elf" // supported by atomic-polyfill
+ // | "riscv32imc-unknown-none-elf" // supported by atomic-polyfill
+ | "thumbv4t-none-eabi"
+ // | "thumbv6m-none-eabi" // supported by atomic-polyfill
+ => {}
_ => {
println!("cargo:rustc-cfg=has_cas");
@@ -32,12 +41,30 @@ fn main() -> Result<(), Box<dyn Error>> {
};
match &target[..] {
- "msp430-none-elf" | "riscv32i-unknown-none-elf" | "riscv32imc-unknown-none-elf" => {}
+ "avr-unknown-gnu-atmega328"
+ | "msp430-none-elf"
+ // | "riscv32i-unknown-none-elf" // supported by atomic-polyfill
+ // | "riscv32imc-unknown-none-elf" // supported by atomic-polyfill
+ => {}
_ => {
println!("cargo:rustc-cfg=has_atomics");
}
};
+ // Let the code know if it should use atomic-polyfill or not, and what aspects
+ // of polyfill it requires
+ match &target[..] {
+ "riscv32i-unknown-none-elf" | "riscv32imc-unknown-none-elf" => {
+ println!("cargo:rustc-cfg=full_atomic_polyfill");
+ println!("cargo:rustc-cfg=cas_atomic_polyfill");
+ }
+
+ "thumbv6m-none-eabi" => {
+ println!("cargo:rustc-cfg=cas_atomic_polyfill");
+ }
+ _ => {}
+ }
+
Ok(())
}
diff --git a/src/mpmc.rs b/src/mpmc.rs
index 0fbf7ce3..91b33311 100644
--- a/src/mpmc.rs
+++ b/src/mpmc.rs
@@ -1,6 +1,7 @@
//! A fixed capacity Multiple-Producer Multiple-Consumer (MPMC) lock-free queue
//!
-//! NOTE: This module is not available on targets that do *not* support CAS operations, e.g. ARMv6-M
+//! NOTE: This module is not available on targets that do *not* support CAS operations and are not
+//! emulated by the [`atomic_polyfill`] crate (e.g., MSP430).
//!
//! # Example
//!
@@ -73,8 +74,10 @@
//!
//! # Portability
//!
-//! This module is not exposed to architectures that lack the instructions to implement CAS loops.
-//! Those architectures include ARMv6-M (`thumbv6m-none-eabi`) and MSP430 (`msp430-none-elf`).
+//! This module requires CAS atomic instructions which are not available on all architectures
+//! (e.g. ARMv6-M (`thumbv6m-none-eabi`) and MSP430 (`msp430-none-elf`)). These atomics can be emulated
+//! however with [`atomic_polyfill`], which is enabled with the `cas` feature and is enabled by default
+//! for `thumbv6m-none-eabi` and `riscv32` targets. MSP430 is currently not supported by [`atomic_polyfill`].
//!
//! # References
//!
@@ -84,18 +87,18 @@
use core::{cell::UnsafeCell, mem::MaybeUninit};
-#[cfg(all(feature = "mpmc_large", not(armv6m)))]
+#[cfg(all(feature = "mpmc_large", not(cas_atomic_polyfill)))]
type AtomicTargetSize = core::sync::atomic::AtomicUsize;
-#[cfg(all(feature = "mpmc_large", armv6m))]
+#[cfg(all(feature = "mpmc_large", cas_atomic_polyfill))]
type AtomicTargetSize = atomic_polyfill::AtomicUsize;
-#[cfg(all(not(feature = "mpmc_large"), not(armv6m)))]
+#[cfg(all(not(feature = "mpmc_large"), not(cas_atomic_polyfill)))]
type AtomicTargetSize = core::sync::atomic::AtomicU8;
-#[cfg(all(not(feature = "mpmc_large"), armv6m))]
+#[cfg(all(not(feature = "mpmc_large"), cas_atomic_polyfill))]
type AtomicTargetSize = atomic_polyfill::AtomicU8;
-#[cfg(not(armv6m))]
+#[cfg(not(cas_atomic_polyfill))]
type Ordering = core::sync::atomic::Ordering;
-#[cfg(armv6m)]
+#[cfg(cas_atomic_polyfill)]
type Ordering = atomic_polyfill::Ordering;
#[cfg(feature = "mpmc_large")]
diff --git a/src/pool/llsc.rs b/src/pool/llsc.rs
index 83081521..33f65557 100644
--- a/src/pool/llsc.rs
+++ b/src/pool/llsc.rs
@@ -3,10 +3,10 @@
pub use core::ptr::NonNull as Ptr;
use core::{cell::UnsafeCell, ptr};
-#[cfg(armv6m)]
+#[cfg(cas_atomic_polyfill)]
use atomic_polyfill::{AtomicPtr, Ordering};
-#[cfg(not(armv6m))]
+#[cfg(not(cas_atomic_polyfill))]
use core::sync::atomic::{AtomicPtr, Ordering};
/// Unfortunate implementation detail required to use the
diff --git a/src/pool/mod.rs b/src/pool/mod.rs
index 15ee5430..65a9c451 100644
--- a/src/pool/mod.rs
+++ b/src/pool/mod.rs
@@ -1,6 +1,7 @@
//! A heap-less, interrupt-safe, lock-free memory pool (\*)
//!
-//! NOTE: This module is not available on targets that do *not* support CAS operations, e.g. ARMv6-M
+//! NOTE: This module is not available on targets that do *not* support CAS operations and are not
+//! emulated by the [`atomic_polyfill`] crate (e.g., MSP430).
//!
//! (\*) Currently, the implementation is only lock-free *and* `Sync` on ARMv6, ARMv7-{A,R,M} & ARMv8-M
//! devices
@@ -59,8 +60,10 @@
//! on the target architecture (see section on ['Soundness'](#soundness) for more information). For
//! this reason, `Pool` only implements `Sync` when compiling for some ARM cores.
//!
-//! Also note that ARMv6-M architecture lacks the primitives for CAS loops so this module does *not*
-//! exist for `thumbv6m-none-eabi`.
+//! This module requires CAS atomic instructions which are not available on all architectures
+//! (e.g. ARMv6-M (`thumbv6m-none-eabi`) and MSP430 (`msp430-none-elf`)). These atomics can be emulated
+//! however with [`atomic_polyfill`], which is enabled with the `cas` feature and is enabled by default
+//! for `thumbv6m-none-eabi` and `riscv32` targets. MSP430 is currently not supported by [`atomic_polyfill`].
//!
//! # Soundness
//!
diff --git a/src/pool/singleton/arc.rs b/src/pool/singleton/arc.rs
index d110817e..a83519d8 100644
--- a/src/pool/singleton/arc.rs
+++ b/src/pool/singleton/arc.rs
@@ -81,10 +81,10 @@ use core::{
sync::atomic,
};
-#[cfg(armv6m)]
+#[cfg(cas_atomic_polyfill)]
use atomic_polyfill::{AtomicUsize, Ordering};
-#[cfg(not(armv6m))]
+#[cfg(not(cas_atomic_polyfill))]
use core::sync::atomic::{AtomicUsize, Ordering};
use crate::pool::{self, stack::Ptr, Node};
diff --git a/src/spsc.rs b/src/spsc.rs
index 2c0a6b44..38990d56 100644
--- a/src/spsc.rs
+++ b/src/spsc.rs
@@ -2,8 +2,8 @@
//!
//! Implementation based on <https://www.codeproject.com/Articles/43510/Lock-Free-Single-Producer-Single-Consumer-Circular>
//!
-//! NOTE: This module is not available on targets that do *not* support atomic loads, e.g. RISC-V
-//! cores w/o the A (Atomic) extension
+//! NOTE: This module is not available on targets that do *not* support atomic loads and are not
+//! supported by [`atomic_polyfill`]. (e.g., MSP430).
//!
//! # Examples
//!
@@ -84,13 +84,12 @@
//! - The numbers reported correspond to the successful path (i.e. `Some` is returned by `dequeue`
//! and `Ok` is returned by `enqueue`).
-use core::{
- cell::UnsafeCell,
- fmt, hash,
- mem::MaybeUninit,
- ptr,
- sync::atomic::{AtomicUsize, Ordering},
-};
+use core::{cell::UnsafeCell, fmt, hash, mem::MaybeUninit, ptr};
+
+#[cfg(full_atomic_polyfill)]
+use atomic_polyfill::{AtomicUsize, Ordering};
+#[cfg(not(full_atomic_polyfill))]
+use core::sync::atomic::{AtomicUsize, Ordering};
/// A statically allocated single producer single consumer queue with a capacity of `N - 1` elements
///