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 = desired has 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_load and atomic_load_explicit return the value pointed to by the obj argument. you asked, she delivers πŸ‘‘
  • atomic_store and atomic_store_explicit have 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 πŸ‘‘πŸ’–