Description
So it looks like mixed-size-accesses made the round on twitter again recently which got me thinking about them. rust-lang/rust#97516 carefully chose not to talk about them (and anyway it's not clear that is the right place to go into more detail about them). So what do we want to do with them in Rust?
Some facts:
-
In C++, you cannot convert a
&uint16_t
into an reference to an array "because no such array exists at that location in memory"; they insist that memory is strongly typed. This means they don't even have to talk about mixed-size accesses. It also means they are ignoring a large fraction of the programs out there but I guess they are fine with that. We are not. ;) -
Apparently the x86 manual says you "should" not do this: "Software should access semaphores (shared memory used for signalling between multiple processors) using identical addresses and operand lengths." It is unclear what "should" means (or what anything else here really means, operationally speaking...)
-
In Rust, it is pretty much established that you can safely turn a
&mut u16
into a&mut [u8; 2]
. So you can do something where you start with a&mut AtomicU16
, do some atomic things to it, then use the above conversion and get a&mut AtomicU8
and do atomic things with that -- a bona fide mixed-size atomic access.However, this means that there is a happens-before edge between all the 16-bit accesses and the 8-bit accesses. Having the
&mut
means that there is synchronization. I hope this means not even Intel disagrees with this, but since literally none of the words in that sentence is defined, who knows.
So... it seems like the most restrictive thing we can say, without disallowing code that you can already write entirely safely using bytemuck, is that
- it is allowed to do differently-sized atomic accesses to the same location over time,
- but only if any two not-perfectly-overlapping accesses are completely synchronized through other means (i.e., it is not these accesses themselves that add a happens-before edge, there already exists a happens-before edge through other accesses).
- Any other kind of mixed-size access is UB.