30RCSID(
"$Id: 7a4d7837f69247a69624f8b33786b9b1587175c1 $")
36#include <freeradius-devel/autoconf.h>
37#include <freeradius-devel/io/atomic_queue.h>
38#include <freeradius-devel/util/talloc.h>
39#include <freeradius-devel/util/math.h>
44#define atomic_int64_t _Atomic(int64_t)
45#define atomic_uint32_t _Atomic(uint32_t)
46#define atomic_uint64_t _Atomic(uint64_t)
48#define cas_incr(_store, _var) atomic_compare_exchange_strong_explicit(&_store, &_var, _var + 1, memory_order_release, memory_order_relaxed)
49#define cas_decr(_store, _var) atomic_compare_exchange_strong_explicit(&_store, &_var, _var - 1, memory_order_release, memory_order_relaxed)
50#define load(_var) atomic_load_explicit(&_var, memory_order_relaxed)
51#define acquire(_var) atomic_load_explicit(&_var, memory_order_acquire)
52#define store(_store, _var) atomic_store_explicit(&_store, _var, memory_order_release)
54#define CACHE_LINE_SIZE 64
121 if (size == 0)
return NULL;
136 sizeof(*
aq) + (size) *
sizeof(
aq->
entry[0]));
137 if (!chunk)
return NULL;
140 talloc_set_name_const(chunk,
"fr_atomic_queue_t");
146 for (i = 0; i < size; i++) {
192 if (!
data)
return false;
289#ifdef __clang_analyzer__
315 if (!p_data)
return false;
325 diff = (seq - (tail + 1));
360 *p_data = entry->
data;
377#ifdef WITH_VERIFY_PTR
416 fprintf(fp,
"AQ %p size %zu, head %" PRId64
", tail %" PRId64
"\n",
419 for (i = 0; i <
aq->
size; i++) {
424 fprintf(fp,
"\t[%zu] = { %p, %" PRId64
" }",
432 fprintf(fp,
"\tstatus %d, data_size %zd, signal %d, ack %zd, ch %p",
atomic_int64_t head
Position of the producer.
bool fr_atomic_queue_pop(fr_atomic_queue_t *aq, void **p_data)
Pop a pointer from the atomic queue.
void fr_atomic_queue_debug(FILE *fp, fr_atomic_queue_t *aq)
Dump an atomic queue.
void * chunk
The start of the talloc chunk to pass to free.
atomic_int64_t tail
Position of the consumer.
#define cas_incr(_store, _var)
fr_atomic_queue_entry_t entry[]
The entry array, also aligned to ensure it's not in the same cache line as tail and size.
fr_atomic_queue_t * fr_atomic_queue_alloc(TALLOC_CTX *ctx, size_t size)
Create fixed-size atomic queue.
size_t size
The length of the queue.
size_t fr_atomic_queue_size(fr_atomic_queue_t *aq)
bool fr_atomic_queue_push(fr_atomic_queue_t *aq, void *data)
Push a pointer into the atomic queue.
void fr_atomic_queue_free(fr_atomic_queue_t **aq)
Free an atomic queue if it's not freed by ctx.
#define store(_store, _var)
atomic_int64_t seq
Must be seq then data to ensure seq is 64bit aligned for 32bit address spaces.
Structure to hold the atomic queue.
static fr_atomic_queue_t ** aq
fr_control_message_status_t status
status of this message
size_t data_size
size of the data we're sending
The header for the control message.
static uint64_t fr_roundup_pow2_uint64(uint64_t v)
#define atomic_thread_fence(order)
TALLOC_CTX * talloc_aligned_array(TALLOC_CTX *ctx, void **start, size_t alignment, size_t size)
Return a page aligned talloc memory array.