diff options
| author | 2022-01-19 14:59:12 +0100 | |
|---|---|---|
| committer | 2022-01-19 14:59:12 +0100 | |
| commit | 70cecc414749bcc06fc477bda3cbf83ada667c8e (patch) | |
| tree | 115527275db30a7f385347b933bb2b1eeef22b78 | |
| parent | 7546c64e791e7d8f67d12b0a9fc74031ec1b8cba (diff) | |
| parent | bc9e208089a415f0400f88ba4a8bfd20d955e317 (diff) | |
| download | heapless-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.md | 4 | ||||
| -rw-r--r-- | Cargo.toml | 9 | ||||
| -rw-r--r-- | build.rs | 33 | ||||
| -rw-r--r-- | src/mpmc.rs | 21 | ||||
| -rw-r--r-- | src/pool/llsc.rs | 4 | ||||
| -rw-r--r-- | src/pool/mod.rs | 9 | ||||
| -rw-r--r-- | src/pool/singleton/arc.rs | 4 | ||||
| -rw-r--r-- | src/spsc.rs | 17 |
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 @@ -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 @@ -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 /// |
