-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Add Atomic*::from_mut. #74532
Add Atomic*::from_mut. #74532
Conversation
r? @cramertj (rust_highfive has picked a reviewer for you, use r? to override) |
This assumes the integral types have the same alignment requirement as their atomic equivalent on all platforms that support those. (This is definitely the case for |
The only platforms where the integer sizes don't match their alignment seem to be:
(Found by The MSP430 supports atomics up to 16 bits (although not supported by llvm nor Rust), and aligns The AVR target doesn't specify a Edit: 32-bit x86 is also a problem for 64-bit atomics. See below. |
On i686-unknown-linux-gnu, |
Thanks! Looks like my grep command didn't give what I was looking for ^^' This works better: fn main() {
for triple in rustc_target::spec::get_targets() {
let target_triple = rustc_target::spec::TargetTriple::from_triple(&triple);
let target = rustc_target::spec::Target::search(&target_triple).unwrap();
let layout = rustc_target::abi::TargetDataLayout::parse(&target).unwrap();
if
layout.i8_align.abi.bits() != 8 ||
layout.i16_align.abi.bits() != 16 ||
layout.i32_align.abi.bits() != 32 ||
layout.i64_align.abi.bits() != 64
{
print!("{:<30}", triple);
print!("{:>4}", layout.i8_align.abi.bits());
print!("{:>4}", layout.i16_align.abi.bits());
print!("{:>4}", layout.i32_align.abi.bits());
print!("{:>4}", layout.i64_align.abi.bits());
println!(" ({})", target.max_atomic_width());
}
}
}
Apart from the two I already mentioned, looks like I missed only intel x86, which is only a problem for 64-bit atomics. I see a lot of discussion on llvm/gcc lists/trackers about whether i64 should've been 64-bit aligned or whether a 64-bit atomic should maybe be 32-bit aligned, but unfortunately this is how things are now. :) Which path forward makes most sense?
3 would work and still be useful, but would become a problem if a platform gets added with 32-bit atomics and 16-bit aligned |
I guess a motivating example for this change makes sense at this point. I want to work towards not only a fn calculate_things(buffer: &mut [u32]) {
let buffer: &[AtomicU32] = AtomicU32::from_mut_slice(buffer);
crossbeam_utils::thread::scope(|s| {
for i in 0..n_threads {
s.spawn(|_| {
// do work and add stuff to `buffer`.
});
}
}).unwrap();
} Whether threads and atomics are used should be transparent to the caller. All it should know is that it needs to give mutable access to a buffer of C++20 also has something similar in the form of |
This comment has been minimized.
This comment has been minimized.
@m-ou-se Ping from triage: can you please address the merge conflict? |
e52cd6d
to
42fa4cf
Compare
Another option is to expect users to use |
42fa4cf
to
09fff5f
Compare
r? @KodrAus |
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.
This seems worthwhile to me, because it's probably not really obvious that integers might have different alignments to their atomic equivalents. I've created a tracking issue we can use: #76314
Should we also consider AtomicIsize
and AtomicUsize
where possible?
/// ``` | ||
#[inline] | ||
#[unstable(feature = "atomic_from_mut", issue = "none")] | ||
pub fn from_mut(v: &mut *mut T) -> &Self { |
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.
This one seems a little strange to me, since *mut T
is already a pointer.
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.
Just like AtomicU16::from_mut
will take a &mut u16
, AtomicPtr<T>::from_mut
should take a &mut
to the non-atomic type: &mut *mut T
. The already existing AtomicPtr<T>::get_mut()
also returns a &mut *mut T
: https://doc.rust-lang.org/stable/core/sync/atomic/struct.AtomicPtr.html#method.get_mut
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.
@KodrAus The pointer itself is what atomic here, not what it points to, so when using is you actually use a pointer to the atomic pointer (otherwise you'll be copying the atomic pointer)
📌 Commit 7cc2569 has been approved by |
…m-mut, r=KodrAus Add Atomic*::from_mut. The atomic equivalent of [`Cell::from_mut`](https://doc.rust-lang.org/stable/std/cell/struct.Cell.html#method.from_mut).
☀️ Test successful - checks-actions, checks-azure |
Seems like this breaks libc CI, see https://dev.azure.com/rust-lang2/libc/_build/results?buildId=3161&view=logs&j=c7464085-50dc-55b0-d49a-ca2fc4e4d69e&t=7417e154-0538-5077-3a89-29444dec6e1c&l=430. |
@JohnTitor The error you linked is for 64 bit atomics. Is your target file correct? Does armv7 have 64 bit atomics? Edit: I'll take a closer look tomorrow. |
Given this, it has 64-bit atomics, right? |
#[inline] | ||
#[unstable(feature = "atomic_from_mut", issue = "76314")] | ||
pub fn from_mut(v: &mut *mut T) -> &Self { | ||
let [] = [(); align_of::<AtomicPtr<()>>() - align_of::<*mut ()>()]; |
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.
This will assert that their alignment is equal right? But shouldn't we rather test that Self
alignment is no stricter than that of the pointer? You can use the static_assert
macro to write any kind of boolean test.
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.
Btw, if you know of any other place that uses the such an array length hack to encode a static assertion, please let me know -- we should add a FIXME at least.
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.
get_mut
already assumes that the alignment of the non-atomic type is ≤ the alignment of the atomic variant. from_mut
technically only needs ≥, but things would be quite broken if it was > instead of just =.
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.
You can use the
static_assert
macro to write any kind of boolean test.
Can I depend on that in core
? I don't think core
has any dependencies right now.
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.
Oh right, you cannot directly use it.
But personally I feel like it'd be worth copying it to libcore and then using it there as an internal macro. That said, it seems you will have to rework this entire thing anyway so let's see where that goes.
The test failure is caused by the alignment check. And while I think the check can be relaxed (and written in a more readable way than an array length hack), I am not sure this is sufficient... there are platforms where |
Yes. This PR disables some conversions that shouldn't exist, but does so using |
Ah I see. That seems rather subtle, both in terms of accidentally writing non-portable code and (if you happen to work on a platform where this is not available) not realizing why the function is missing. But that's a discussion for the tracking issue, 'll raise my points there. |
It seems appropriate to me to revert this PR, both to take time pressure off of you and to get broken users fixed ASAP. Developing an alternative approach looks like it could take some time. "Revert" doesn't mean "we'll never land this", it means "this PR had some unforeseen problems so let's take it back and then re-considering landing with what we learned". |
I have the PR that fixes this properly ready! Just running the tests locally first :) |
Seems to work 🎉 #76965 |
Notes to self:
|
Okay, implementing it went quicker than I expected, but since this is now a language addition, there might be extra process here -- IIRC we've had RFCs for new Maybe open a thread in the t-lang stream on Zulip to get some lang team people to comment on that. |
All the cfg() flags for atomics are unstable (gated behind If this PR doesn't go through quickly, I'll send a PR to revert this one first. |
Ah, if there's precedent for "ad-hoc" new atomic cfg flags then please link to that in the other PR. |
Oh... I missed all of this going on here 😟 Sorry everyone! |
…mic-from-mut, r=kodrAus Revert adding Atomic::from_mut. This reverts rust-lang#74532, which made too many assumptions about platforms, breaking some things. Will need to be added later with a better way of gating on proper alignment, without hardcoding cfg(target_arch)s. --- To be merged if fixing from_mut (rust-lang#76965) takes too long. r? @ghost
…mic-from-mut, r=kodrAus Revert adding Atomic::from_mut. This reverts rust-lang#74532, which made too many assumptions about platforms, breaking some things. Will need to be added later with a better way of gating on proper alignment, without hardcoding cfg(target_arch)s. --- To be merged if fixing from_mut (rust-lang#76965) takes too long. r? @ghost
As mentioned on the PR for it, adding this new feature-gated cfg looks like a good solution to me from a language perspective. |
…-from-mut, r=Amanieu Add cfg(target_has_atomic_equal_alignment) and use it for Atomic::from_mut. Fixes some platform-specific problems with rust-lang#74532 by using the actual alignment of the types instead of hardcoding a few `target_arch`s. r? @RalfJung
…-from-mut, r=Amanieu Add cfg(target_has_atomic_equal_alignment) and use it for Atomic::from_mut. Fixes some platform-specific problems with rust-lang#74532 by using the actual alignment of the types instead of hardcoding a few `target_arch`s. r? @RalfJung
The atomic equivalent of
Cell::from_mut
.