Heh, 10 years ago I gave a presentation about how easy folks used to x86 can trip up when dealing with ARM's weaker memory model. My demonstration then was with a naive implementation of Peterson's algorithm.[1] I have a feeling that we will see a sharp rise of stories like this, now that ARM finds itself in more places which were previously mostly occupied by x86, and all the subtle race conditions that x86's memory…
I doubt that. The number of ARM processors is far greater in reality than in x86 if we clarify it by saying “in operation” rather than historically and these stories will become more common but certainly won't see a “sharp increase”.
A bug that doesn’t exist on x86: Exploiting an ARM-only race condition
71–80 of 141 posts
Re: A bug that doesn’t exist on x86: Exploiting an ARM-only race condition
#72Either I'm not understanding something that I thought I understood very well, or TFA's author's don't understand something that they think they understand very well. Their code is unsafe even on x86. You cannot write a single-writer, single-reader FIFO on modern processors without the use of memory barriers. Their attempt to use "volatile" instead of memory barriers is not appropriate. It could easily cause problems…
Re: A bug that doesn’t exist on x86: Exploiting an ARM-only race condition
#73Earlier quoted context omitted.
Memory ordering gets somewhat easier after you understand that flat memory shared by execution units is a leaky abstraction desperately patched over decades by layer and layers of hardware and software. Memory ordering is one way to represent message passing and synchronization between different cores and RAM. This why I think that "lock-free algorithms" is a misnomer, you still have synchronization, but you simply r…
Is there anything out there that exposes a better or tighter abstraction? Something not flat?
But that's just bad for running general purpose software that can require more memory than available locally since it means you have to do memory cache management in software which is going to be much slower than letting the hardware do it.
Re: A bug that doesn’t exist on x86: Exploiting an ARM-only race condition
#74I spent some time trying to figure out why the lock-free read/write implementation is correct under x86, assuming a multiprocessor environment. My read of the situation was that there's already potential for a double-read / double-write between when the spinlock returns and when the head/tail index is updated. Turns out that I was missing something: there's only one producer thread, and only one consumer thread. If t…
Indeed. It's not safe under x86 either.
Re: A bug that doesn’t exist on x86: Exploiting an ARM-only race condition
#75Either I'm not understanding something that I thought I understood very well, or TFA's author's don't understand something that they think they understand very well. Their code is unsafe even on x86. You cannot write a single-writer, single-reader FIFO on modern processors without the use of memory barriers. Their attempt to use "volatile" instead of memory barriers is not appropriate. It could easily cause problems…
Another "correct" use of volatile is a hack to prevent compilers from optimizing away certain code. It's pretty rare to need that and often you can just use a lower optimization level (like the usual -O2) but sometimes you need -O3 / -Ofast or something and a strategic volatile type def to keep everything working.
A classic example is Kahan summation algorithim. At -O2 it's fine. At -O3 or higher it silently defeats the algorithm while appearing to work (you get a sum but without the error compensation). Defining the working vars as volatile makes it work again. This is noted in the wikipedia pseudocode with the comment "// Algebraically, c should always be zero. Beware overly-aggressive optimizing compilers!"
https://en.wikipedia.org/wiki/Kahan_summation_algorithm
Of course -O3 might not be any faster anyway but that's another topic.
Re: A bug that doesn’t exist on x86: Exploiting an ARM-only race condition
#76There is a proposal (possibly accepted) to deprecate 'volatile' in C++. http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p115...
Yes P1152 was taken for C++ 20. The purpose of abolishing volatile isn't so much to reinforce that it's not intended for this sort of threading nonsense (indeed on Windows the MSVC guarantees mean it almost is intended for this sort of nonsense) but to make it explicit that "volatile variables" were never really a thing anyway by abolishing the volatile qualifier on variables. The thing your hardware can actually do…
It means exactly the same thing as on a normal variable, and it boggles the mind that people somehow not understand that. Given 'volatile int i', 'i++' means the exact same thing as 'i = i + 1'. Does that also not make any sense to you? If it does, can you explain why you believe they are different?
Volatile member functions and parameters make no sense, but volatile member variables most certainly do. And there is considerable pushback in the C++ community because this is a significant loss of compatibility with various C-headers used frequently in embedded applications. I wouldn't be surprised if the deprecated features will be reinstated in the language in the end.
Re: A bug that doesn’t exist on x86: Exploiting an ARM-only race condition
#77Either I'm not understanding something that I thought I understood very well, or TFA's author's don't understand something that they think they understand very well. Their code is unsafe even on x86. You cannot write a single-writer, single-reader FIFO on modern processors without the use of memory barriers. Their attempt to use "volatile" instead of memory barriers is not appropriate. It could easily cause problems…
Re: A bug that doesn’t exist on x86: Exploiting an ARM-only race condition
#78Either I'm not understanding something that I thought I understood very well, or TFA's author's don't understand something that they think they understand very well. Their code is unsafe even on x86. You cannot write a single-writer, single-reader FIFO on modern processors without the use of memory barriers. Their attempt to use "volatile" instead of memory barriers is not appropriate. It could easily cause problems…
Re: A bug that doesn’t exist on x86: Exploiting an ARM-only race condition
#79Either I'm not understanding something that I thought I understood very well, or TFA's author's don't understand something that they think they understand very well. Their code is unsafe even on x86. You cannot write a single-writer, single-reader FIFO on modern processors without the use of memory barriers. Their attempt to use "volatile" instead of memory barriers is not appropriate. It could easily cause problems…
> "volatile" does not mean what you think it means; if you're using it for anything other than interacting with hardware registers in a device driver, you're almost certainly using it incorrectly. Another "correct" use of volatile is a hack to prevent compilers from optimizing away certain code. It's pretty rare to need that and often you can just use a lower optimization level (like the usual -O2) but sometimes you…
Do you have anything to actually support this statement or did you just assume “overly aggressive optimizing compilers” and “O3” are somehow linked?
Generally optimization levels may find more opportunities to exploit UB, but they do not change the semantics of the language, and all languages I’m familiar with define floating point as a non-associative operation because it’s not when you’re working with finite precision.
TLDR: Don’t use volatile unless you really know what you’re doing, and unless you know C/C++ really well, you probably do not. If anyone tells you to throw in a volatile to “make things work”, it’s most likely cargo curling bad advice (not always, but probably).
Re: A bug that doesn’t exist on x86: Exploiting an ARM-only race condition
#80Earlier quoted context omitted.
emulator would have a zero issue, if it's a direct transfer for assembly (not an emulator), it'd need either hardware support - e.g. apple chips, or memory barriers. The differences between arm and x86 are known for 15y+, there is nothing new about it. Also concurrency support is one of the major benefits of languages with proper memory model - java started it with JMM[0] [0]: https://www.cs.umd.edu/~pugh/java/memory…
Any emulator that wants to be remotely performance competitive will do dynamic translation (i.e JIT). In fact ahead-of-time translation is not really feasible. Memory models and JVM are not really relevant when discussing running binaries for a different architecture.