Em 04/08/2025 08:15, Roberto A. Foglietta escreveu:
On Mon, 4 Aug 2025 at 13:11, Denys Vlasenko <[email protected]> wrote:
The correct fix is to specify the pointer in question as "volatile"
variable, so that gcc stops making assumptions about its liveness.
You are right as a manual, Denis.
...but god knows what gcc does with a volatile which is not associated
with a hardware I/O line. (LOL)
Compilers never cared about this. "volatile" in C is very well defined:
it simply means every time the memory location is accessed, the compiler
must issue a fresh read.
And that's *all* it does, which is quite often "not enough". It is
indeed a real pitfall that has claimed a lot of victims over the years.
volatile isn't "read once" or "write once": the compiler can output code
that will read a volatile variable many times even if the load shows up
only once in the source code. In fact, declaring something volatile
INCREASES the chances the compiler will load it more than once.
volatile isn't a compile barrier: the compiler can still move the
loads/stores to volatile variables around, unless something else in the
code forbids it to. It must not reorder loads and stores to the same
volatile variable, and it must not elide loads because it just stored
something and that data is still in a register, but that's it.
volatile loads and stores are not atomic, and they are not synchronizing
(memory barriers) either. A store to a volatile variable can result
into the compiler generating read-modify-write code for some types, for
example. There is *nothing* in volatile that ensures no mixing of
concurrent writes won't be observed by a concurrent reader. Evidently,
there is also no implied ordering between reads or writes from separate
hardware threads.
Granted, some CPU architectures might give you atomic behavior on
load/store of for some types "for free", and paper over *some* such bugs
on code that misused volatile. E.g. x86 and x86-64 are not going to
allow a concurrent load to observe a mixed concurrent writes for aligned
int32_t (among many other types). This still gives you no
synchronization, and a stored value by one hardware thread might take
its sweet time to become visible to other hardware threads.
Now, when doing memory-mapped I/O, *SOME* architectures will have
specific hardware access modes (e.g. uncached) for that address space
region, which may paper over some of the above issues. Some would call
C code that depends on such behavior buggy.
So, when two threads of execution could access the same memory location
(and that certainly includes parent and child from fork() and friends),
if any of these accesses could be a store or you need ordering of any
sort, you will most likely need more than just "volatile" to ensure it
will always behave as intended.
--
Henrique de Moraes Holschuh
Analista de Projetos
Centro de Estudos e Pesquisas em Tecnologias de Redes e Operações
(Ceptro.br)
+55 11 5509-3537 R.:4023
INOC 22548*625
www.nic.br
_______________________________________________
busybox mailing list
[email protected]
https://lists.busybox.net/mailman/listinfo/busybox