-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
document when atomic loads are guaranteed read-only #115577
Conversation
r? @cuviper (rustbot has picked a reviewer for you, use r? to override) |
badf7d6
to
f330560
Compare
I'm going to put this in the API domain, since it's making guarantees. @rustbot label -T-libs +t-libs-api |
Cc @rust-lang/opsem for help in filling out the table |
Can GCC guarantee this too? cc @antoyo |
I'm not sure I have enough context/understanding of the situation. |
On x86 LLVM emits cmpxchg8b for 64bit loads and on x86_64 cmpxchg16b for 128bit loads as far as I understand, which is considered a write (and thus causes SIGSEGV on read-only memory) even if it wouldn't actually change the value at the memory location in question. For values of at most the register width LLVM will use mov on x86/x86_64 which is guaranteed read-only. Does GCC behave the same? |
The doc mentions:
but trying to do so on my computer results in the following error:
and I read somewhere that 16-byte atomic operations always call a function in gcc, so not read-only. I assume we would need to call |
Rust atomics must always be lock-free, so if the GGC backend uses a lock implementation, that's already a bug -- but separate from the issue discussed here. |
@rust-lang/libs-api: This is module-level documentation for As I understand it, the new guarantee introduced here would make the following sound: we want a value that can be atomically loaded but the backing data might either be the read-write memory where interior mutable values ordinarily go, or could be readonly memory on certain architectures that have this new guarantee. #[repr(transparent)]
pub struct AtomicallyLoadableU64(AtomicU64);
impl AtomicallyLoadableU64 {
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64", target_arch = "riscv64"))]
pub fn from_readonly(readonly: &u64) -> &Self {
unsafe { ... }
}
pub fn from_interior_mutable(interior_mutable: &AtomicU64) -> &Self {
unsafe { ... }
}
pub fn load(&self, ordering: Ordering) -> u64 {
self.0.load(ordering)
}
} Perhaps we'd be happy to delegate this to a T-opsem FCP? I'm not sure that I would have any relevant API insight on this. It seems fine to guarantee, if this is a stable property these architectures and our compiler backends can guarantee. @rfcbot poll libs-api -- opsem makes the call |
Team member @dtolnay has asked teams: T-libs-api, for consensus on:
|
7827676
to
7239980
Compare
@BurntSushi @joshtriplett @m-ou-se there's an rfcbot poll waiting for your checkmark here. :) |
The t-libs-api rfcbot poll has now reached the usual threshold for team consensus (a strict majority of approvals with at most two votes still open). So I assume we can hand this over to t-opsem. @rfcbot merge |
Team member @RalfJung has proposed to merge this. The next step is review by the rest of the tagged team members: No concerns currently listed. Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See this document for info about what commands tagged team members can give me. |
library/core/src/sync/atomic.rs
Outdated
//! | `i(3|5|6)86-`, `arm`, `thumb`, `mips(|el)-`, `powerpc-`, `riscv32`, `sparc-` | 4 bytes | | ||
//! | `x86_64-`, `aarch64-`, `loongarch64-`, `mips64(|el)-`, `powerpc64-`, `riscv64` | 8 bytes | | ||
//! | `powerpc64le-` | 16 bytes | | ||
//! | `s390x-` | 16 bytes | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
//! | `i(3|5|6)86-`, `arm`, `thumb`, `mips(|el)-`, `powerpc-`, `riscv32`, `sparc-` | 4 bytes | | |
//! | `x86_64-`, `aarch64-`, `loongarch64-`, `mips64(|el)-`, `powerpc64-`, `riscv64` | 8 bytes | | |
//! | `powerpc64le-` | 16 bytes | | |
//! | `s390x-` | 16 bytes | | |
//! | `i(3|5|6)86-`, `arm`, `thumb`, `mips(|el)-`, `mipsisa32r6(|el)-`, `powerpc-`, `riscv32`, `sparc-` | 4 bytes | | |
//! | `x86_64`, `aarch64`, `arm64`, `loongarch64-`, `mips64(|el)-`, `mipsisa64r6(|el)-`, `powerpc64-`, `riscv64`, `sparc(64|v9)-` | 8 bytes | | |
//! | `powerpc64le-`, `s390x-` | 16 bytes | |
Changes in the above suggestion:
- x86_64- -> x86_64: x86_64h(-apple-darwin) is not x86_64- but is x86_64
- aarch64- -> aarch64: aarch64_be-(-unknown-linux-gnu(|_ilp32)|-unknown-linux-netbsd) are not aarch64- but is aarch64
- add arm64: arm64_32(-apple-watchos) is not aarch64- but is aarch64
- add sparc(64|v9)- (target_arch: sparc64), mipsisa32r6(|el)- (target_arch: mips32r6), mipsisa64r6(|el)- (target_arch: mips64r6)
- merge powerpc64le- and s390x- into the same row
Since target triples are complex and cannot be handled correctly on the user side without a build script, I recommend using target_arch based table (like #115577 (comment)) if possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I recommend using target_arch based table (like #115577 (comment)) if possible.
Yeah that's what we had earlier, but powerpc64le- has target_arch = powerpc64 so then we can't tell it apart from powerpc64-.
Would it make sense to use target_cpu? That's a field I can see in the JSON target spec, anyway. But it doesn't seem exposed as a cfg
so I guess that's not helpful either...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My recommendation is to guarantee nothing about 128-bit atomics as said in #115577 (comment).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well I guess we're back to a table that just says "pointer size" is a convoluted way then. 🤷
library/core/src/sync/atomic.rs
Outdated
//! |---------------|---------| | ||
//! | `x86`, `arm`, `mips`, `mips32r6, `powerpc`, `riscv32`, `sparc`, `hexagon` | 4 bytes | | ||
//! | `x86_64`, `aarch64`, `loongarch64`, `mips64`, `mips64r6`, `powerpc64`, `riscv64`, `sparc64` | 8 bytes | | ||
//! | `s390x`, `powerpc64` with `target_feature = "quadword-atomics"` | 16 bytes | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
quadword-atomics is not a valid rust target feature. Also note that even if valid, the powerpc target feature is not stable.
rust/compiler/rustc_codegen_ssa/src/target_features.rs
Lines 225 to 235 in 49691b1
const POWERPC_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[ | |
// tidy-alphabetical-start | |
("altivec", Some(sym::powerpc_target_feature)), | |
("power10-vector", Some(sym::powerpc_target_feature)), | |
("power8-altivec", Some(sym::powerpc_target_feature)), | |
("power8-vector", Some(sym::powerpc_target_feature)), | |
("power9-altivec", Some(sym::powerpc_target_feature)), | |
("power9-vector", Some(sym::powerpc_target_feature)), | |
("vsx", Some(sym::powerpc_target_feature)), | |
// tidy-alphabetical-end | |
]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But we have some targets that enable it. How do you suggest we reflect that in the list?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is reasonable to document it once the 128-bit atomics in that target and the corresponding target feature have stabilized.
All right, so we have FCP passed and approval from our domain expert. |
I'm still not very happy about not supporting @bors r+ rollup |
☀️ Test successful - checks-actions |
Finished benchmarking commit (93e62a2): comparison URL. Overall result: no relevant changes - no action needed@rustbot label: -perf-regression Instruction countThis benchmark run did not return any relevant results for this metric. Max RSS (memory usage)ResultsThis is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
CyclesResultsThis is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
Binary sizeThis benchmark run did not return any relevant results for this metric. Bootstrap: 626.338s -> 623.96s (-0.38%) |
57: Pull upstream master 2023 10 18 r=pietroalbini a=Veykril * rust-lang/rust#116505 * rust-lang/rust#116840 * rust-lang/rust#116767 * rust-lang/rust#116855 * rust-lang/rust#116827 * rust-lang/rust#116787 * rust-lang/rust#116719 * rust-lang/rust#116717 * rust-lang/rust#111072 * rust-lang/rust#116844 * rust-lang/rust#115577 * rust-lang/rust#116756 * rust-lang/rust#116518 Co-authored-by: Urgau <[email protected]> Co-authored-by: Esteban Küber <[email protected]> Co-authored-by: Deadbeef <[email protected]> Co-authored-by: Ralf Jung <[email protected]> Co-authored-by: Camille GILLOT <[email protected]> Co-authored-by: Celina G. Val <[email protected]> Co-authored-by: Nicholas Nethercote <[email protected]> Co-authored-by: Arthur Lafrance <[email protected]> Co-authored-by: Nikolay Arhipov <[email protected]> Co-authored-by: Nikita Popov <[email protected]> Co-authored-by: bors <[email protected]>
accept some atomic loads from read-only memory matches rust-lang/rust#115577
…Jung accept some atomic loads from read-only memory matches rust-lang#115577
Pkgsrc changes: * Adjust patches and cargo checksums to new versions. * For an external LLVM, set dependency of llvm >= 16, in accordance with the upstream changes. * Mark that on NetBSD we now need >= 9.0, so 8.x is no longer supported. * On NetBSD/sparc64 10.x, we now need GCC 12 to build the embedded LLVM, which is version 17; apparently GCC 10.4 or 10.5 mis-compiles it, resulting in an illegal instruction fault during the build. Ref. rust-lang/rust#117231 Upstream changes: Version 1.75.0 (2023-12-28) ========================== - [Stabilize `async fn` and return-position `impl Trait` in traits.] (rust-lang/rust#115822) - [Allow function pointer signatures containing `&mut T` in `const` contexts.] (rust-lang/rust#116015) - [Match `usize`/`isize` exhaustively with half-open ranges.] (rust-lang/rust#116692) - [Guarantee that `char` has the same size and alignment as `u32`.] (rust-lang/rust#116894) - [Document that the null pointer has the 0 address.] (rust-lang/rust#116988) - [Allow partially moved values in `match`.] (rust-lang/rust#103208) - [Add notes about non-compliant FP behavior on 32bit x86 targets.] (rust-lang/rust#113053) - [Stabilize ratified RISC-V target features.] (rust-lang/rust#116485) Compiler -------- - [Rework negative coherence to properly consider impls that only partly overlap.] (rust-lang/rust#112875) - [Bump `COINDUCTIVE_OVERLAP_IN_COHERENCE` to deny, and warn in dependencies.] (rust-lang/rust#116493) - [Consider alias bounds when computing liveness in NLL.] (rust-lang/rust#116733) - [Add the V (vector) extension to the `riscv64-linux-android` target spec.] (rust-lang/rust#116618) - [Automatically enable cross-crate inlining for small functions] (rust-lang/rust#116505) - Add several new tier 3 targets: - [`csky-unknown-linux-gnuabiv2hf`] (rust-lang/rust#117049) - [`i586-unknown-netbsd`] (rust-lang/rust#117170) - [`mipsel-unknown-netbsd`] (rust-lang/rust#117356) Refer to Rust's [platform support page][platform-support-doc] for more information on Rust's tiered platform support. Libraries --------- - [Override `Waker::clone_from` to avoid cloning `Waker`s unnecessarily.] (rust-lang/rust#96979) - [Implement `BufRead` for `VecDeque<u8>`.] (rust-lang/rust#110604) - [Implement `FusedIterator` for `DecodeUtf16` when the inner iterator does.] (rust-lang/rust#110729) - [Implement `Not, Bit{And,Or}{,Assign}` for IP addresses.] (rust-lang/rust#113747) - [Implement `Default` for `ExitCode`.] (rust-lang/rust#114589) - [Guarantee representation of None in NPO] (rust-lang/rust#115333) - [Document when atomic loads are guaranteed read-only.] (rust-lang/rust#115577) - [Broaden the consequences of recursive TLS initialization.] (rust-lang/rust#116172) - [Windows: Support sub-millisecond sleep.] (rust-lang/rust#116461) - [Fix generic bound of `str::SplitInclusive`'s `DoubleEndedIterator` impl] (rust-lang/rust#100806) - [Fix exit status / wait status on non-Unix `cfg(unix)` platforms.] (rust-lang/rust#115108) Stabilized APIs --------------- - [`Atomic*::from_ptr`] (https://doc.rust-lang.org/stable/core/sync/atomic/struct.AtomicUsize.html#method.from_ptr) - [`FileTimes`] (https://doc.rust-lang.org/stable/std/fs/struct.FileTimes.html) - [`FileTimesExt`] (https://doc.rust-lang.org/stable/std/os/windows/fs/trait.FileTimesExt.html) - [`File::set_modified`] (https://doc.rust-lang.org/stable/std/fs/struct.File.html#method.set_modified) - [`File::set_times`] (https://doc.rust-lang.org/stable/std/fs/struct.File.html#method.set_times) - [`IpAddr::to_canonical`] (https://doc.rust-lang.org/stable/core/net/enum.IpAddr.html#method.to_canonical) - [`Ipv6Addr::to_canonical`] (https://doc.rust-lang.org/stable/core/net/struct.Ipv6Addr.html#method.to_canonical) - [`Option::as_slice`] (https://doc.rust-lang.org/stable/core/option/enum.Option.html#method.as_slice) - [`Option::as_mut_slice`] (https://doc.rust-lang.org/stable/core/option/enum.Option.html#method.as_mut_slice) - [`pointer::byte_add`] (https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.byte_add) - [`pointer::byte_offset`] (https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.byte_offset) - [`pointer::byte_offset_from`] (https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.byte_offset_from) - [`pointer::byte_sub`] (https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.byte_sub) - [`pointer::wrapping_byte_add`] (https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.wrapping_byte_add) - [`pointer::wrapping_byte_offset`] (https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.wrapping_byte_offset) - [`pointer::wrapping_byte_sub`] (https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.wrapping_byte_sub) These APIs are now stable in const contexts: - [`Ipv6Addr::to_ipv4_mapped`] (https://doc.rust-lang.org/stable/core/net/struct.Ipv6Addr.html#method.to_ipv4_mapped) - [`MaybeUninit::assume_init_read`] (https://doc.rust-lang.org/stable/core/mem/union.MaybeUninit.html#method.assume_init_read) - [`MaybeUninit::zeroed`] (https://doc.rust-lang.org/stable/core/mem/union.MaybeUninit.html#method.zeroed) - [`mem::discriminant`] (https://doc.rust-lang.org/stable/core/mem/fn.discriminant.html) - [`mem::zeroed`] (https://doc.rust-lang.org/stable/core/mem/fn.zeroed.html) Cargo ----- - [Add new packages to `[workspace.members]` automatically.] (rust-lang/cargo#12779) - [Allow version-less `Cargo.toml` manifests.] (rust-lang/cargo#12786) - [Make browser links out of HTML file paths.] (rust-lang/cargo#12889) Rustdoc ------- - [Accept less invalid Rust in rustdoc.] (rust-lang/rust#117450) - [Document lack of object safety on affected traits.] (rust-lang/rust#113241) - [Hide `#[repr(transparent)]` if it isn't part of the public ABI.] (rust-lang/rust#115439) - [Show enum discriminant if it is a C-like variant.] (rust-lang/rust#116142) Compatibility Notes ------------------- - [FreeBSD targets now require at least version 12.] (rust-lang/rust#114521) - [Formally demote tier 2 MIPS targets to tier 3.] (rust-lang/rust#115238) - [Make misalignment a hard error in `const` contexts.] (rust-lang/rust#115524) - [Fix detecting references to packed unsized fields.] (rust-lang/rust#115583) - [Remove support for compiler plugins.] (rust-lang/rust#116412)
Based on this discussion in Zulip.
The values for x86 and x86_64 are complete guesswork on my side, and I have no clue what the values might be for other architectures. I hope we can get the right people to chime in to gather the required information. :)
I'll update Miri to respect these rules once we have more data.