Implementation:ClickHouse ClickHouse Musl Atomic
| Knowledge Sources | |
|---|---|
| Domains | Concurrency, Portability |
| Last Updated | 2026-02-08 00:00 GMT |
Overview
Portable atomic operations library providing lock-free synchronization primitives across different architectures.
Description
This header provides a comprehensive set of atomic operations including compare-and-swap, fetch-and-add, fetch-and-or, and memory barriers. It supports both load-linked/store-conditional (LL/SC) architectures and architectures requiring CAS-based implementations. The code adapts to the underlying hardware capabilities through architecture-specific includes and provides fallback implementations when native atomics are unavailable.
Usage
Use these atomic operations when implementing lock-free data structures, concurrent algorithms, or synchronization primitives that need to work across multiple CPU architectures without relying on compiler-specific intrinsics.
Code Reference
Source Location
- Repository: ClickHouse
- File: base/glibc-compatibility/musl/atomic.h
- Lines: 1-318
Signature
// Core atomic operations
int a_cas(volatile int *p, int t, int s);
int a_swap(volatile int *p, int v);
int a_fetch_add(volatile int *p, int v);
int a_fetch_and(volatile int *p, int v);
int a_fetch_or(volatile int *p, int v);
// Pointer atomics
void *a_cas_p(volatile void *p, void *t, void *s);
// Convenience operations
void a_inc(volatile int *p);
void a_dec(volatile int *p);
void a_and(volatile int *p, int v);
void a_or(volatile int *p, int v);
void a_store(volatile int *p, int v);
// Memory barriers
void a_barrier();
void a_spin();
// 64-bit operations
void a_and_64(volatile uint64_t *p, uint64_t v);
void a_or_64(volatile uint64_t *p, uint64_t v);
// Bit manipulation
int a_ctz_32(uint32_t x);
int a_ctz_64(uint64_t x);
int a_clz_64(uint64_t x);
Import
#include "base/glibc-compatibility/musl/atomic.h"
I/O Contract
| Operation Category | Input | Output | Atomicity Guarantee |
|---|---|---|---|
| Compare-and-Swap | Pointer, expected, desired | Old value | Atomic read-modify-write |
| Fetch-and-Op | Pointer, operand | Old value before operation | Atomic read-modify-write |
| Store/Swap | Pointer, new value | Old value (swap only) | Atomic write with barriers |
| Memory Barriers | None | None | Full memory fence |
| Bit Operations | Integer value | Bit position | Non-atomic computation |
Usage Examples
// Lock-free increment
volatile int counter = 0;
a_inc(&counter); // Atomically increment
// Compare-and-swap for lock-free updates
volatile int value = 10;
int expected = 10;
int new_val = 20;
int old = a_cas(&value, expected, new_val);
if (old == expected) {
// Successfully swapped
}
// Atomic bitwise operations
volatile int flags = 0;
a_or(&flags, 0x4); // Set bit 2
a_and(&flags, ~0x2); // Clear bit 1
// Memory barrier for visibility
int data = 42;
volatile int ready = 0;
a_store(&ready, 1); // Ensures data is visible before ready
// Lock-free stack pointer update
void *old_top, *new_top;
do {
old_top = stack_top;
new_top = prepare_new_top(old_top);
} while (a_cas_p(&stack_top, old_top, new_top) != old_top);
// Counting trailing zeros for bit manipulation
uint32_t mask = 0x00FF0000;
int shift = a_ctz_32(mask); // Returns 16