Skip to content

Commit

Permalink
Use portable-atomic instead of atomic-polyfill.
Browse files Browse the repository at this point in the history
  • Loading branch information
Dirbaio committed Dec 23, 2022
1 parent 188f94d commit 1001759
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 56 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,10 @@ jobs:
target: ${{ matrix.target }}
override: true

- name: Export variables
run: |
echo RUSTFLAGS="--cfg=portable_atomic_unsafe_assume_single_core" >> $GITHUB_ENV
- name: cargo check
uses: actions-rs/cargo@v1
with:
Expand Down
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- [breaking-change] changed the target support of memory pool API to only support 32-bit x86 and a
subset of ARM targets. See the module level documentation of the `pool` module for details

- [breaking-change] this crate now depends on `atomic-polyfill` v1.0.1, meaning that targets that
require a polyfill need a `critical-section` **v1.x.x** implementation.
- [breaking-change] this crate now uses `portable-atomic` v0.3 instead of `atomic-polyfill` for emulating
CAS instructions on targets where they're not natively available.

### Fixed

Expand Down
13 changes: 8 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ version = "0.8.0"

[features]
default = ["cas"]
cas = ["atomic-polyfill"]
cas = ["portable-atomic"]
ufmt-impl = ["ufmt-write"]
# only for tests
__trybuild = []
Expand All @@ -26,16 +26,19 @@ mpmc_large = []
defmt-impl = ["defmt"]

[target.thumbv6m-none-eabi.dependencies]
atomic-polyfill = { version = "1.0.1", optional = true }
portable-atomic = { version = "0.3.18", optional = true }

[target.riscv32i-unknown-none-elf.dependencies]
atomic-polyfill = { version = "1.0.1" }
portable-atomic = { version = "0.3.18" }

[target.riscv32imc-unknown-none-elf.dependencies]
atomic-polyfill = { version = "1.0.1" }
portable-atomic = { version = "0.3.18" }

[target.msp430-none-elf.dependencies]
portable-atomic = { version = "0.3.18" }

[target.'cfg(target_arch = "avr")'.dependencies]
atomic-polyfill = { version = "1.0.1", optional = true }
portable-atomic = { version = "0.3.18", optional = true }

[dependencies]
hash32 = "0.3.0"
Expand Down
48 changes: 24 additions & 24 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,14 @@ fn main() -> Result<(), Box<dyn Error>> {

let is_avr = env::var("CARGO_CFG_TARGET_ARCH").as_deref() == Ok("avr");

// Set some cfg's depending on the target.
// - has_atomics: atomic load/store is available (either natively or through portable-atomic)
// - has_cas: atomic CAS is available (either natively or through portable-atomic)
// - use_portable_atomic: Use portable-atomic for all atomics (load/store and CAS).
// - use_portable_atomic_cas: Use portable-atomic for CAS atomic operations. Load/store can keep using core::sync:atomic.

// built-in targets with no atomic / CAS support as of nightly-2022-01-13
// AND not supported by the atomic-polyfill crate
// AND not supported by the portable-atomic crate
// see the `no-atomics.sh` / `no-cas.sh` script sitting next to this file
if is_avr {
// lacks cas
Expand All @@ -41,11 +47,11 @@ fn main() -> Result<(), Box<dyn Error>> {
"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
// | "msp430-none-elf" // supported by portable-atomic
// | "riscv32i-unknown-none-elf" // supported by portable-atomic
// | "riscv32imc-unknown-none-elf" // supported by portable-atomic
// | "thumbv4t-none-eabi" // supported by portable-atomic
// | "thumbv6m-none-eabi" // supported by portable-atomic
=> {}

_ => {
Expand All @@ -57,32 +63,26 @@ fn main() -> Result<(), Box<dyn Error>> {
if is_avr {
// lacks atomics
} else {
match &target[..] {
"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");
}
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
// Let the code know if it should use portable-atomic or not, for either
// only CAS, or for all atomics.
if is_avr {
println!("cargo:rustc-cfg=full_atomic_polyfill");
println!("cargo:rustc-cfg=cas_atomic_polyfill");
println!("cargo:rustc-cfg=use_portable_atomic");
println!("cargo:rustc-cfg=use_portable_atomic_cas");
} else {
match &target[..] {
"riscv32i-unknown-none-elf" | "riscv32imc-unknown-none-elf" => {
println!("cargo:rustc-cfg=full_atomic_polyfill");
println!("cargo:rustc-cfg=cas_atomic_polyfill");
"riscv32i-unknown-none-elf"
| "riscv32imc-unknown-none-elf"
| "thumbv4t-none-eabi"
| "msp430-none-elf" => {
println!("cargo:rustc-cfg=use_portable_atomic");
println!("cargo:rustc-cfg=use_portable_atomic_cas");
}

"thumbv6m-none-eabi" => {
println!("cargo:rustc-cfg=cas_atomic_polyfill");
println!("cargo:rustc-cfg=use_portable_atomic_cas");
}
_ => {}
}
Expand Down
34 changes: 15 additions & 19 deletions src/mpmc.rs
Original file line number Diff line number Diff line change
@@ -1,8 +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 and are not
//! emulated by the [`atomic_polyfill`](https://crates.io/crates/atomic-polyfill) crate (e.g.,
//! MSP430).
//! NOTE: This module requires atomic CAS operations. On targets where they're not natively available,
//! they are emulated by the [`portable-atomic`](https://crates.io/crates/portable-atomic) crate.
//!
//! # Example
//!
Expand Down Expand Up @@ -77,10 +76,9 @@
//!
//! 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`](https://crates.io/crates/atomic-polyfill), which is
//! emulated however with [`portable-atomic`](https://crates.io/crates/portable-atomic), 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`](https://crates.io/crates/atomic-polyfill).
//! targets.
//!
//! # References
//!
Expand All @@ -90,19 +88,17 @@

use core::{cell::UnsafeCell, mem::MaybeUninit};

#[cfg(all(feature = "mpmc_large", not(cas_atomic_polyfill)))]
type AtomicTargetSize = core::sync::atomic::AtomicUsize;
#[cfg(all(feature = "mpmc_large", cas_atomic_polyfill))]
type AtomicTargetSize = atomic_polyfill::AtomicUsize;
#[cfg(all(not(feature = "mpmc_large"), not(cas_atomic_polyfill)))]
type AtomicTargetSize = core::sync::atomic::AtomicU8;
#[cfg(all(not(feature = "mpmc_large"), cas_atomic_polyfill))]
type AtomicTargetSize = atomic_polyfill::AtomicU8;

#[cfg(not(cas_atomic_polyfill))]
type Ordering = core::sync::atomic::Ordering;
#[cfg(cas_atomic_polyfill)]
type Ordering = atomic_polyfill::Ordering;
#[cfg(not(use_portable_atomic_cas))]
use core::sync::atomic;
#[cfg(use_portable_atomic_cas)]
use portable_atomic as atomic;

use atomic::Ordering;

#[cfg(feature = "mpmc_large")]
type AtomicTargetSize = atomic::AtomicUsize;
#[cfg(not(feature = "mpmc_large"))]
type AtomicTargetSize = atomic::AtomicU8;

#[cfg(feature = "mpmc_large")]
type IntSize = usize;
Expand Down
19 changes: 13 additions & 6 deletions src/spsc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,13 @@
//!
//! 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 and are not
//! supported by [`atomic_polyfill`](https://crates.io/crates/atomic-polyfill). (e.g., MSP430).
//! # Portability
//!
//! 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 [`portable-atomic`](https://crates.io/crates/portable-atomic), which is
//! enabled with the `cas` feature and is enabled by default for `thumbv6m-none-eabi` and `riscv32`
//! targets.
//!
//! # Examples
//!
Expand Down Expand Up @@ -91,10 +96,12 @@

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};
#[cfg(not(use_portable_atomic))]
use core::sync::atomic;
#[cfg(use_portable_atomic)]
use portable_atomic as atomic;

use atomic::{AtomicUsize, Ordering};

/// A statically allocated single producer single consumer queue with a capacity of `N - 1` elements
///
Expand Down

0 comments on commit 1001759

Please sign in to comment.