Zephyr Project API 3.7.0
A Scalable Open Source RTOS
Loading...
Searching...
No Matches

Single Producer Single Consumer (SPSC) Lockfree Queue API. More...

Files

file  spsc_lockfree.h
 A lock-free and type safe power of 2 fixed sized single producer single consumer (SPSC) queue using a ringbuffer and atomics to ensure coherency.
 

Macros

#define SPSC_INITIALIZER(sz, buf)
 Statically initialize an spsc.
 
#define SPSC_DECLARE(name, type)
 Declare an anonymous struct type for an spsc.
 
#define SPSC_DEFINE(name, type, sz)
 Define an spsc with a fixed size.
 
#define spsc_size(spsc)   ((spsc)->_spsc.mask + 1)
 Size of the SPSC queue.
 
#define spsc_reset(spsc)
 Initialize/reset a spsc such that its empty.
 
#define spsc_acquire(spsc)
 Acquire an element to produce from the SPSC.
 
#define spsc_produce(spsc)
 Produce one previously acquired element to the SPSC.
 
#define spsc_produce_all(spsc)
 Produce all previously acquired elements to the SPSC.
 
#define spsc_drop_all(spsc)
 Drop all previously acquired elements.
 
#define spsc_consume(spsc)
 Consume an element from the spsc.
 
#define spsc_release(spsc)
 Release a consumed element.
 
#define spsc_release_all(spsc)
 Release all consumed elements.
 
#define spsc_acquirable(spsc)    ({ (((spsc)->_spsc.in + (spsc)->_spsc.acquire) - (spsc)->_spsc.out) - spsc_size(spsc); })
 Count of acquirable in spsc.
 
#define spsc_consumable(spsc)   ({ (spsc)->_spsc.in - (spsc)->_spsc.out - (spsc)->_spsc.consume; })
 Count of consumables in spsc.
 
#define spsc_peek(spsc)
 Peek at the first available item in queue.
 
#define spsc_next(spsc, item)
 Peek at the next item in the queue from a given one.
 
#define spsc_prev(spsc, item)
 Get the previous item in the queue from a given one.
 

Detailed Description

Single Producer Single Consumer (SPSC) Lockfree Queue API.

Macro Definition Documentation

◆ spsc_acquirable

#define spsc_acquirable (   spsc)     ({ (((spsc)->_spsc.in + (spsc)->_spsc.acquire) - (spsc)->_spsc.out) - spsc_size(spsc); })

#include <include/zephyr/sys/spsc_lockfree.h>

Count of acquirable in spsc.

Parameters
spscSPSC to get item count for

◆ spsc_acquire

#define spsc_acquire (   spsc)

#include <include/zephyr/sys/spsc_lockfree.h>

Value:
({ \
unsigned long idx = z_spsc_in(spsc) + (spsc)->_spsc.acquire; \
bool spsc_acq = (idx - z_spsc_out(spsc)) < spsc_size(spsc); \
if (spsc_acq) { \
(spsc)->_spsc.acquire += 1; \
} \
spsc_acq ? &((spsc)->buffer[z_spsc_mask(spsc, idx)]) : NULL; \
})
#define spsc_size(spsc)
Size of the SPSC queue.
Definition spsc_lockfree.h:124
static ZTEST_BMEM char buffer[8]
Definition test_mbox_api.c:433

Acquire an element to produce from the SPSC.

Parameters
spscSPSC to acquire an element from for producing
Returns
A pointer to the acquired element or null if the spsc is full

◆ spsc_consumable

#define spsc_consumable (   spsc)    ({ (spsc)->_spsc.in - (spsc)->_spsc.out - (spsc)->_spsc.consume; })

#include <include/zephyr/sys/spsc_lockfree.h>

Count of consumables in spsc.

Parameters
spscSPSC to get item count for

◆ spsc_consume

#define spsc_consume (   spsc)

#include <include/zephyr/sys/spsc_lockfree.h>

Value:
({ \
unsigned long idx = z_spsc_out(spsc) + (spsc)->_spsc.consume; \
bool has_consumable = (idx != z_spsc_in(spsc)); \
if (has_consumable) { \
(spsc)->_spsc.consume += 1; \
} \
has_consumable ? &((spsc)->buffer[z_spsc_mask(spsc, idx)]) : NULL; \
})

Consume an element from the spsc.

Parameters
spscSpsc to consume from
Returns
Pointer to element or null if no consumable elements left

◆ SPSC_DECLARE

#define SPSC_DECLARE (   name,
  type 
)

#include <include/zephyr/sys/spsc_lockfree.h>

Value:
static struct spsc_##name { \
struct spsc _spsc; \
type * const buffer; \
}

Declare an anonymous struct type for an spsc.

Parameters
nameName of the spsc symbol to be provided
typeType stored in the spsc

◆ SPSC_DEFINE

#define SPSC_DEFINE (   name,
  type,
  sz 
)

#include <include/zephyr/sys/spsc_lockfree.h>

Value:
BUILD_ASSERT(IS_POWER_OF_TWO(sz)); \
static type __spsc_buf_##name[sz]; \
SPSC_DECLARE(name, type) name = SPSC_INITIALIZER(sz, __spsc_buf_##name);
#define SPSC_INITIALIZER(sz, buf)
Statically initialize an spsc.
Definition spsc_lockfree.h:82
#define IS_POWER_OF_TWO(x)
Check if a x is a power of two.
Definition util_macro.h:77

Define an spsc with a fixed size.

Parameters
nameName of the spsc symbol to be provided
typeType stored in the spsc
szSize of the spsc, must be power of 2 (ex: 2, 4, 8)

◆ spsc_drop_all

#define spsc_drop_all (   spsc)

#include <include/zephyr/sys/spsc_lockfree.h>

Value:
do { \
(spsc)->_spsc.acquire = 0; \
} while (false)

Drop all previously acquired elements.

This makes all previous acquired elements available to be acquired again

Parameters
spscSPSC to drop all previously acquired elements or do nothing

◆ SPSC_INITIALIZER

#define SPSC_INITIALIZER (   sz,
  buf 
)

#include <include/zephyr/sys/spsc_lockfree.h>

Value:
{ \
._spsc = \
{ \
.acquire = 0, \
.consume = 0, \
.in = ATOMIC_INIT(0), \
.out = ATOMIC_INIT(0), \
.mask = sz - 1, \
}, \
.buffer = buf, \
}
#define ATOMIC_INIT(i)
Initialize an atomic variable.
Definition atomic.h:59

Statically initialize an spsc.

Parameters
szSize of the spsc, must be power of 2 (ex: 2, 4, 8)
bufBuffer pointer

◆ spsc_next

#define spsc_next (   spsc,
  item 
)

#include <include/zephyr/sys/spsc_lockfree.h>

Value:
({ \
unsigned long idx = ((item) - (spsc)->buffer); \
bool has_next = \
z_spsc_mask(spsc, (idx + 1)) != (z_spsc_mask(spsc, z_spsc_in(spsc))); \
has_next ? &((spsc)->buffer[z_spsc_mask((spsc), idx + 1)]) : NULL; \
})

Peek at the next item in the queue from a given one.

Parameters
spscSPSC to peek at
itemPointer to an item in the queue
Returns
Pointer to element or null if none left

◆ spsc_peek

#define spsc_peek (   spsc)

#include <include/zephyr/sys/spsc_lockfree.h>

Value:
({ \
unsigned long idx = z_spsc_out(spsc) + (spsc)->_spsc.consume; \
bool has_consumable = (idx != z_spsc_in(spsc)); \
has_consumable ? &((spsc)->buffer[z_spsc_mask(spsc, idx)]) : NULL; \
})

Peek at the first available item in queue.

Parameters
spscSpsc to peek into
Returns
Pointer to element or null if no consumable elements left

◆ spsc_prev

#define spsc_prev (   spsc,
  item 
)

#include <include/zephyr/sys/spsc_lockfree.h>

Value:
({ \
unsigned long idx = ((item) - &(spsc)->buffer[0]) / sizeof((spsc)->buffer[0]); \
bool has_prev = idx != z_spsc_mask(spsc, z_spsc_out(spsc)); \
has_prev ? &((spsc)->buffer[z_spsc_mask(spsc, idx - 1)]) : NULL; \
})

Get the previous item in the queue from a given one.

Parameters
spscSPSC to peek at
itemPointer to an item in the queue
Returns
Pointer to element or null if none left

◆ spsc_produce

#define spsc_produce (   spsc)

#include <include/zephyr/sys/spsc_lockfree.h>

Value:
({ \
if ((spsc)->_spsc.acquire > 0) { \
(spsc)->_spsc.acquire -= 1; \
atomic_add(&(spsc)->_spsc.in, 1); \
} \
})

Produce one previously acquired element to the SPSC.

This makes one element available to the consumer immediately

Parameters
spscSPSC to produce the previously acquired element or do nothing

◆ spsc_produce_all

#define spsc_produce_all (   spsc)

#include <include/zephyr/sys/spsc_lockfree.h>

Value:
({ \
if ((spsc)->_spsc.acquire > 0) { \
unsigned long acquired = (spsc)->_spsc.acquire; \
(spsc)->_spsc.acquire = 0; \
atomic_add(&(spsc)->_spsc.in, acquired); \
} \
})

Produce all previously acquired elements to the SPSC.

This makes all previous acquired elements available to the consumer immediately

Parameters
spscSPSC to produce all previously acquired elements or do nothing

◆ spsc_release

#define spsc_release (   spsc)

#include <include/zephyr/sys/spsc_lockfree.h>

Value:
({ \
if ((spsc)->_spsc.consume > 0) { \
(spsc)->_spsc.consume -= 1; \
atomic_add(&(spsc)->_spsc.out, 1); \
} \
})

Release a consumed element.

Parameters
spscSPSC to release consumed element or do nothing

◆ spsc_release_all

#define spsc_release_all (   spsc)

#include <include/zephyr/sys/spsc_lockfree.h>

Value:
({ \
if ((spsc)->_spsc.consume > 0) { \
unsigned long consumed = (spsc)->_spsc.consume; \
(spsc)->_spsc.consume = 0; \
atomic_add(&(spsc)->_spsc.out, consumed); \
} \
})

Release all consumed elements.

Parameters
spscSPSC to release consumed elements or do nothing

◆ spsc_reset

#define spsc_reset (   spsc)

#include <include/zephyr/sys/spsc_lockfree.h>

Value:
({ \
(spsc)->_spsc.consume = 0; \
(spsc)->_spsc.acquire = 0; \
atomic_set(&(spsc)->_spsc.in, 0); \
atomic_set(&(spsc)->_spsc.out, 0); \
})

Initialize/reset a spsc such that its empty.

Note that this is not safe to do while being used in a producer/consumer situation with multiple calling contexts (isrs/threads).

Parameters
spscSPSC to initialize/reset

◆ spsc_size

#define spsc_size (   spsc)    ((spsc)->_spsc.mask + 1)

#include <include/zephyr/sys/spsc_lockfree.h>

Size of the SPSC queue.

Parameters
spscSPSC reference