include!("macros.rs");
#[cfg(not(any(
target_feature = "quadword-atomics",
portable_atomic_target_feature = "quadword-atomics",
)))]
#[path = "../fallback/outline_atomics.rs"]
mod fallback;
#[cfg(not(portable_atomic_no_outline_atomics))]
#[cfg(any(
test,
not(any(
target_feature = "quadword-atomics",
portable_atomic_target_feature = "quadword-atomics",
)),
))]
#[cfg(any(
all(
target_os = "linux",
any(
all(
target_env = "gnu",
any(target_endian = "little", not(target_feature = "crt-static")),
),
all(target_env = "musl", any(not(target_feature = "crt-static"), feature = "std")),
target_env = "ohos",
all(target_env = "uclibc", not(target_feature = "crt-static")),
portable_atomic_outline_atomics,
),
),
target_os = "android",
all(
target_os = "freebsd",
any(
target_endian = "little",
not(target_feature = "crt-static"),
portable_atomic_outline_atomics,
),
),
target_os = "openbsd",
))]
#[path = "../detect/auxv.rs"]
mod detect;
#[cfg(not(portable_atomic_no_outline_atomics))]
#[cfg(any(
test,
not(any(
target_feature = "quadword-atomics",
portable_atomic_target_feature = "quadword-atomics",
)),
))]
#[cfg(target_os = "aix")]
#[cfg(not(portable_atomic_pre_llvm_20))] #[cfg(any(test, portable_atomic_outline_atomics))] #[path = "../detect/powerpc64_aix.rs"]
mod detect;
use core::{arch::asm, sync::atomic::Ordering};
use crate::utils::{Pair, U128};
macro_rules! debug_assert_pwr8 {
() => {
#[cfg(not(any(
target_feature = "quadword-atomics",
portable_atomic_target_feature = "quadword-atomics",
)))]
{
debug_assert!(detect::detect().quadword_atomics());
}
};
}
macro_rules! start_pwr8 {
() => {
".machine push\n.machine power8"
};
}
macro_rules! end_pwr8 {
() => {
".machine pop"
};
}
macro_rules! atomic_rmw {
($op:ident, $order:ident) => {
match $order {
Ordering::Relaxed => $op!("", ""),
Ordering::Acquire => $op!("isync", ""),
Ordering::Release => $op!("", "lwsync"),
Ordering::AcqRel => $op!("isync", "lwsync"),
Ordering::SeqCst => $op!("isync", "sync"),
_ => unreachable!(),
}
};
}
macro_rules! atomic_cas {
($op:ident, $success:ident, $failure:ident) => {
if $failure == Ordering::Relaxed {
match $success {
Ordering::Relaxed => $op!("", "", ""),
Ordering::Acquire => $op!("", "isync", ""),
Ordering::Release => $op!("", "", "lwsync"),
Ordering::AcqRel => $op!("", "isync", "lwsync"),
Ordering::SeqCst => $op!("", "isync", "sync"),
_ => unreachable!(),
}
} else {
let order = crate::utils::upgrade_success_ordering($success, $failure);
match order {
Ordering::Acquire => $op!("isync", "", ""),
Ordering::AcqRel => $op!("isync", "", "lwsync"),
Ordering::SeqCst => $op!("isync", "", "sync"),
_ => unreachable!(),
}
}
};
}
#[inline]
fn test_cr0_eq(cr: u64) -> bool {
cr & 0x20000000 != 0
}
#[cfg(any(
target_feature = "quadword-atomics",
portable_atomic_target_feature = "quadword-atomics",
))]
use self::atomic_load_pwr8 as atomic_load;
#[cfg(not(any(
target_feature = "quadword-atomics",
portable_atomic_target_feature = "quadword-atomics",
)))]
#[inline]
unsafe fn atomic_load(src: *mut u128, order: Ordering) -> u128 {
fn_alias! {
#[inline(never)]
unsafe fn(src: *mut u128) -> u128;
atomic_load_pwr8_relaxed = atomic_load_pwr8(Ordering::Relaxed);
atomic_load_pwr8_acquire = atomic_load_pwr8(Ordering::Acquire);
atomic_load_pwr8_seqcst = atomic_load_pwr8(Ordering::SeqCst);
}
unsafe {
match order {
Ordering::Relaxed => {
ifunc!(unsafe fn(src: *mut u128) -> u128 {
if detect::detect().quadword_atomics() {
atomic_load_pwr8_relaxed
} else {
fallback::atomic_load_non_seqcst
}
})
}
Ordering::Acquire => {
ifunc!(unsafe fn(src: *mut u128) -> u128 {
if detect::detect().quadword_atomics() {
atomic_load_pwr8_acquire
} else {
fallback::atomic_load_non_seqcst
}
})
}
Ordering::SeqCst => {
ifunc!(unsafe fn(src: *mut u128) -> u128 {
if detect::detect().quadword_atomics() {
atomic_load_pwr8_seqcst
} else {
fallback::atomic_load_seqcst
}
})
}
_ => unreachable!(),
}
}
}
#[inline]
unsafe fn atomic_load_pwr8(src: *mut u128, order: Ordering) -> u128 {
debug_assert!(src as usize % 16 == 0);
debug_assert_pwr8!();
let (out_hi, out_lo);
unsafe {
macro_rules! atomic_load_acquire {
($release:tt) => {
asm!(
start_pwr8!(),
$release,
"lq %r4, 0({src})", "cmpw %r4, %r4", "bne- %cr0, 2f", "2:", "isync", end_pwr8!(),
src = in(reg_nonzero) ptr_reg!(src),
out("r4") out_hi,
out("r5") out_lo,
out("cr0") _,
options(nostack, preserves_flags),
)
};
}
match order {
Ordering::Relaxed => {
asm!(
start_pwr8!(),
"lq %r4, 0({src})", end_pwr8!(),
src = in(reg_nonzero) ptr_reg!(src),
out("r4") out_hi,
out("r5") out_lo,
options(nostack, preserves_flags),
);
}
Ordering::Acquire => atomic_load_acquire!(""),
Ordering::SeqCst => atomic_load_acquire!("sync"),
_ => unreachable!(),
}
U128 { pair: Pair { hi: out_hi, lo: out_lo } }.whole
}
}
#[cfg(any(
target_feature = "quadword-atomics",
portable_atomic_target_feature = "quadword-atomics",
))]
use self::atomic_store_pwr8 as atomic_store;
#[cfg(not(any(
target_feature = "quadword-atomics",
portable_atomic_target_feature = "quadword-atomics",
)))]
#[inline]
unsafe fn atomic_store(dst: *mut u128, val: u128, order: Ordering) {
fn_alias! {
#[inline(never)]
unsafe fn(dst: *mut u128, val: u128);
atomic_store_pwr8_relaxed = atomic_store_pwr8(Ordering::Relaxed);
atomic_store_pwr8_release = atomic_store_pwr8(Ordering::Release);
atomic_store_pwr8_seqcst = atomic_store_pwr8(Ordering::SeqCst);
}
unsafe {
match order {
Ordering::Relaxed => {
ifunc!(unsafe fn(dst: *mut u128, val: u128) {
if detect::detect().quadword_atomics() {
atomic_store_pwr8_relaxed
} else {
fallback::atomic_store_non_seqcst
}
});
}
Ordering::Release => {
ifunc!(unsafe fn(dst: *mut u128, val: u128) {
if detect::detect().quadword_atomics() {
atomic_store_pwr8_release
} else {
fallback::atomic_store_non_seqcst
}
});
}
Ordering::SeqCst => {
ifunc!(unsafe fn(dst: *mut u128, val: u128) {
if detect::detect().quadword_atomics() {
atomic_store_pwr8_seqcst
} else {
fallback::atomic_store_seqcst
}
});
}
_ => unreachable!(),
}
}
}
#[inline]
unsafe fn atomic_store_pwr8(dst: *mut u128, val: u128, order: Ordering) {
debug_assert!(dst as usize % 16 == 0);
debug_assert_pwr8!();
let val = U128 { whole: val };
unsafe {
macro_rules! atomic_store {
($release:tt) => {
asm!(
start_pwr8!(),
$release, "stq %r4, 0({dst})", end_pwr8!(),
dst = in(reg_nonzero) ptr_reg!(dst),
in("r4") val.pair.hi,
in("r5") val.pair.lo,
options(nostack, preserves_flags),
)
};
}
match order {
Ordering::Relaxed => atomic_store!(""),
Ordering::Release => atomic_store!("lwsync"),
Ordering::SeqCst => atomic_store!("sync"),
_ => unreachable!(),
}
}
}
#[inline]
unsafe fn atomic_compare_exchange(
dst: *mut u128,
old: u128,
new: u128,
success: Ordering,
failure: Ordering,
) -> Result<u128, u128> {
#[cfg(any(
target_feature = "quadword-atomics",
portable_atomic_target_feature = "quadword-atomics",
))]
let (prev, ok) = unsafe { atomic_compare_exchange_pwr8(dst, old, new, success, failure) };
#[cfg(not(any(
target_feature = "quadword-atomics",
portable_atomic_target_feature = "quadword-atomics",
)))]
let (prev, ok) = {
fn_alias! {
#[inline(never)]
unsafe fn(dst: *mut u128, old: u128, new: u128) -> (u128, bool);
pwr8_relaxed_fn = atomic_compare_exchange_pwr8(Ordering::Relaxed, Ordering::Relaxed);
pwr8_acquire_fn = atomic_compare_exchange_pwr8(Ordering::Acquire, Ordering::Acquire);
pwr8_release_fn = atomic_compare_exchange_pwr8(Ordering::Release, Ordering::Relaxed);
pwr8_acqrel_fn = atomic_compare_exchange_pwr8(Ordering::AcqRel, Ordering::Acquire);
pwr8_seqcst_fn = atomic_compare_exchange_pwr8(Ordering::SeqCst, Ordering::SeqCst);
}
unsafe {
let success = crate::utils::upgrade_success_ordering(success, failure);
match success {
Ordering::Relaxed => {
ifunc!(unsafe fn(dst: *mut u128, old: u128, new: u128) -> (u128, bool) {
if detect::detect().quadword_atomics() {
pwr8_relaxed_fn
} else {
fallback::atomic_compare_exchange_non_seqcst
}
})
}
Ordering::Acquire => {
ifunc!(unsafe fn(dst: *mut u128, old: u128, new: u128) -> (u128, bool) {
if detect::detect().quadword_atomics() {
pwr8_acquire_fn
} else {
fallback::atomic_compare_exchange_non_seqcst
}
})
}
Ordering::Release => {
ifunc!(unsafe fn(dst: *mut u128, old: u128, new: u128) -> (u128, bool) {
if detect::detect().quadword_atomics() {
pwr8_release_fn
} else {
fallback::atomic_compare_exchange_non_seqcst
}
})
}
Ordering::AcqRel => {
ifunc!(unsafe fn(dst: *mut u128, old: u128, new: u128) -> (u128, bool) {
if detect::detect().quadword_atomics() {
pwr8_acqrel_fn
} else {
fallback::atomic_compare_exchange_non_seqcst
}
})
}
Ordering::SeqCst => {
ifunc!(unsafe fn(dst: *mut u128, old: u128, new: u128) -> (u128, bool) {
if detect::detect().quadword_atomics() {
pwr8_seqcst_fn
} else {
fallback::atomic_compare_exchange_seqcst
}
})
}
_ => unreachable!(),
}
}
};
if ok { Ok(prev) } else { Err(prev) }
}
#[inline]
unsafe fn atomic_compare_exchange_pwr8(
dst: *mut u128,
old: u128,
new: u128,
success: Ordering,
failure: Ordering,
) -> (u128, bool) {
debug_assert!(dst as usize % 16 == 0);
debug_assert_pwr8!();
let old = U128 { whole: old };
let new = U128 { whole: new };
let (mut prev_hi, mut prev_lo);
let mut r;
unsafe {
macro_rules! cmpxchg {
($acquire_always:tt, $acquire_success:tt, $release:tt) => {
asm!(
start_pwr8!(),
$release, "2:", "lqarx %r8, 0, {dst}", "xor {tmp_lo}, %r9, {old_lo}", "xor {tmp_hi}, %r8, {old_hi}", "or. {tmp_lo}, {tmp_lo}, {tmp_hi}", "bne %cr0, 3f", "stqcx. %r6, 0, {dst}", "bne %cr0, 2b", $acquire_success, "3:", $acquire_always, "mfcr {tmp_lo}", end_pwr8!(),
dst = in(reg_nonzero) ptr_reg!(dst),
old_hi = in(reg) old.pair.hi,
old_lo = in(reg) old.pair.lo,
tmp_hi = out(reg) _,
tmp_lo = out(reg) r,
in("r6") new.pair.hi,
in("r7") new.pair.lo,
out("r8") prev_hi,
out("r9") prev_lo,
out("cr0") _,
options(nostack, preserves_flags),
)
};
}
atomic_cas!(cmpxchg, success, failure);
(U128 { pair: Pair { hi: prev_hi, lo: prev_lo } }.whole, test_cr0_eq(r))
}
}
#[cfg(not(any(
target_feature = "quadword-atomics",
portable_atomic_target_feature = "quadword-atomics",
)))]
use self::atomic_compare_exchange as atomic_compare_exchange_weak;
#[cfg(any(
target_feature = "quadword-atomics",
portable_atomic_target_feature = "quadword-atomics",
))]
#[inline]
unsafe fn atomic_compare_exchange_weak(
dst: *mut u128,
old: u128,
new: u128,
success: Ordering,
failure: Ordering,
) -> Result<u128, u128> {
let (prev, ok) = unsafe { atomic_compare_exchange_weak_pwr8(dst, old, new, success, failure) };
if ok { Ok(prev) } else { Err(prev) }
}
#[cfg(any(
target_feature = "quadword-atomics",
portable_atomic_target_feature = "quadword-atomics",
))]
#[inline]
unsafe fn atomic_compare_exchange_weak_pwr8(
dst: *mut u128,
old: u128,
new: u128,
success: Ordering,
failure: Ordering,
) -> (u128, bool) {
debug_assert!(dst as usize % 16 == 0);
debug_assert_pwr8!();
let old = U128 { whole: old };
let new = U128 { whole: new };
let (mut prev_hi, mut prev_lo);
let mut r;
unsafe {
macro_rules! cmpxchg_weak {
($acquire_always:tt, $acquire_success:tt, $release:tt) => {
asm!(
start_pwr8!(),
$release, "lqarx %r8, 0, {dst}", "xor {tmp_lo}, %r9, {old_lo}", "xor {tmp_hi}, %r8, {old_hi}", "or. {tmp_lo}, {tmp_lo}, {tmp_hi}", "bne %cr0, 3f", "stqcx. %r6, 0, {dst}", $acquire_success, "3:", $acquire_always, "mfcr {tmp_lo}", end_pwr8!(),
dst = in(reg_nonzero) ptr_reg!(dst),
old_hi = in(reg) old.pair.hi,
old_lo = in(reg) old.pair.lo,
tmp_hi = out(reg) _,
tmp_lo = out(reg) r,
in("r6") new.pair.hi,
in("r7") new.pair.lo,
out("r8") prev_hi,
out("r9") prev_lo,
out("cr0") _,
options(nostack, preserves_flags),
)
};
}
atomic_cas!(cmpxchg_weak, success, failure);
(U128 { pair: Pair { hi: prev_hi, lo: prev_lo } }.whole, test_cr0_eq(r))
}
}
#[inline]
unsafe fn atomic_swap_pwr8(dst: *mut u128, val: u128, order: Ordering) -> u128 {
debug_assert!(dst as usize % 16 == 0);
debug_assert_pwr8!();
let val = U128 { whole: val };
let (mut prev_hi, mut prev_lo);
unsafe {
macro_rules! swap {
($acquire:tt, $release:tt) => {
asm!(
start_pwr8!(),
$release, "2:", "lqarx %r6, 0, {dst}", "stqcx. %r8, 0, {dst}", "bne %cr0, 2b", $acquire, end_pwr8!(),
dst = in(reg_nonzero) ptr_reg!(dst),
out("r6") prev_hi,
out("r7") prev_lo,
in("r8") val.pair.hi,
in("r9") val.pair.lo,
out("cr0") _,
options(nostack, preserves_flags),
)
};
}
atomic_rmw!(swap, order);
U128 { pair: Pair { hi: prev_hi, lo: prev_lo } }.whole
}
}
macro_rules! atomic_rmw_ll_sc_3 {
($name:ident, [$($reg:tt)*], $($op:tt)*) => {
#[inline]
unsafe fn $name(dst: *mut u128, val: u128, order: Ordering) -> u128 {
debug_assert!(dst as usize % 16 == 0);
debug_assert_pwr8!();
let val = U128 { whole: val };
let (mut prev_hi, mut prev_lo);
unsafe {
macro_rules! op {
($acquire:tt, $release:tt) => {
asm!(
start_pwr8!(),
$release, "2:", "lqarx %r6, 0, {dst}", $($op)*
"stqcx. %r8, 0, {dst}", "bne %cr0, 2b", $acquire, end_pwr8!(),
dst = in(reg_nonzero) ptr_reg!(dst),
val_hi = in(reg) val.pair.hi,
val_lo = in(reg) val.pair.lo,
$($reg)*
out("r6") prev_hi,
out("r7") prev_lo,
out("r8") _, out("r9") _, out("cr0") _,
options(nostack, preserves_flags),
)
};
}
atomic_rmw!(op, order);
U128 { pair: Pair { hi: prev_hi, lo: prev_lo } }.whole
}
}
};
}
macro_rules! atomic_rmw_ll_sc_2 {
($name:ident, [$($reg:tt)*], $($op:tt)*) => {
#[inline]
unsafe fn $name(dst: *mut u128, order: Ordering) -> u128 {
debug_assert!(dst as usize % 16 == 0);
debug_assert_pwr8!();
let (mut prev_hi, mut prev_lo);
unsafe {
macro_rules! op {
($acquire:tt, $release:tt) => {
asm!(
start_pwr8!(),
$release, "2:", "lqarx %r6, 0, {dst}", $($op)*
"stqcx. %r8, 0, {dst}", "bne %cr0, 2b", $acquire, end_pwr8!(),
dst = in(reg_nonzero) ptr_reg!(dst),
$($reg)*
out("r6") prev_hi,
out("r7") prev_lo,
out("r8") _, out("r9") _, out("cr0") _,
options(nostack, preserves_flags),
)
};
}
atomic_rmw!(op, order);
U128 { pair: Pair { hi: prev_hi, lo: prev_lo } }.whole
}
}
};
}
atomic_rmw_ll_sc_3! {
atomic_add_pwr8, [out("xer") _,],
"addc %r9, {val_lo}, %r7", "adde %r8, {val_hi}, %r6", }
atomic_rmw_ll_sc_3! {
atomic_sub_pwr8, [out("xer") _,],
"subc %r9, %r7, {val_lo}", "subfe %r8, {val_hi}, %r6", }
atomic_rmw_ll_sc_3! {
atomic_and_pwr8, [],
"and %r9, {val_lo}, %r7", "and %r8, {val_hi}, %r6", }
atomic_rmw_ll_sc_3! {
atomic_nand_pwr8, [],
"nand %r9, {val_lo}, %r7", "nand %r8, {val_hi}, %r6", }
atomic_rmw_ll_sc_3! {
atomic_or_pwr8, [],
"or %r9, {val_lo}, %r7", "or %r8, {val_hi}, %r6", }
atomic_rmw_ll_sc_3! {
atomic_xor_pwr8, [],
"xor %r9, {val_lo}, %r7", "xor %r8, {val_hi}, %r6", }
atomic_rmw_ll_sc_3! {
atomic_max_pwr8, [out("cr1") _,],
"cmpld %r7, {val_lo}", "iselgt %r9, %r7, {val_lo}", "cmpd %cr1, %r6, {val_hi}", "isel %r8, %r7, {val_lo}, 5", "cmpld %r6, {val_hi}", "iseleq %r9, %r9, %r8", "isel %r8, %r6, {val_hi}, 5", }
atomic_rmw_ll_sc_3! {
atomic_umax_pwr8, [],
"cmpld %r7, {val_lo}", "iselgt %r9, %r7, {val_lo}", "cmpld %r6, {val_hi}", "iselgt %r8, %r7, {val_lo}", "iseleq %r9, %r9, %r8", "iselgt %r8, %r6, {val_hi}", }
atomic_rmw_ll_sc_3! {
atomic_min_pwr8, [out("cr1") _,],
"cmpld %r7, {val_lo}", "isellt %r9, %r7, {val_lo}", "cmpd %cr1, %r6, {val_hi}", "isel %r8, %r7, {val_lo}, 4", "cmpld %r6, {val_hi}", "iseleq %r9, %r9, %r8", "isel %r8, %r6, {val_hi}, 4", }
atomic_rmw_ll_sc_3! {
atomic_umin_pwr8, [],
"cmpld %r7, {val_lo}", "isellt %r9, %r7, {val_lo}", "cmpld %r6, {val_hi}", "isellt %r8, %r7, {val_lo}", "iseleq %r9, %r9, %r8", "isellt %r8, %r6, {val_hi}", }
#[inline]
unsafe fn atomic_not_pwr8(dst: *mut u128, order: Ordering) -> u128 {
unsafe { atomic_xor_pwr8(dst, !0, order) }
}
#[cfg(not(portable_atomic_pre_llvm_16))]
atomic_rmw_ll_sc_2! {
atomic_neg_pwr8, [out("xer") _,],
"subfic %r9, %r7, 0", "subfze %r8, %r6", }
#[cfg(portable_atomic_pre_llvm_16)]
atomic_rmw_ll_sc_2! {
atomic_neg_pwr8, [zero = in(reg) 0_u64, out("xer") _,],
"subc %r9, {zero}, %r7", "subfze %r8, %r6", }
macro_rules! select_atomic_rmw {
(
unsafe fn $name:ident($($arg:tt)*) $(-> $ret_ty:ty)?;
pwr8 = $pwr8_fn:ident;
non_seqcst_fallback = $non_seqcst_fallback_fn:ident;
seqcst_fallback = $seqcst_fallback_fn:ident;
) => {
#[cfg(any(
target_feature = "quadword-atomics",
portable_atomic_target_feature = "quadword-atomics",
))]
use self::$pwr8_fn as $name;
#[cfg(not(any(
target_feature = "quadword-atomics",
portable_atomic_target_feature = "quadword-atomics",
)))]
#[inline]
unsafe fn $name($($arg)*, order: Ordering) $(-> $ret_ty)? {
fn_alias! {
#[inline(never)]
unsafe fn($($arg)*) $(-> $ret_ty)?;
pwr8_relaxed_fn = $pwr8_fn(Ordering::Relaxed);
pwr8_acquire_fn = $pwr8_fn(Ordering::Acquire);
pwr8_release_fn = $pwr8_fn(Ordering::Release);
pwr8_acqrel_fn = $pwr8_fn(Ordering::AcqRel);
pwr8_seqcst_fn = $pwr8_fn(Ordering::SeqCst);
}
unsafe {
match order {
Ordering::Relaxed => {
ifunc!(unsafe fn($($arg)*) $(-> $ret_ty)? {
if detect::detect().quadword_atomics() {
pwr8_relaxed_fn
} else {
fallback::$non_seqcst_fallback_fn
}
})
}
Ordering::Acquire => {
ifunc!(unsafe fn($($arg)*) $(-> $ret_ty)? {
if detect::detect().quadword_atomics() {
pwr8_acquire_fn
} else {
fallback::$non_seqcst_fallback_fn
}
})
}
Ordering::Release => {
ifunc!(unsafe fn($($arg)*) $(-> $ret_ty)? {
if detect::detect().quadword_atomics() {
pwr8_release_fn
} else {
fallback::$non_seqcst_fallback_fn
}
})
}
Ordering::AcqRel => {
ifunc!(unsafe fn($($arg)*) $(-> $ret_ty)? {
if detect::detect().quadword_atomics() {
pwr8_acqrel_fn
} else {
fallback::$non_seqcst_fallback_fn
}
})
}
Ordering::SeqCst => {
ifunc!(unsafe fn($($arg)*) $(-> $ret_ty)? {
if detect::detect().quadword_atomics() {
pwr8_seqcst_fn
} else {
fallback::$seqcst_fallback_fn
}
})
}
_ => unreachable!(),
}
}
}
};
}
select_atomic_rmw! {
unsafe fn atomic_swap(dst: *mut u128, val: u128) -> u128;
pwr8 = atomic_swap_pwr8;
non_seqcst_fallback = atomic_swap_non_seqcst;
seqcst_fallback = atomic_swap_seqcst;
}
select_atomic_rmw! {
unsafe fn atomic_add(dst: *mut u128, val: u128) -> u128;
pwr8 = atomic_add_pwr8;
non_seqcst_fallback = atomic_add_non_seqcst;
seqcst_fallback = atomic_add_seqcst;
}
select_atomic_rmw! {
unsafe fn atomic_sub(dst: *mut u128, val: u128) -> u128;
pwr8 = atomic_sub_pwr8;
non_seqcst_fallback = atomic_sub_non_seqcst;
seqcst_fallback = atomic_sub_seqcst;
}
select_atomic_rmw! {
unsafe fn atomic_and(dst: *mut u128, val: u128) -> u128;
pwr8 = atomic_and_pwr8;
non_seqcst_fallback = atomic_and_non_seqcst;
seqcst_fallback = atomic_and_seqcst;
}
select_atomic_rmw! {
unsafe fn atomic_nand(dst: *mut u128, val: u128) -> u128;
pwr8 = atomic_nand_pwr8;
non_seqcst_fallback = atomic_nand_non_seqcst;
seqcst_fallback = atomic_nand_seqcst;
}
select_atomic_rmw! {
unsafe fn atomic_or(dst: *mut u128, val: u128) -> u128;
pwr8 = atomic_or_pwr8;
non_seqcst_fallback = atomic_or_non_seqcst;
seqcst_fallback = atomic_or_seqcst;
}
select_atomic_rmw! {
unsafe fn atomic_xor(dst: *mut u128, val: u128) -> u128;
pwr8 = atomic_xor_pwr8;
non_seqcst_fallback = atomic_xor_non_seqcst;
seqcst_fallback = atomic_xor_seqcst;
}
select_atomic_rmw! {
unsafe fn atomic_max(dst: *mut u128, val: u128) -> u128;
pwr8 = atomic_max_pwr8;
non_seqcst_fallback = atomic_max_non_seqcst;
seqcst_fallback = atomic_max_seqcst;
}
select_atomic_rmw! {
unsafe fn atomic_umax(dst: *mut u128, val: u128) -> u128;
pwr8 = atomic_umax_pwr8;
non_seqcst_fallback = atomic_umax_non_seqcst;
seqcst_fallback = atomic_umax_seqcst;
}
select_atomic_rmw! {
unsafe fn atomic_min(dst: *mut u128, val: u128) -> u128;
pwr8 = atomic_min_pwr8;
non_seqcst_fallback = atomic_min_non_seqcst;
seqcst_fallback = atomic_min_seqcst;
}
select_atomic_rmw! {
unsafe fn atomic_umin(dst: *mut u128, val: u128) -> u128;
pwr8 = atomic_umin_pwr8;
non_seqcst_fallback = atomic_umin_non_seqcst;
seqcst_fallback = atomic_umin_seqcst;
}
select_atomic_rmw! {
unsafe fn atomic_not(dst: *mut u128) -> u128;
pwr8 = atomic_not_pwr8;
non_seqcst_fallback = atomic_not_non_seqcst;
seqcst_fallback = atomic_not_seqcst;
}
select_atomic_rmw! {
unsafe fn atomic_neg(dst: *mut u128) -> u128;
pwr8 = atomic_neg_pwr8;
non_seqcst_fallback = atomic_neg_non_seqcst;
seqcst_fallback = atomic_neg_seqcst;
}
#[inline]
fn is_lock_free() -> bool {
#[cfg(any(
target_feature = "quadword-atomics",
portable_atomic_target_feature = "quadword-atomics",
))]
{
true
}
#[cfg(not(any(
target_feature = "quadword-atomics",
portable_atomic_target_feature = "quadword-atomics",
)))]
{
detect::detect().quadword_atomics()
}
}
const IS_ALWAYS_LOCK_FREE: bool = cfg!(any(
target_feature = "quadword-atomics",
portable_atomic_target_feature = "quadword-atomics",
));
atomic128!(AtomicI128, i128, atomic_max, atomic_min);
atomic128!(AtomicU128, u128, atomic_umax, atomic_umin);
#[cfg(not(valgrind))] #[cfg(test)]
mod tests {
use super::*;
test_atomic_int!(i128);
test_atomic_int!(u128);
stress_test!(u128);
}