funct(3rtapi)
β¨ funct(3rtapi) β¨
okay bestie, welcome to funct(3rtapi) from the RTAPI manual π this one is short but it's lowkey a big deal, so let's get into it π«Ά
πΈ NAME πΈ
rtapi_atomic β it's a subset of C11 <stdatomic.h>, no cap β¨
π SYNTAX π
#include <rtapi_atomic.h>
enum memory_order { ... };
#define atomic_store(obj, desired)...
#define atomic_store_explicit(obj, desired, order)...
#define atomic_load(obj)...
#define atomic_load_explicit(obj, order)...
yes it's giving macros, yes it's giving enum, and yes every single one of those ...s is doing heavy lifting π§
π ARGUMENTS π
volatile A* objβ a pointer to a volatile object. It's either the destination of the store or the source of the load, depending on which one you're calling. The pointer has to have the right type and alignment so that the underlying store or load operation is itself atomic. At the absolute minimum you can assume a properly aligned"int"is one of those types. And listen β if the size or alignment is wrong, that's an undiagnosed error. like, nobody's gonna tell you. it'll just be wrong. πC desiredβ the value you're storing into the object.*obj = desiredhas to be well-formed. that's the whole vibe check β¨memory_order orderβ the required memory ordering semantic. it's the vibe of the ordering, if you will π«
π¦ DESCRIPTION π¦
So this header provides at least the subset of C11's <stdatomic.h> shown above. That "at least" is doing work β there might be more, there might not, but this is the guaranteed floor π«Ά
Now here's the part that actually matters. When you have an ordering requirement for multiple values that are being read or written in RTAPI shared memory areas by other threads of execution β and yes, that includes the values of HAL pins and parameters β these functions (or function-like macros, same thing here) are the only way to make sure that ordering requirement is obeyed. periodt.
Otherwise? according to architecture-specific rules, loads and stores may get reordered from their normal source code order. your code says one thing, the CPU does another. iconic behavior honestly but not what you want π
For example β say you wanna leave a message in a shared memory area from one thread and pick it up from another. The writer must use an atomic store for the "message is complete" variable, and the reader must use an atomic load when it checks that variable:
// producer
*message = 42;
atomic_store_explicit(message_ready, 1, memory_order_release);
// consumer
while(atomic_load_explicit(message_ready, memory_order_acquire) == 0) sched_yield();
printf("message was %d\n", *message); // must print 42
see that memory_order_release on the way out and memory_order_acquire on the way in? that's the handshake bestie π€ and that comment // must print 42 is not a suggestion, it's a promise π
β‘ REALTIME CONSIDERATIONS β‘
May be called from any code. that's it, that's the whole section, she's easygoing π
β RETURN VALUE β
atomic_loadandatomic_load_explicitreturn the value pointed to by theobjargument. you asked, she delivers πatomic_storeandatomic_store_explicithave no return value. they're givers, not takers π
π SEE ALSO π
<stdatomic.h>(C11) β the real one, the original, the blueprint π<rtapi_bitops.h>β for other atomic memory operations supported by rtapi β¨
and that's the whole page bestie, you ate it π go forth and be atomic, and remember: no ordering, no guarantees, no cap π
LinuxCNC Documentation Β· 2006-10-12 Β· funct(3rtapi) β mwah, sending u a kiss, this page is old enough to be your cool auntie and she still slays ππ
π¦ where this page comes from
- debian bookworm: linuxcnc-uspace-dev 2.9.0~pre1+git20230208.f1270d6ed7-1+deb12u2 Β· GFDL-1.1-or-later
- debian trixie: linuxcnc-uspace-dev 1:2.9.4-2+deb13u1 Β· GFDL-1.1-or-later
- ubuntu questing: linuxcnc-uspace-dev 1:2.9.4-2ubuntu2
- ubuntu resolute: linuxcnc-uspace-dev 1:2.9.4-2ubuntu4 Β· GFDL-1.1-or-later
- ubuntu stonking: linuxcnc-uspace-dev 1:2.9.4-2ubuntu4 Β· GFDL-1.1-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms