Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .cirrus.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ env:
RUST_BACKTRACE: '1'
RUST_TEST_THREADS: '1'
RUSTDOCFLAGS: -D warnings
RUSTFLAGS: -D warnings
RUSTFLAGS: -D warnings --cfg portable_atomic_unstable_f16 --cfg quickcheck_unstable_f16 --cfg rand_unstable_f16 --cfg portable_atomic_unstable_f128 --cfg quickcheck_unstable_f128 --cfg rand_unstable_f128
RUSTUP_MAX_RETRIES: '10'
PORTABLE_ATOMIC_DENY_WARNINGS: '1'

Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,12 @@ jobs:
# TODO: LLVM bug: Undefined temporary symbol error when building std.
- run: printf 'RELEASE=--release\n' >>"${GITHUB_ENV}"
if: startsWith(matrix.target, 'mips-') || startsWith(matrix.target, 'mipsel-')
# for f16 and f128
# https://github.com/rust-lang/compiler-builtins/blob/compiler_builtins-v0.1.142/configure.rs#L60
- run: printf '%s\n' "RUSTFLAGS=${RUSTFLAGS} --cfg portable_atomic_unstable_f16 --cfg quickcheck_unstable_f16 --cfg rand_unstable_f16" >>"${GITHUB_ENV}"
if: matrix.rust == 'nightly' && !(startsWith(matrix.target, 'arm64ec') || startsWith(matrix.target, 'csky') || startsWith(matrix.target, 'hexagon') || startsWith(matrix.target, 'i586') || startsWith(matrix.target, 'i686') || startsWith(matrix.target, 'loongarch64') || startsWith(matrix.target, 'mips') || startsWith(matrix.target, 'powerpc') || startsWith(matrix.target, 's390x') || startsWith(matrix.target, 'sparc') || startsWith(matrix.target, 'wasm') || contains(matrix.flags, 'codegen-backend=cranelift'))
- run: printf '%s\n' "RUSTFLAGS=${RUSTFLAGS} --cfg portable_atomic_unstable_f128 --cfg quickcheck_unstable_f128 --cfg rand_unstable_f128" >>"${GITHUB_ENV}"
if: matrix.rust == 'nightly' && !(startsWith(matrix.target, 'arm64ec') || startsWith(matrix.target, 'i586') || startsWith(matrix.target, 'i686') || startsWith(matrix.target, 'mips64') || startsWith(matrix.target, 'mipsisa64') || startsWith(matrix.target, 'powerpc-') || startsWith(matrix.target, 'powerpc64-') || startsWith(matrix.target, 'sparc') || contains(matrix.flags, 'codegen-backend=cranelift'))
# for serde
- run: printf '%s\n' "RUSTFLAGS=${RUSTFLAGS} --cfg no_diagnostic_namespace" >>"${GITHUB_ENV}"
if: matrix.rust == 'nightly-2024-02-13'
Expand Down
5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Portable atomic types including support for 128-bit atomics, atomic float, etc.
# - env.TEST_FEATURES in .github/workflows/ci.yml.
# - test_features list in tools/build.sh and tools/test.sh.
features = ["float", "std", "serde", "critical-section"]
rustdoc-args = ["--cfg", "portable_atomic_unstable_f16", "--cfg", "portable_atomic_unstable_f128"]
targets = ["x86_64-unknown-linux-gnu"]

[package.metadata.cargo_check_external_types]
Expand Down Expand Up @@ -132,8 +133,8 @@ unexpected_cfgs = { level = "warn", check-cfg = [
# Known custom cfgs, excluding those that may be set by build script.
# Not public API.
'cfg(portable_atomic_test_outline_atomics_detect_false,qemu,valgrind)',
# Public APIs, considered unstable unless documented in readme.
'cfg(portable_atomic_no_outline_atomics,portable_atomic_outline_atomics)',
# Public APIs, considered unstable unless documented as stable in readme.
'cfg(portable_atomic_no_outline_atomics,portable_atomic_outline_atomics,portable_atomic_unstable_f16,portable_atomic_unstable_f128)',
# Public unstable API(s) - portable-atomic-util
'cfg(portable_atomic_unstable_coerce_unsized)',
] }
Expand Down
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Portable atomic types including support for 128-bit atomics, atomic float, etc.
- Provide all atomic integer types (`Atomic{I,U}{8,16,32,64}`) for all targets that can use atomic CAS. (i.e., all targets that can use `std`, and most no-std targets)
- Provide `AtomicI128` and `AtomicU128`.
- Provide `AtomicF32` and `AtomicF64`. ([optional, requires the `float` feature](#optional-features-float))
- Provide `AtomicF16` and `AtomicF128` for [unstable `f16` and `f128`](https://github.com/rust-lang/rust/issues/116909). ([optional, requires the `float` feature and unstable cfgs](#optional-features-float))
- Provide atomic load/store for targets where atomic is not available at all in the standard library. (RISC-V without A-extension, MSP430, AVR)
- Provide atomic CAS for targets where atomic CAS is not available in the standard library. (thumbv6m, pre-v6 Arm, RISC-V without A-extension, MSP430, AVR, Xtensa, etc.) (always enabled for MSP430 and AVR, [optional](#optional-features-critical-section) otherwise)
- Provide stable equivalents of the standard library's atomic types' unstable APIs, such as [`AtomicPtr::fetch_*`](https://github.com/rust-lang/rust/issues/99108).
Expand Down Expand Up @@ -70,7 +71,12 @@ See the [`atomic128` module's readme](https://github.com/taiki-e/portable-atomic
- <a name="optional-features-float"></a>**`float`**<br>
Provide `AtomicF{32,64}`.

Note that most of `fetch_*` operations of atomic floats are implemented using CAS loops, which can be slower than equivalent operations of atomic integers. ([GPU targets have atomic instructions for float, so we plan to use these instructions for GPU targets in the future.](https://github.com/taiki-e/portable-atomic/issues/34))
- When unstable `--cfg portable_atomic_unstable_f16` is also enabled, `AtomicF16` for [unstable `f16`](https://github.com/rust-lang/rust/issues/116909) is also provided.
- When unstable `--cfg portable_atomic_unstable_f128` is also enabled, `AtomicF128` for [unstable `f128`](https://github.com/rust-lang/rust/issues/116909) is also provided.

Note:
- Most of `fetch_*` operations of atomic floats are implemented using CAS loops, which can be slower than equivalent operations of atomic integers. (AArch64 with FEAT_LSFE and GPU targets have atomic instructions for float, [so we plan to use these instructions for them in the future.](https://github.com/taiki-e/portable-atomic/issues/34))
- Unstable cfgs are outside of the normal semver guarantees and minor or patch versions of portable-atomic may make breaking changes to them at any time.

- **`std`**<br>
Use `std`.
Expand Down
8 changes: 8 additions & 0 deletions src/imp/float/int.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,9 +199,17 @@ macro_rules! atomic_float {
};
}

#[cfg(portable_atomic_unstable_f16)]
cfg_has_atomic_16! {
atomic_float!(AtomicF16, f16, AtomicU16, u16, 2);
}
cfg_has_atomic_32! {
atomic_float!(AtomicF32, f32, AtomicU32, u32, 4);
}
cfg_has_atomic_64! {
atomic_float!(AtomicF64, f64, AtomicU64, u64, 8);
}
#[cfg(portable_atomic_unstable_f128)]
cfg_has_atomic_128! {
atomic_float!(AtomicF128, f128, AtomicU128, u128, 16);
}
8 changes: 8 additions & 0 deletions src/imp/float/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,17 @@ Atomic float implementations

mod int;

#[cfg(portable_atomic_unstable_f16)]
cfg_has_atomic_16! {
pub(crate) use self::int::AtomicF16;
}
cfg_has_atomic_32! {
pub(crate) use self::int::AtomicF32;
}
cfg_has_atomic_64! {
pub(crate) use self::int::AtomicF64;
}
#[cfg(portable_atomic_unstable_f128)]
cfg_has_atomic_128! {
pub(crate) use self::int::AtomicF128;
}
29 changes: 20 additions & 9 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Portable atomic types including support for 128-bit atomics, atomic float, etc.
- Provide all atomic integer types (`Atomic{I,U}{8,16,32,64}`) for all targets that can use atomic CAS. (i.e., all targets that can use `std`, and most no-std targets)
- Provide `AtomicI128` and `AtomicU128`.
- Provide `AtomicF32` and `AtomicF64`. ([optional, requires the `float` feature](#optional-features-float))
- Provide `AtomicF16` and `AtomicF128` for [unstable `f16` and `f128`](https://github.com/rust-lang/rust/issues/116909). ([optional, requires the `float` feature and unstable cfgs](#optional-features-float))
- Provide atomic load/store for targets where atomic is not available at all in the standard library. (RISC-V without A-extension, MSP430, AVR)
- Provide atomic CAS for targets where atomic CAS is not available in the standard library. (thumbv6m, pre-v6 Arm, RISC-V without A-extension, MSP430, AVR, Xtensa, etc.) (always enabled for MSP430 and AVR, [optional](#optional-features-critical-section) otherwise)
- Provide stable equivalents of the standard library's atomic types' unstable APIs, such as [`AtomicPtr::fetch_*`](https://github.com/rust-lang/rust/issues/99108).
Expand Down Expand Up @@ -64,7 +65,12 @@ See the [`atomic128` module's readme](https://github.com/taiki-e/portable-atomic
- <a name="optional-features-float"></a>**`float`**<br>
Provide `AtomicF{32,64}`.

Note that most of `fetch_*` operations of atomic floats are implemented using CAS loops, which can be slower than equivalent operations of atomic integers. ([GPU targets have atomic instructions for float, so we plan to use these instructions for GPU targets in the future.](https://github.com/taiki-e/portable-atomic/issues/34))
- When unstable `--cfg portable_atomic_unstable_f16` is also enabled, `AtomicF16` for [unstable `f16`](https://github.com/rust-lang/rust/issues/116909) is also provided.
- When unstable `--cfg portable_atomic_unstable_f128` is also enabled, `AtomicF128` for [unstable `f128`](https://github.com/rust-lang/rust/issues/116909) is also provided.

Note:
- Most of `fetch_*` operations of atomic floats are implemented using CAS loops, which can be slower than equivalent operations of atomic integers. (AArch64 with FEAT_LSFE and GPU targets have atomic instructions for float, [so we plan to use these instructions for them in the future.](https://github.com/taiki-e/portable-atomic/issues/34))
- Unstable cfgs are outside of the normal semver guarantees and minor or patch versions of portable-atomic may make breaking changes to them at any time.

- **`std`**<br>
Use `std`.
Expand Down Expand Up @@ -230,6 +236,10 @@ RUSTFLAGS="--cfg portable_atomic_no_outline_atomics" cargo ...
),
feature(asm_experimental_arch)
)]
// f16/f128
// cfg is unstable and explicitly enabled by the user
#![cfg_attr(portable_atomic_unstable_f16, feature(f16))]
#![cfg_attr(portable_atomic_unstable_f128, feature(f128))]
// Old nightly only
// These features are already stabilized or have already been removed from compilers,
// and can safely be enabled for old nightly as long as version detection works.
Expand Down Expand Up @@ -4115,12 +4125,15 @@ assert_eq!(foo.load(Ordering::Relaxed), 5);
} // cfg_no_atomic_cas!
$(
#[$cfg_float]
atomic_int!(float, $atomic_float_type, $float_type, $atomic_type, $int_type, $align);
atomic_int!(float,
#[$cfg_float] $atomic_float_type, $float_type, $atomic_type, $int_type, $align
);
)?
};

// AtomicF* impls
(float,
#[$cfg_float:meta]
$atomic_type:ident,
$float_type:ident,
$atomic_int_type:ident,
Expand All @@ -4134,7 +4147,7 @@ This type has the same in-memory representation as the underlying floating point
[`", stringify!($float_type), "`].
"
),
#[cfg_attr(docsrs, doc(cfg(feature = "float")))]
#[cfg_attr(docsrs, doc($cfg_float))]
// We can use #[repr(transparent)] here, but #[repr(C, align(N))]
// will show clearer docs.
#[repr(C, align($align))]
Expand Down Expand Up @@ -4754,9 +4767,8 @@ cfg_has_atomic_8! {
}
cfg_has_atomic_16! {
atomic_int!(AtomicI16, i16, 2, cfg_has_atomic_cas_or_amo8, cfg_no_atomic_cas_or_amo8);
atomic_int!(AtomicU16, u16, 2, cfg_has_atomic_cas_or_amo8, cfg_no_atomic_cas_or_amo8);
// TODO: support once https://github.com/rust-lang/rust/issues/116909 stabilized.
// #[cfg(all(feature = "float", not(portable_atomic_no_f16)))] AtomicF16, f16);
atomic_int!(AtomicU16, u16, 2, cfg_has_atomic_cas_or_amo8, cfg_no_atomic_cas_or_amo8,
#[cfg(all(feature = "float", portable_atomic_unstable_f16))] AtomicF16, f16);
}
cfg_has_atomic_32! {
atomic_int!(AtomicI32, i32, 4, cfg_has_atomic_cas_or_amo32, cfg_no_atomic_cas_or_amo32);
Expand All @@ -4770,9 +4782,8 @@ cfg_has_atomic_64! {
}
cfg_has_atomic_128! {
atomic_int!(AtomicI128, i128, 16, cfg_has_atomic_cas_or_amo32, cfg_no_atomic_cas_or_amo32);
atomic_int!(AtomicU128, u128, 16, cfg_has_atomic_cas_or_amo32, cfg_no_atomic_cas_or_amo32);
// TODO: support once https://github.com/rust-lang/rust/issues/116909 stabilized.
// #[cfg(all(feature = "float", not(portable_atomic_no_f128)))] AtomicF128, f128);
atomic_int!(AtomicU128, u128, 16, cfg_has_atomic_cas_or_amo32, cfg_no_atomic_cas_or_amo32,
#[cfg(all(feature = "float", portable_atomic_unstable_f128))] AtomicF128, f128);
}

// See https://github.com/taiki-e/portable-atomic/issues/180
Expand Down
68 changes: 67 additions & 1 deletion src/tests/helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1014,6 +1014,18 @@ macro_rules! __test_atomic_float {
}
#[test]
fn fetch_max() {
if mem::size_of::<$float_type>() == 16
&& cfg!(any(
target_arch = "arm",
target_arch = "mips",
target_arch = "mips32r6",
target_vendor = "apple",
windows,
))
{
// TODO(f128):
return;
}
let a = <$atomic_type>::new(23.);
test_swap_ordering(|order| a.fetch_max(23., order));
for &order in &helper::SWAP_ORDERINGS {
Expand All @@ -1026,6 +1038,18 @@ macro_rules! __test_atomic_float {
}
#[test]
fn fetch_min() {
if mem::size_of::<$float_type>() == 16
&& cfg!(any(
target_arch = "arm",
target_arch = "mips",
target_arch = "mips32r6",
target_vendor = "apple",
windows,
))
{
// TODO(f128):
return;
}
let a = <$atomic_type>::new(23.);
test_swap_ordering(|order| a.fetch_min(23., order));
for &order in &helper::SWAP_ORDERINGS {
Expand Down Expand Up @@ -1071,7 +1095,7 @@ macro_rules! __test_atomic_float {
}
fn quickcheck_compare_exchange(x: $float_type, y: $float_type) -> bool {
let z = loop {
let z = fastrand::$float_type();
let z = float_rand::$float_type();
if z != y {
break z;
}
Expand Down Expand Up @@ -1119,6 +1143,18 @@ macro_rules! __test_atomic_float {
true
}
fn quickcheck_fetch_max(x: $float_type, y: $float_type) -> bool {
if mem::size_of::<$float_type>() == 16
&& cfg!(any(
target_arch = "arm",
target_arch = "mips",
target_arch = "mips32r6",
target_vendor = "apple",
windows,
))
{
// TODO(f128):
return true;
}
for &order in &helper::SWAP_ORDERINGS {
let a = <$atomic_type>::new(x);
assert_float_op_eq!(a.fetch_max(y, order), x);
Expand All @@ -1130,6 +1166,18 @@ macro_rules! __test_atomic_float {
true
}
fn quickcheck_fetch_min(x: $float_type, y: $float_type) -> bool {
if mem::size_of::<$float_type>() == 16
&& cfg!(any(
target_arch = "arm",
target_arch = "mips",
target_arch = "mips32r6",
target_vendor = "apple",
windows,
))
{
// TODO(f128):
return true;
}
for &order in &helper::SWAP_ORDERINGS {
let a = <$atomic_type>::new(x);
assert_float_op_eq!(a.fetch_min(y, order), x);
Expand Down Expand Up @@ -2513,3 +2561,21 @@ macro_rules! stress_test {
}
};
}

#[cfg(feature = "float")]
pub(crate) mod float_rand {
#[cfg(portable_atomic_unstable_f16)]
pub(crate) fn f16() -> f16 {
f16::from_bits(fastrand::u16(..))
}
pub(crate) fn f32() -> f32 {
f32::from_bits(fastrand::u32(..))
}
pub(crate) fn f64() -> f64 {
f64::from_bits(fastrand::u64(..))
}
#[cfg(portable_atomic_unstable_f128)]
pub(crate) fn f128() -> f128 {
f128::from_bits(fastrand::u128(..))
}
}
Loading