ae2f_docs
c89atomic Directory Reference

Directories

 
extras
 
tests

Files

 
c89atomic.c
 
c89atomic.h

Detailed Description

C89 compatible atomics.

discord

This library aims to implement an equivalent to the C11 atomics library. It's intended to be used as a way to enable the use of atomics in a mostly consistent manner to modern C, while still enabling compatibility with older compilers. This is not a drop-in replacement for C11 atomics, but is very similar. Only limited testing has been done so use at your own risk. I'm happy to accept feedback and pull requests with bug fixes.

The following compilers are supported:

New compilers will use intrinsics. GCC-likes, such as GCC and Clang, will use __atomic_* intrinsics through a pre-processor define and should have no overhead. This uses __GNUC__ to detect GCC-likes.

Old compilers, or compilers lacking support for intrinsics, will use inlined assembly. There are two inlined assembly paths: GCC-style (GAS syntax) and MSVC-style. For an old compiler to be supported, it must support one of these two paths. Note that only 32- and 64-bit x86 is supported for inlined assembly. I have not thouroughly tested the inlined assembly paths. It passes basics tests, but things like memory ordering may have some issues. Advice welcome on how to improve this.

Usage

In most cases you can use this as a header-only library. Just add c89atomic.h to your source tree and include it:

#include "c89atomic.h"

Everything is implemented with defines and inline functions. In some cases there may not be native hardware support for a given atomic operation in which case the library will emulate it with a global spinlock. If you get errors about c89atomic_global_lock being undefined, you need to integrate c89atomic.c into your build. This will not usually be required on modern compilers.

Differences With C11

For practicality, this is not a drop-in replacement for C11's stdatomic.h. Below are the main differences between c89atomic and stdatomic.

Types and Functions

The following types and functions are implemented:

+-----------------------------------------+-----------------------------------------------+
| C11 Atomics | C89 Atomics |
+-----------------------------------------+-----------------------------------------------+
| #include <stdatomic.h> | #include "c89atomic.h" |
+-----------------------------------------+-----------------------------------------------+
| memory_order | c89atomic_memory_order |
| memory_order_relaxed | c89atomic_memory_order_relaxed |
| memory_order_consume | c89atomic_memory_order_consume |
| memory_order_acquire | c89atomic_memory_order_acquire |
| memory_order_release | c89atomic_memory_order_release |
| memory_order_acq_rel | c89atomic_memory_order_acq_rel |
| memory_order_seq_cst | c89atomic_memory_order_seq_cst |
+-----------------------------------------+-----------------------------------------------+
| atomic_flag | c89atomic_flag |
| atomic_bool | c89atomic_bool |
| atomic_int8 | c89atomic_int8 |
| atomic_uint8 | c89atomic_uint8 |
| atomic_int16 | c89atomic_int16 |
| atomic_uint16 | c89atomic_uint16 |
| atomic_int32 | c89atomic_int32 |
| atomic_uint32 | c89atomic_uint32 |
| atomic_int64 | c89atomic_int64 |
| atomic_uint64 | c89atomic_uint64 |
+-----------------------------------------+-----------------------------------------------+
| atomic_flag_test_and_set | c89atomic_flag_test_and_set |
| atomic_flag_test_and_set_explicit | c89atomic_flag_test_and_set_explicit |
+-----------------------------------------+-----------------------------------------------+
| atomic_flag_clear | c89atomic_flag_clear |
| atomic_flag_clear_explicit | c89atomic_flag_clear_explicit |
+-----------------------------------------+-----------------------------------------------+
| atomic_store | c89atomic_store_8 |
| atomic_store_explicit | c89atomic_store_16 |
| | c89atomic_store_32 |
| | c89atomic_store_64 |
| | c89atomic_store_explicit_8 |
| | c89atomic_store_explicit_16 |
| | c89atomic_store_explicit_32 |
| | c89atomic_store_explicit_64 |
+-----------------------------------------+-----------------------------------------------+
| atomic_load | c89atomic_load_8 |
| atomic_load_explicit | c89atomic_load_16 |
| | c89atomic_load_32 |
| | c89atomic_load_64 |
| | c89atomic_load_explicit_8 |
| | c89atomic_load_explicit_16 |
| | c89atomic_load_explicit_32 |
| | c89atomic_load_explicit_64 |
+-----------------------------------------+-----------------------------------------------+
| atomic_exchange | c89atomic_exchange_8 |
| atomic_exchange_explicit | c89atomic_exchange_16 |
| | c89atomic_exchange_32 |
| | c89atomic_exchange_64 |
| | c89atomic_exchange_explicit_8 |
| | c89atomic_exchange_explicit_16 |
| | c89atomic_exchange_explicit_32 |
| | c89atomic_exchange_explicit_64 |
+-----------------------------------------+-----------------------------------------------+
| atomic_compare_exchange_weak | c89atomic_compare_exchange_weak_8 |
| atomic_compare_exchange_weak_explicit | c89atomic_compare_exchange_weak_16 |
| atomic_compare_exchange_strong | c89atomic_compare_exchange_weak_32 |
| atomic_compare_exchange_strong_explicit | c89atomic_compare_exchange_weak_64 |
| | c89atomic_compare_exchange_weak_explicit_8 |
| | c89atomic_compare_exchange_weak_explicit_16 |
| | c89atomic_compare_exchange_weak_explicit_32 |
| | c89atomic_compare_exchange_weak_explicit_64 |
| | c89atomic_compare_exchange_strong_8 |
| | c89atomic_compare_exchange_strong_16 |
| | c89atomic_compare_exchange_strong_32 |
| | c89atomic_compare_exchange_strong_64 |
| | c89atomic_compare_exchange_strong_explicit_8 |
| | c89atomic_compare_exchange_strong_explicit_16 |
| | c89atomic_compare_exchange_strong_explicit_32 |
| | c89atomic_compare_exchange_strong_explicit_64 |
+-----------------------------------------+-----------------------------------------------+
| atomic_fetch_add | c89atomic_fetch_add_8 |
| atomic_fetch_add_explicit | c89atomic_fetch_add_16 |
| | c89atomic_fetch_add_32 |
| | c89atomic_fetch_add_64 |
| | c89atomic_fetch_add_explicit_8 |
| | c89atomic_fetch_add_explicit_16 |
| | c89atomic_fetch_add_explicit_32 |
| | c89atomic_fetch_add_explicit_64 |
+-----------------------------------------+-----------------------------------------------+
| atomic_fetch_sub | c89atomic_fetch_sub_8 |
| atomic_fetch_sub_explicit | c89atomic_fetch_sub_16 |
| | c89atomic_fetch_sub_32 |
| | c89atomic_fetch_sub_64 |
| | c89atomic_fetch_sub_explicit_8 |
| | c89atomic_fetch_sub_explicit_16 |
| | c89atomic_fetch_sub_explicit_32 |
| | c89atomic_fetch_sub_explicit_64 |
+-----------------------------------------+-----------------------------------------------+
| atomic_fetch_or | c89atomic_fetch_or_8 |
| atomic_fetch_or_explicit | c89atomic_fetch_or_16 |
| | c89atomic_fetch_or_32 |
| | c89atomic_fetch_or_64 |
| | c89atomic_fetch_or_explicit_8 |
| | c89atomic_fetch_or_explicit_16 |
| | c89atomic_fetch_or_explicit_32 |
| | c89atomic_fetch_or_explicit_64 |
+-----------------------------------------+-----------------------------------------------+
| atomic_fetch_xor | c89atomic_fetch_xor_8 |
| atomic_fetch_xor_explicit | c89atomic_fetch_xor_16 |
| | c89atomic_fetch_xor_32 |
| | c89atomic_fetch_xor_64 |
| | c89atomic_fetch_xor_explicit_8 |
| | c89atomic_fetch_xor_explicit_16 |
| | c89atomic_fetch_xor_explicit_32 |
| | c89atomic_fetch_xor_explicit_64 |
+-----------------------------------------+-----------------------------------------------+
| atomic_fetch_and | c89atomic_fetch_and_8 |
| atomic_fetch_and_explicit | c89atomic_fetch_and_16 |
| | c89atomic_fetch_and_32 |
| | c89atomic_fetch_and_64 |
| | c89atomic_fetch_and_explicit_8 |
| | c89atomic_fetch_and_explicit_16 |
| | c89atomic_fetch_and_explicit_32 |
| | c89atomic_fetch_and_explicit_64 |
+-----------------------------------------+-----------------------------------------------+
| atomic_thread_fence() | c89atomic_thread_fence |
| atomic_signal_fence() | c89atomic_signal_fence |
+-----------------------------------------+-----------------------------------------------+
| atomic_is_lock_free | c89atomic_is_lock_free_8 |
| | c89atomic_is_lock_free_16 |
| | c89atomic_is_lock_free_32 |
| | c89atomic_is_lock_free_64 |
+-----------------------------------------+-----------------------------------------------+
| (Not Defined) | c89atomic_compare_and_swap_8 |
| | c89atomic_compare_and_swap_16 |
| | c89atomic_compare_and_swap_32 |
| | c89atomic_compare_and_swap_64 |
| | c89atomic_compare_and_swap_ptr |
+-----------------------------------------+-----------------------------------------------+