CXX and atomic instructions

Post Reply

Topic author
mberryman
Active Contributor
Posts: 27
Joined: Sat Sep 02, 2023 1:31 pm
Reputation: 0
Location: Colorado Springs, CO, USA
Status: Offline

CXX and atomic instructions

Post by mberryman » Mon Nov 06, 2023 2:36 pm

What atomic instructions are available to the C++ compiler on x86? I've been using __ATOMIC_EXCH_LONG, __CMP_SWAP_LONG_ACQ, and similar.


jhamby
Contributor
Posts: 22
Joined: Wed Oct 04, 2023 8:59 pm
Reputation: 0
Status: Offline

Re: CXX and atomic instructions

Post by jhamby » Wed Nov 08, 2023 3:41 pm

Use std::atomic (C++11). I figured this one out while looking at libuv, which is written in C and uses <stdatomic.h> from C11, which isn't present in the VMS C RTL.

It's a total hack, but I discovered that I could compile the libuv code as C++ (after adding some casts and other needed changes), change the include to <atomic>, and change "_Atomic int" to "atomic_int". The Clang version of the C++ header file includes both the C++ atomic<> class and all the C functions in <stdatomic.h> (in std:: or you can use the namespace).

https://en.cppreference.com/w/cpp/header/stdatomic.h
https://en.cppreference.com/w/cpp/atomic/atomic

Typical uses of the C API in libuv:

Code: Select all

version = atomic_load_explicit(&cached_version, memory_order_relaxed);
atomic_store_explicit(&cached_version, version, memory_order_relaxed);
atomic_fetch_add(busy, 1);
atomic_fetch_add(busy, -1);
atomic_exchange(pending, 1);
One thing I noticed right away in the VMS version of the header file (due to color syntax highlighting) is that the first 550 lines are commented out, and the actual implementation starts below that. I was worried there might be something not implemented yet, but it looks like it's all there, below the commented-out block.
Last edited by jhamby on Wed Nov 08, 2023 3:48 pm, edited 1 time in total.


jhamby
Contributor
Posts: 22
Joined: Wed Oct 04, 2023 8:59 pm
Reputation: 0
Status: Offline

Re: CXX and atomic instructions

Post by jhamby » Sun Nov 12, 2023 4:49 pm

I learned a few details about std::atomic on OpenVMS that may be of interest. std::atomic<> is typically lock-free for types that are atomic in hardware (up to 64 bits on x86, if suitably aligned), but it also supports larger types with a hidden lock.

Sadly, the VMS runtime support is currently missing for those types. There's an .is_lock_free() method in C++11 and a const member is_always_lock_free (for compile-time testing) added in C++17. Trying them on OpenVMS, you can't use .is_lock_free() or "is_always_lock_free" on non-primitive types because libcxx is missing __atomic_is_lock_free. They both return true for bool, pointers, etc. (you need /stand=cxx17 to see is_always_lock_free).

Similarly, if you try to load or store to a non-lock-free atomic type, you get an undefined __atomic_load or __atomic_store. I tried to use them for a pointer type in the project I'm working on, and I discovered some limitations of this C++ type, namely that it doesn't have a simple constructor and turns containing structs into non-POD types, which means C-style code doing stuff like putting the struct inside a union or using a macro to get the offsetof() a member or to find the containing struct given a pointer to an inner one gives a compiler warning about being a non-POD type.

So my "just use this" advice turned out to be full of limitations. The best talk I've seen on using C++ atomics is Fedor Pikus's 2017 CppCon talk. Highly recommended. https://youtu.be/ZQFzMfHIxng?si=CpD68zQw3WjLszAK
Last edited by jhamby on Sun Nov 12, 2023 4:50 pm, edited 1 time in total.


jreagan
VSI Expert
Master
Posts: 139
Joined: Tue Dec 01, 2020 8:40 am
Reputation: 0
Status: Offline

Re: CXX and atomic instructions

Post by jreagan » Sun Nov 12, 2023 10:28 pm

I'll have somebody look into this.

Post Reply