ARM is free to reorder stores and loads. This is called a weak memory model. So unless it's explicitly told to the compiler, like C++ memory_order::acquire and memory_order::release, you might get invalid behavior. Heisenbugs in the worst case.
Like:
a=fooMethod(); b=otherMethod()
Will this be reordered?
That said, I've never actually run into one of these issues.
Also most software runs on ARM now and I don't think that has actually happened in practice.
At least in my house, ARM cores outnumber x86 cores by at least four to one. And I'm not even counting the 32-bit ARM cores in embedded devices.
There is a lot of space for memory ordering bugs to manifest in all those devices.
x = *a;
if (x) y = *b;
The compiler cannot reorder the load of b before the load of a, because it may not be a valid pointer if x is false. But the CPU is free to speculate long ahead, and if the pointer in b isn't valid, that's fine, the CPU can attempt a speculative load and fail.It's not particularly common and code that has this issue will probably crash only rarely, but it's not too hard to do.
Imagine that code was paired with code in another thread that did:
*b = newValue;
barrier();
*a = 1;
We put a barrier here to ensure the stores don't get reordered, since we must write out the new value in b before writing out the flag in a that tells the other code to use it.Paired with this, my example above will work fine on an architecture with strong ordering, but will potentially get a bad value into y on archs with weak ordering. The reader may fetch the value in b first, getting the value before the reassignment. It may then fetch the value in a and see 1. This will cause it to use the old value loaded from *b, which is semantically incorrect in this case even though it's perfectly correct according to the architecture and the language spec.
Correct code here would need an acquire barrier on the load of a, paired with a release barrier on the store.
It's a fun perception. For the longest time, all the "serious" computers were used through networks and terminals and didn't even come with any ability to connect a monitor or a keyboard (although a serial terminal would work as the system console). I used to joke (usually looking at Unisys Windows-based big servers), if the computer had VGA and PS/2 ports, it wasn't a computer, but a toy. Those Unisys servers weren't toys, but you could run Pinball and Minesweeper directly on them, which kind of said otherwise.
I think we got used to such levels of platform bloat that we don't care if the UI toolkit these days is bigger than the entire operating system that runs 95% of the world's payment transactions.
It is the Year of Desktop Linux that keeps being inundated with Electron crap, to detriment of Gtk, Qt, KDE, and whatever else is out there.
*a = 1;
*b = 'p';
both the compiler and the CPU can freely pick the order in which those two happen (or even execute them in parallel, or do half of one first, then the other, then the other half of the first, but I think those are hypothetical cases)x86-64 will never do such a swap, but x86-64 compilers might.
If you write
*a = 1;
*b = 2;
, things might be different for the C compiler because a and b can alias. The hardware still is free to change that order, though.As you'd expect, Linux distribution support for big- and little-endian varies.
Developed on Intel i860, then MIPS, and only then on x86, alongside Alpha.
Intel let the i860 and indeed the slightly older i960 wither, which was a damned shame. Ditto the Alpha it ended up with, while it sold its Arm licence to Marvell, which at one point recently was worth more than Intel.
I'd like to see a skunkworks project to resurrect one, or several, of these. :-) Attack Arm from a direction it's not expecting. And RISC-V come to that.
Compilers can only be relied on to emit code that's correct in terms of the language spec, not the programmer's intent.