vsync / atomic
Rich interface of atomic operations and fences.
VSync atomics (VAtomics) implements a rich interface of atomic operations and fences. It employs efficient custom assembly for supported architectures, and falls back to compiler builtins otherwise.
core.h implements the following atomic types:
Atomic type (A) | Related type (T) |
---|---|
vatomic8_t | vuint8_t |
vatomic16_t | vuint16_t |
vatomic32_t | vuint32_t |
vatomic64_t | vuint64_t |
vatomicptr_t | void* |
Functions are always prefixed with the atomic type, e.g., vatomic32_read(), vatomic64_read(), vatomicptr_read(). Arguments or return values typically are of related types, e.g., vatomic64_write(vatomic64_t *a, vuint64_t v)
.
The types vuint32_t
and vuint64_t
map to equivalent types from <stdint.h> unless VSYNC_ENABLE_FREESTANDING is defined.
Note that a few functions are not defined for vatomicptr_t, e.g., add, sub, etc.
By default, atomic functions are seq_cst (sequentially consistent). To specify another memory order, add the corresponding suffix to the function name:
Mode | Suffix |
---|---|
acquire | _acq |
release | _rel |
relaxed | _rlx |
Note: Not all functions support every memory order. See the function documentation for more information.
VSync atomics are divided in several components.
For the declaration and definition of the core atomic operations and fences, include core.h (as in #include <
vsync/atomic/core.h
>
).
For a set of advanced atomic operations optimized for politely waiting (spinning), include await.h.
For readability and ease of use, include dispatch.h. It introduces several macro dispatchers prefixed with vatomic_. These dispatchers map to the call to the respective vatomic8_, vatomic16_, vatomic32_ or vatomi64_ functions depending on the type/size of the arguments. For example, vatomic_read(a) is the same as vatomic32_read(a) if the type of a
is vatomic32_t.
More advanced stamped and marked atomic pointers are available in atomicptr_stamped.h and atomicptr_markable.h.
Optimized atomic implementations are available for ARMv7 (32 and 64 bits) and ARMv8 (32 and 64 bits). For all other architectures, including x86_64, the fallback is __atomic
compiler builtins. To force the use of compiler builtins, define VATOMIC_BUILTINS.
For further configuration flags, please refer to config.h.
#include <vsync/atomic.h>
#include <assert.h>
#include <stdio.h>
vatomic32_t var;
vatomicptr_t ptr;
int x;
void
foo(void)
{
vatomic32_write(&var, 1000);
vatomic32_add(&var, 10);
vuint32_t val = vatomic32_read(&var);
assert(val == 1010);
assert(vatomic32_cmpxchg(&var, val, 0) == val);
x = 123;
vatomicptr_write(&ptr, &x);
int *y = vatomicptr_read(&ptr);
(*y)++;
assert(*y == x);
printf("passed\n");
}
int
main(void)
{
foo();
}
File | Description |
---|---|
vsync/atomic/atomicptr_markable.h | C implementation of AtomicMarkableReference in Java. |
vsync/atomic/atomicptr_stamped.h | C implementation of AtomicstampedReference in Java. |
vsync/atomic/await.h | Atomic await functions. |
vsync/atomic/await_ptr.h | Atomic await functions for vatomicptr_t variables. |
vsync/atomic/await_u32.h | Atomic await functions for vatomic32_t variables. |
vsync/atomic/await_u64.h | Atomic await functions for vatomic64_t variables. |
vsync/atomic/config.h | Global configuration of vatomics. |
vsync/atomic/core.h | Atomic types, core atomic operations and fences. |
vsync/atomic/core_ptr.h | Atomic functions for vatomicptr_t variables. |
vsync/atomic/core_sz.h | Atomic functions for vatomicsz_t variables. |
vsync/atomic/core_u16.h | Atomic functions for vatomic16_t variables. |
vsync/atomic/core_u32.h | Atomic functions for vatomic32_t variables. |
vsync/atomic/core_u64.h | Atomic functions for vatomic64_t variables. |
vsync/atomic/core_u8.h | Atomic functions for vatomic8_t variables. |