C89 compatible atomics. (forked)
  • C 97.1%
  • CMake 1.9%
  • Batchfile 0.6%
  • Assembly 0.4%
Find a file
dalmurii 9727be7471 UPDATE: made target_include_directories PUBLIC from INTERFACE
since c89atomics may use its header.

 Changes to be committed:
	- modified:   CMakeLists.txt
2026-02-10 10:43:55 +09:00
.github/workflows CI: Remove 32-bit MSVC ARM checks. 2025-09-19 12:40:17 +10:00
build Add TCC build script. 2025-05-07 18:48:34 +10:00
extras deque: Remove a feature I no longer need. 2025-06-05 17:27:59 +10:00
tests Add bitmap allocator. 2025-06-05 13:12:04 +10:00
x64 Initial commit. 2020-06-22 20:58:40 +10:00
.gitignore Update gitignore. 2025-05-07 18:48:42 +10:00
c89atomic.c Add some tagging. 2025-06-01 15:08:03 +10:00
c89atomic.h Remove a stray line continuation from a macro. 2025-09-19 13:02:08 +10:00
CMakeLists.txt UPDATE: made target_include_directories PUBLIC from INTERFACE 2026-02-10 10:43:55 +09:00
README.md Fix a typo. 2025-05-08 18:05:11 +10:00

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:

  • Visual Studio from VC6 (Earlier versions may work, but are untested.)
  • GCC starting from 2.7 (Earlier versions lack support for extended inline assembly.)
  • Clang
  • Intel oneAPI (Tested with 2025.0.4. Intel C++ Compiler Classic has not been tested.)
  • TinyCC/TCC (Tested with 0.9.27)
  • OpenWatcom (Tested with 2.0)
  • Digital Mars
  • Borland C++ (Tested with 5.02)

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.

  • All operations require an explicit size which is specified by the name of the function, and only 8-, 16-, 32- and 64-bit operations are supported. Objects of arbitrary sizes are not supported.
  • All APIs are namespaced with c89.
  • c89atomic_* data types are undecorated (there is no _Atomic decoration).

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                |
+-----------------------------------------+-----------------------------------------------+