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 Oct 30, 2023
1 parent 9094278 commit 8f6dc81
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 58 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ jobs:
- nightly
features:
- ""
- "cas"
- "cas,portable-atomic/critical-section"
- "serde"
steps:
- name: Checkout
Expand Down
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- [breaking-change] export `IndexMapKeys`, `IndexMapValues` and
`IndexMapValuesMut` iterator types.

- [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` v1.0 instead of `atomic-polyfill` for emulating
CAS instructions on targets where they're not natively available.

### Fixed

Expand Down
15 changes: 9 additions & 6 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,19 +26,22 @@ mpmc_large = []
defmt-impl = ["defmt"]

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

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

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

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

[target.xtensa-esp32s2-none-elf.dependencies]
atomic-polyfill = { version = "1.0.1" }
portable-atomic = { version = "1.0", optional = true }

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

[dependencies]
hash32 = "0.3.0"
Expand Down
47 changes: 23 additions & 24 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,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 @@ -39,11 +45,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 @@ -55,34 +61,27 @@ 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"
| "xtensa-esp32s2-none-elf" => {
println!("cargo:rustc-cfg=full_atomic_polyfill");
println!("cargo:rustc-cfg=cas_atomic_polyfill");
| "xtensa-esp32s2-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 8f6dc81

Please sign in to comment.