diff --git a/.cirrus.yml b/.cirrus.yml
index b70ab9a81..2f7a1d790 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -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'
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index df1a93a61..960b297ca 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -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'
diff --git a/Cargo.toml b/Cargo.toml
index 1037930e6..ff86f32e8 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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]
@@ -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)',
] }
diff --git a/README.md b/README.md
index 329fc8762..86fa52d56 100644
--- a/README.md
+++ b/README.md
@@ -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).
@@ -70,7 +71,12 @@ See the [`atomic128` module's readme](https://github.com/taiki-e/portable-atomic
- **`float`**
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`**
Use `std`.
diff --git a/src/imp/float/int.rs b/src/imp/float/int.rs
index 61f5b5844..bda88364c 100644
--- a/src/imp/float/int.rs
+++ b/src/imp/float/int.rs
@@ -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);
+}
diff --git a/src/imp/float/mod.rs b/src/imp/float/mod.rs
index afc89032b..a36f0983d 100644
--- a/src/imp/float/mod.rs
+++ b/src/imp/float/mod.rs
@@ -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;
+}
diff --git a/src/lib.rs b/src/lib.rs
index 6501e208f..26e28e1b9 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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).
@@ -64,7 +65,12 @@ See the [`atomic128` module's readme](https://github.com/taiki-e/portable-atomic
- **`float`**
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`**
Use `std`.
@@ -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.
@@ -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,
@@ -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))]
@@ -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);
@@ -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
diff --git a/src/tests/helper.rs b/src/tests/helper.rs
index 364a5b8c8..e98f8ec2b 100644
--- a/src/tests/helper.rs
+++ b/src/tests/helper.rs
@@ -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 {
@@ -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 {
@@ -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;
}
@@ -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);
@@ -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);
@@ -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(..))
+ }
+}
diff --git a/src/tests/mod.rs b/src/tests/mod.rs
index 38c63438d..553f7ab58 100644
--- a/src/tests/mod.rs
+++ b/src/tests/mod.rs
@@ -35,10 +35,14 @@ test_atomic_int_pub!(u64);
test_atomic_int_pub!(i128);
test_atomic_int_pub!(u128);
+#[cfg(all(feature = "float", portable_atomic_unstable_f16))]
+test_atomic_float_pub!(f16);
#[cfg(feature = "float")]
test_atomic_float_pub!(f32);
#[cfg(feature = "float")]
test_atomic_float_pub!(f64);
+#[cfg(all(feature = "float", portable_atomic_unstable_f128))]
+test_atomic_float_pub!(f128);
#[deny(improper_ctypes)]
extern "C" {
@@ -54,15 +58,17 @@ extern "C" {
fn _atomic_u32_ffi_safety(_: AtomicU32);
fn _atomic_i64_ffi_safety(_: AtomicI64);
fn _atomic_u64_ffi_safety(_: AtomicU64);
- // TODO: 128-bit integers are not FFI safe
- // https://github.com/rust-lang/unsafe-code-guidelines/issues/119
- // https://github.com/rust-lang/rust/issues/54341
+ // TODO: https://github.com/rust-lang/lang-team/issues/255
// fn _atomic_i128_ffi_safety(_: AtomicI128);
// fn _atomic_u128_ffi_safety(_: AtomicU128);
+ #[cfg(all(feature = "float", portable_atomic_unstable_f16))]
+ fn _atomic_f16_ffi_safety(_: AtomicF16);
#[cfg(feature = "float")]
fn _atomic_f32_ffi_safety(_: AtomicF32);
#[cfg(feature = "float")]
fn _atomic_f64_ffi_safety(_: AtomicF64);
+ #[cfg(all(feature = "float", portable_atomic_unstable_f128))]
+ fn _atomic_f128_ffi_safety(_: AtomicF128);
}
#[test]
@@ -75,10 +81,18 @@ fn test_is_lock_free() {
assert!(AtomicI16::is_lock_free());
assert!(AtomicU16::is_always_lock_free());
assert!(AtomicU16::is_lock_free());
+ #[cfg(all(feature = "float", portable_atomic_unstable_f16))]
+ assert!(AtomicF16::is_always_lock_free());
+ #[cfg(all(feature = "float", portable_atomic_unstable_f16))]
+ assert!(AtomicF16::is_lock_free());
assert!(AtomicI32::is_always_lock_free());
assert!(AtomicI32::is_lock_free());
assert!(AtomicU32::is_always_lock_free());
assert!(AtomicU32::is_lock_free());
+ #[cfg(feature = "float")]
+ assert!(AtomicF32::is_always_lock_free());
+ #[cfg(feature = "float")]
+ assert!(AtomicF32::is_lock_free());
#[cfg(not(portable_atomic_no_cfg_target_has_atomic))]
{
if cfg!(any(
@@ -97,6 +111,10 @@ fn test_is_lock_free() {
assert!(AtomicI64::is_lock_free());
assert!(AtomicU64::is_always_lock_free());
assert!(AtomicU64::is_lock_free());
+ #[cfg(feature = "float")]
+ assert!(AtomicF64::is_always_lock_free());
+ #[cfg(feature = "float")]
+ assert!(AtomicF64::is_lock_free());
} else if cfg!(all(
feature = "fallback",
target_arch = "arm",
@@ -110,15 +128,23 @@ fn test_is_lock_free() {
)) {
assert!(!AtomicI64::is_always_lock_free());
assert!(!AtomicU64::is_always_lock_free());
+ #[cfg(feature = "float")]
+ assert!(!AtomicF64::is_always_lock_free());
assert!(AtomicI64::is_lock_free());
assert!(AtomicU64::is_lock_free());
+ #[cfg(feature = "float")]
+ assert!(AtomicF64::is_lock_free());
} else {
assert!(!AtomicI64::is_always_lock_free());
assert!(!AtomicU64::is_always_lock_free());
+ #[cfg(feature = "float")]
+ assert!(!AtomicF64::is_always_lock_free());
#[cfg(not(target_arch = "riscv32"))]
{
assert!(!AtomicI64::is_lock_free());
assert!(!AtomicU64::is_lock_free());
+ #[cfg(feature = "float")]
+ assert!(!AtomicF64::is_lock_free());
}
#[cfg(target_arch = "riscv32")]
{
@@ -131,6 +157,10 @@ fn test_is_lock_free() {
assert!(!AtomicI128::is_lock_free());
assert!(!AtomicU128::is_always_lock_free());
assert!(!AtomicU128::is_lock_free());
+ #[cfg(all(feature = "float", portable_atomic_unstable_f128))]
+ assert!(!AtomicF128::is_always_lock_free());
+ #[cfg(all(feature = "float", portable_atomic_unstable_f128))]
+ assert!(!AtomicF128::is_lock_free());
} else if cfg!(any(
target_arch = "aarch64",
all(target_arch = "arm64ec", not(portable_atomic_no_asm)),
@@ -159,9 +189,15 @@ fn test_is_lock_free() {
assert!(AtomicI128::is_lock_free());
assert!(AtomicU128::is_always_lock_free());
assert!(AtomicU128::is_lock_free());
+ #[cfg(all(feature = "float", portable_atomic_unstable_f128))]
+ assert!(AtomicF128::is_always_lock_free());
+ #[cfg(all(feature = "float", portable_atomic_unstable_f128))]
+ assert!(AtomicF128::is_lock_free());
} else {
assert!(!AtomicI128::is_always_lock_free());
assert!(!AtomicU128::is_always_lock_free());
+ #[cfg(all(feature = "float", portable_atomic_unstable_f128))]
+ assert!(!AtomicF128::is_always_lock_free());
#[cfg(not(any(
target_arch = "x86_64",
target_arch = "powerpc64",
@@ -170,6 +206,8 @@ fn test_is_lock_free() {
{
assert!(!AtomicI128::is_lock_free());
assert!(!AtomicU128::is_lock_free());
+ #[cfg(all(feature = "float", portable_atomic_unstable_f128))]
+ assert!(!AtomicF128::is_lock_free());
}
#[cfg(target_arch = "x86_64")]
{
@@ -181,6 +219,8 @@ fn test_is_lock_free() {
)) && std::is_x86_feature_detected!("cmpxchg16b");
assert_eq!(AtomicI128::is_lock_free(), has_cmpxchg16b);
assert_eq!(AtomicU128::is_lock_free(), has_cmpxchg16b);
+ #[cfg(all(feature = "float", portable_atomic_unstable_f128))]
+ assert_eq!(AtomicF128::is_lock_free(), has_cmpxchg16b);
}
#[cfg(target_arch = "powerpc64")]
{
@@ -425,6 +465,7 @@ fn test_serde() {
t!(AtomicU64, u64, U64);
t!(AtomicI128, i128, I128);
t!(AtomicU128, u128, U128);
+ // TODO(f16_and_f128): Test f16 & f128 once stabilized.
#[cfg(feature = "float")]
t!(AtomicF32, f32, F32);
#[cfg(feature = "float")]
diff --git a/src/utils.rs b/src/utils.rs
index c4ab2d91f..d22a8c1d3 100644
--- a/src/utils.rs
+++ b/src/utils.rs
@@ -134,14 +134,15 @@ macro_rules! const_fn {
/// Implements `core::fmt::Debug` and `serde::{Serialize, Deserialize}` (when serde
/// feature is enabled) for atomic bool, integer, or float.
macro_rules! impl_debug_and_serde {
+ // TODO(f16_and_f128): Implement serde traits for f16 & f128 once stabilized.
+ (AtomicF16) => {
+ impl_debug!(AtomicF16);
+ };
+ (AtomicF128) => {
+ impl_debug!(AtomicF128);
+ };
($atomic_type:ident) => {
- impl fmt::Debug for $atomic_type {
- #[inline] // fmt is not hot path, but #[inline] on fmt seems to still be useful: https://github.com/rust-lang/rust/pull/117727
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- // std atomic types use Relaxed in Debug::fmt: https://github.com/rust-lang/rust/blob/1.80.0/library/core/src/sync/atomic.rs#L2166
- fmt::Debug::fmt(&self.load(Ordering::Relaxed), f)
- }
- }
+ impl_debug!($atomic_type);
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl serde::ser::Serialize for $atomic_type {
@@ -167,6 +168,17 @@ macro_rules! impl_debug_and_serde {
}
};
}
+macro_rules! impl_debug {
+ ($atomic_type:ident) => {
+ impl fmt::Debug for $atomic_type {
+ #[inline] // fmt is not hot path, but #[inline] on fmt seems to still be useful: https://github.com/rust-lang/rust/pull/117727
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ // std atomic types use Relaxed in Debug::fmt: https://github.com/rust-lang/rust/blob/1.80.0/library/core/src/sync/atomic.rs#L2166
+ fmt::Debug::fmt(&self.load(Ordering::Relaxed), f)
+ }
+ }
+ };
+}
// We do not provide `nand` because it cannot be optimized on neither x86 nor MSP430.
// https://godbolt.org/z/ahWejchbT
diff --git a/tests/api-test/src/helper.rs b/tests/api-test/src/helper.rs
index 63d6d4823..092a2fe02 100644
--- a/tests/api-test/src/helper.rs
+++ b/tests/api-test/src/helper.rs
@@ -394,6 +394,18 @@ macro_rules! __test_atomic_float {
}
__run_test!(fetch_max);
fn fetch_max() {
+ if core::mem::size_of::<$float_type>() == 16
+ && cfg!(any(
+ target_arch = "arm",
+ target_arch = "mips",
+ target_arch = "mips32r6",
+ target_vendor = "apple",
+ windows,
+ ))
+ {
+ // TODO(f128):
+ return;
+ }
for &order in &helper::SWAP_ORDERINGS {
let a = <$atomic_type>::new(23.);
assert_eq!(a.fetch_max(22., order), 23.);
@@ -409,6 +421,18 @@ macro_rules! __test_atomic_float {
}
__run_test!(fetch_min);
fn fetch_min() {
+ if core::mem::size_of::<$float_type>() == 16
+ && cfg!(any(
+ target_arch = "arm",
+ target_arch = "mips",
+ target_arch = "mips32r6",
+ target_vendor = "apple",
+ windows,
+ ))
+ {
+ // TODO(f128):
+ return;
+ }
for &order in &helper::SWAP_ORDERINGS {
let a = <$atomic_type>::new(23.);
assert_eq!(a.fetch_min(24., order), 23.);
diff --git a/tests/api-test/src/lib.rs b/tests/api-test/src/lib.rs
index 107b4aa62..0070854eb 100644
--- a/tests/api-test/src/lib.rs
+++ b/tests/api-test/src/lib.rs
@@ -1,12 +1,18 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT
#![no_std]
+#![cfg_attr(portable_atomic_unstable_f16, feature(f16))]
+#![cfg_attr(portable_atomic_unstable_f128, feature(f128))]
#![allow(unused_imports)]
#[macro_use]
mod helper;
use portable_atomic as atomic;
+#[cfg(all(feature = "float", portable_atomic_unstable_f128))]
+use portable_atomic::AtomicF128;
+#[cfg(all(feature = "float", portable_atomic_unstable_f16))]
+use portable_atomic::AtomicF16;
use portable_atomic::{
hint, AtomicBool, AtomicI128, AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicIsize,
AtomicPtr, AtomicU128, AtomicU16, AtomicU32, AtomicU64, AtomicU8, AtomicUsize, Ordering,
@@ -74,10 +80,14 @@ pub fn all() {
test_atomic_int!(u64);
test_atomic_int!(i128);
test_atomic_int!(u128);
+ #[cfg(all(feature = "float", portable_atomic_unstable_f16))]
+ test_atomic_float!(f16);
#[cfg(feature = "float")]
test_atomic_float!(f32);
#[cfg(feature = "float")]
test_atomic_float!(f64);
+ #[cfg(all(feature = "float", portable_atomic_unstable_f128))]
+ test_atomic_float!(f128);
}
#[cfg(test)]
diff --git a/tools/build.sh b/tools/build.sh
index ff916c543..669d1103c 100755
--- a/tools/build.sh
+++ b/tools/build.sh
@@ -349,6 +349,10 @@ build() {
mips-*-linux-* | mipsel-*-linux-*) target_rustflags+=" -C opt-level=1" ;;
esac
fi
+ if [[ "${base_rustflags}" == *"unqualified_local_imports"* ]]; then
+ [[ "${target_rustflags}" == *"portable_atomic_unstable_f16"* ]] || target_rustflags+=" --cfg portable_atomic_unstable_f16 --cfg quickcheck_unstable_f16 --cfg rand_unstable_f16"
+ [[ "${target_rustflags}" == *"portable_atomic_unstable_f128"* ]] || target_rustflags+=" --cfg portable_atomic_unstable_f128 --cfg quickcheck_unstable_f128 --cfg rand_unstable_f128"
+ fi
if [[ -n "${TESTS:-}" ]]; then
# We use std in main tests, so we cannot build them on no-std targets.