Skip to content

Commit

Permalink
detect: Support run-time detection on powerpc64 AIX
Browse files Browse the repository at this point in the history
  • Loading branch information
taiki-e committed Aug 7, 2023
1 parent 30dd36b commit aec8a2d
Show file tree
Hide file tree
Showing 8 changed files with 91 additions and 1 deletion.
1 change: 1 addition & 0 deletions .github/.cspell/project-dictionary.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ espup
exynos
FIQs
getauxval
getsystemcfg
HWCAP
ifunc
includepath
Expand Down
1 change: 1 addition & 0 deletions src/imp/atomic128/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ Here is the table of targets that support run-time feature detection and the ins
| aarch64 | fuchsia | zx_system_get_features | Enabled by default |
| powerpc64 | linux | getauxval | Disabled by default |
| powerpc64 | freebsd | elf_aux_info | Disabled by default |
| powerpc64 | aix | getsystemcfg | Disabled by default |

Run-time detection is enabled by default on most targets and can be disabled with `--cfg portable_atomic_no_outline_atomics`.

Expand Down
68 changes: 68 additions & 0 deletions src/imp/atomic128/detect/powerpc64_aix.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Run-time feature detection on powerpc64 AIX by using getsystemcfg.
//
// Refs:
// - https://github.com/golang/go/blob/master/src/internal/cpu/cpu_ppc64x_aix.go

include!("common.rs");

// core::ffi::c_* (except c_void) requires Rust 1.64, libc will soon require Rust 1.47
mod ffi {
pub(crate) use super::c_types::{c_int, c_ulong};

// https://github.com/rust-lang/libc/blob/0.2.140/src/unix/aix/mod.rs#L1576
// https://github.com/golang/go/blob/master/src/internal/cpu/cpu_ppc64x_aix.go
pub(crate) const SC_IMPL: c_int = 2;
pub(crate) const POWER_8: c_ulong = 0x10000;

extern "C" {
// https://www.ibm.com/docs/en/aix/7.2?topic=g-getsystemcfg-subroutine
// https://github.com/rust-lang/libc/blob/0.2.140/src/unix/aix/powerpc64.rs#L569
pub(crate) fn getsystemcfg(name: c_int) -> c_ulong;
}
}

#[cold]
fn _detect(info: &mut CpuInfo) {
// SAFETY: calling getsystemcfg is safe.
let impl_ = unsafe { ffi::getsystemcfg(ffi::SC_IMPL) };
if impl_ == ffi::c_ulong::MAX {
return;
}
if impl_ & ffi::POWER_8 != 0 {
info.set(CpuInfo::HAS_QUADWORD_ATOMICS);
}
}

#[allow(
clippy::alloc_instead_of_core,
clippy::std_instead_of_alloc,
clippy::std_instead_of_core,
clippy::undocumented_unsafe_blocks,
clippy::wildcard_imports
)]
#[cfg(test)]
mod tests {
use super::*;

// Static assertions for FFI bindings.
// This checks that FFI bindings defined in this crate and FFI bindings defined
// in libc compatible signatures (or the same values if constants).
// Since this is static assertion, we can detect problems with
// `cargo check --tests --target <target>` run in CI (via TESTS=1 build.sh)
// without actually running tests on these platforms.
// See also tools/codegen/src/ffi.rs.
// TODO: auto-generate this test
#[allow(
clippy::cast_possible_wrap,
clippy::cast_sign_loss,
clippy::cast_possible_truncation,
clippy::no_effect_underscore_binding
)]
const _: fn() = || {
use test_helper::libc;
let mut _getsystemcfg: unsafe extern "C" fn(ffi::c_int) -> ffi::c_ulong = ffi::getsystemcfg;
_getsystemcfg = libc::getsystemcfg;
static_assert!(ffi::SC_IMPL == libc::SC_IMPL);
static_assert!(ffi::POWER_8 == libc::POWER_8);
};
}
12 changes: 12 additions & 0 deletions src/imp/atomic128/powerpc64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,18 @@ mod fallback;
))]
#[path = "detect/auxv.rs"]
mod detect;
#[cfg(not(portable_atomic_no_outline_atomics))]
#[cfg(any(test, portable_atomic_outline_atomics))] // TODO(powerpc64): currently disabled by default
#[cfg(any(
test,
not(any(
target_feature = "quadword-atomics",
portable_atomic_target_feature = "quadword-atomics",
)),
))]
#[cfg(target_os = "aix")]
#[path = "detect/powerpc64_aix.rs"]
mod detect;

use core::{arch::asm, sync::atomic::Ordering};

Expand Down
1 change: 1 addition & 0 deletions src/imp/fallback/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
),
target_os = "android",
target_os = "freebsd",
target_os = "aix",
),
not(any(miri, portable_atomic_sanitize_thread)),
),
Expand Down
3 changes: 3 additions & 0 deletions src/imp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ mod x86_64;
),
target_os = "android",
target_os = "freebsd",
target_os = "aix",
),
not(any(miri, portable_atomic_sanitize_thread)),
),
Expand Down Expand Up @@ -369,6 +370,7 @@ items! {
),
target_os = "android",
target_os = "freebsd",
target_os = "aix",
),
not(any(miri, portable_atomic_sanitize_thread)),
),
Expand Down Expand Up @@ -442,6 +444,7 @@ pub(crate) use self::x86_64::{AtomicI128, AtomicU128};
),
target_os = "android",
target_os = "freebsd",
target_os = "aix",
),
not(any(miri, portable_atomic_sanitize_thread)),
),
Expand Down
2 changes: 2 additions & 0 deletions src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,7 @@ mod atomic_64_macros {
),
target_os = "android",
target_os = "freebsd",
target_os = "aix",
),
not(any(miri, portable_atomic_sanitize_thread)),
),
Expand Down Expand Up @@ -596,6 +597,7 @@ mod atomic_128_macros {
),
target_os = "android",
target_os = "freebsd",
target_os = "aix",
),
not(any(miri, portable_atomic_sanitize_thread)),
),
Expand Down
4 changes: 3 additions & 1 deletion tools/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ default_targets=(
powerpc64le-unknown-linux-musl
powerpc64-unknown-freebsd
powerpc64le-unknown-freebsd
powerpc64-ibm-aix

# s390x
# rustc --print target-list | grep -E '^s390x'
Expand Down Expand Up @@ -153,7 +154,8 @@ is_no_std() {
case "$1" in
# https://github.com/rust-lang/rust/blob/1.70.0/library/std/build.rs#L41
# TODO: aarch64-unknown-linux-uclibc is a custom target and libc/std currently doesn't support it.
*-none* | *-uefi* | *-psp* | *-psx* | *-cuda* | avr-* | aarch64-unknown-linux-uclibc) return 0 ;;
# TODO: std currently doesn't support AIX: https://github.com/rust-lang/rust/pull/109882
*-none* | *-uefi* | *-psp* | *-psx* | *-cuda* | avr-* | aarch64-unknown-linux-uclibc | *-aix) return 0 ;;
*) return 1 ;;
esac
}
Expand Down

0 comments on commit aec8a2d

Please sign in to comment.