On 12/14/24 7:31 PM, andy pugh wrote:
HAL processes run in strict sequence, so most realtime components
probably don't access the same memory at the same time.
The exceptions are where there are both base threads and a servo
thread, and possibly where there is access to HAL pins from user-space
(and, maybe from the G-code (but I think that G-code HAL pin access is
read-only))
No multi-threaded application is helped or fixed by using volatile. On
any CPU it is almost always wrong to use volatile and always wrong in a
multi-threaded context. This was pointed out by Robert linking to
https://github.com/torvalds/linux/blob/master/Documentation/process/volatile-considered-harmful.rst.
Things change with SMP and it gets worse when CPUs do things differently
internally than their programing-model would suggest. And, there are now
many types of memory and none of which you control as a programmer
anymore. You need to use different primitives.
MMIO is generally the only place left where volatile is actually needed.
Because it instructs the compiler not to rely on previous contents of
the same location. And that is fine and sometimes essential for hardware
access.
In multi-threaded application you primarily need to ensure that only
_whole_ variables can be read or written without interference. Atomicity
is the key. And preferably lock-less atomicity whenever possible.
A second problem you need to address is the _order_ of reads and writes.
Modern CPUs can reorder any access (for normal memory). Sometimes you
want to ensure that a very specific order is achieved and must be
visible to other threads in exactly that order.
None of these problems are solved by volatile and any attempt is plain
wrong.
From what I have seen of the functions that update in a base thread
(stepgen, encoder, etc) there is a fair degree of care taken to avoid
the base thread treading on the toes of the servo thread.
There is, conversely, no car taken by the GUIs that access HAL pins,
but in most cases that probably doesn't matter.
There is a low-level access function, I believe, that has some
precautions built into it. I have not yet looked all the way own the
rabbit hole, but I think accesses are probably fine.
But I think it would take exhaustive testing with real hardware to
check if volatile is needed and even then it would be hard to be sure
that you had tested all corners of the behaviour.
That I think would be a good thing to do. That is why I ran it on the
RPi5 with an 7C80 attached and tortured it slightly. But, yes, it needs
to be run on real hardware.
That said, the use of volatile previously did not do what you expected.
It simply didn't do anything for most, if not all, access to shared
memory because it was cast into non-volatile all the time. That part I'm
still looking into. But, if my suspicion is confirmed, then all the
volatiles were simply unused ballast and cast away anyway.
I get the feeling that the "volatile" directives were put in as a
prophylactic , best-effort measure. They may or may not be useful. But
are they harmful?
Probably done as an "it should not hurt" effort. However, using volatile
on shared variables in a multi-threaded context is wrong, plain and
simple, and therefore actually harmful.
--
Greetings Bertho
(disclaimers are disclaimed)
_______________________________________________
Emc-developers mailing list
Emc-developers@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/emc-developers