Hello, some architectures have instructions to atomically load 2 words, like cmpxchg16b
on x86_64. I don't think AtomicU128
is an answer, because there might be 32-bit architectures that allow 64 bit loads. That's why we have AtomicUnsize
. Can we then have something like AtomicDoubleUsize
or something similar?
You could define it yourself:
#[cfg(target_pointer_width = "16")]
pub type AtomicDoubleUsize = std::sync::atomic::AtomicU32;
#[cfg(target_pointer_width = "32")]
pub type AtomicDoubleUsize = std::sync::atomic::AtomicU64;
#[cfg(target_pointer_width = "64")]
pub type AtomicDoubleUsize = std::sync::atomic::AtomicU128;
HjVT
July 20, 2024, 4:35pm
3
But this assumes that native register size is == pointer size == there is support for atomic operations with wish double of that
eggyal
July 20, 2024, 6:05pm
4
Under strict provenance, there are issues with using (atomic) integer types to hold pointers—which makes even having an AtomicDoubleUsize
type or similar of limited use in such cases.
I raised this very concern in the unsafe code guidelines issue tracker a couple of days ago, and there has been some interesting discussion there since.
opened 06:57PM - 17 Jul 24 UTC
Under [Using Strict Provenance](https://doc.rust-lang.org/std/ptr/index.html#usi… ng-strict-provenance), the standard library documents:
> (Yes, if you’ve been using AtomicUsize for pointers in concurrent datastructures, you should be using AtomicPtr instead. If that messes up the way you atomically manipulate pointers, we would like to know why, and what needs to be done to fix it.)
(I've not been able to locate a discussion similar to the following, and assume that this is the best place to reply to that invitation—but please do point me elsewhere if not!).
Some concurrent algorithms (I am particularly thinking of some epoch-based memory reclamation schemes) solve the ABA problem by packing both a pointer and an integer (e.g. an epoch) into a single (double-word width) atomic variable (e.g. a 128-bit atomic, manipulated using `cmpxchg16b`, on x86_64 architectures).
To do this with the existing atomic types requires using the appropriate double-word width atomic integer (e.g. `AtomicU128` on 64-bit architectures), and converting the relevant single-word width subpart to/from a pointer.
If such pointer may be to different allocated objects over the course of the algorithm, it clearly is not possible to derive provenance in those conversions via strict provenance's `.with_addr()` method (because any "base" pointer from which provenance is derived would also have to be updated atomically with any update to this atomic).
I am not sure what the best solution to this might be. Perhaps something like an `AtomicDoublePtr<T, U>` type or similar?
Somewhat related to #286 and #480.
4 Likes
farnz
July 21, 2024, 10:55am
5
That sounds like we should have both AtomicDoubleUsize
and AtomicDoublePtr
, with the same relationship as AtomicUsize
and AtomicPtr
.
2 Likes
kornel
July 21, 2024, 11:24pm
6
There's also #[cfg(target_has_atomic="128")]
which could be used to provide a fallback like Mutex
.
1 Like
system
Closed
October 19, 2024, 11:25pm
7
This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.