7#ifndef ZEPHYR_SYS_SPSC_LOCKFREE_H_
8#define ZEPHYR_SYS_SPSC_LOCKFREE_H_
61 unsigned long acquire;
64 unsigned long consume;
73 const unsigned long mask;
82#define SPSC_INITIALIZER(sz, buf) \
88 .in = ATOMIC_INIT(0), \
89 .out = ATOMIC_INIT(0), \
101#define SPSC_DECLARE(name, type) \
102 static struct spsc_##name { \
104 type * const buffer; \
114#define SPSC_DEFINE(name, type, sz) \
115 BUILD_ASSERT(IS_POWER_OF_TWO(sz)); \
116 static type __spsc_buf_##name[sz]; \
117 SPSC_DECLARE(name, type) name = SPSC_INITIALIZER(sz, __spsc_buf_##name);
124#define spsc_size(spsc) ((spsc)->_spsc.mask + 1)
133#define z_spsc_mask(spsc, i) ((i) & (spsc)->_spsc.mask)
139#define z_spsc_in(spsc) (unsigned long)atomic_get(&(spsc)->_spsc.in)
145#define z_spsc_out(spsc) (unsigned long)atomic_get(&(spsc)->_spsc.out)
155#define spsc_reset(spsc) \
157 (spsc)->_spsc.consume = 0; \
158 (spsc)->_spsc.acquire = 0; \
159 atomic_set(&(spsc)->_spsc.in, 0); \
160 atomic_set(&(spsc)->_spsc.out, 0); \
170#define spsc_acquire(spsc) \
172 unsigned long idx = z_spsc_in(spsc) + (spsc)->_spsc.acquire; \
173 bool spsc_acq = (idx - z_spsc_out(spsc)) < spsc_size(spsc); \
175 (spsc)->_spsc.acquire += 1; \
177 spsc_acq ? &((spsc)->buffer[z_spsc_mask(spsc, idx)]) : NULL; \
187#define spsc_produce(spsc) \
189 if ((spsc)->_spsc.acquire > 0) { \
190 (spsc)->_spsc.acquire -= 1; \
191 atomic_add(&(spsc)->_spsc.in, 1); \
203#define spsc_produce_all(spsc) \
205 if ((spsc)->_spsc.acquire > 0) { \
206 unsigned long acquired = (spsc)->_spsc.acquire; \
207 (spsc)->_spsc.acquire = 0; \
208 atomic_add(&(spsc)->_spsc.in, acquired); \
219#define spsc_drop_all(spsc) \
221 (spsc)->_spsc.acquire = 0; \
231#define spsc_consume(spsc) \
233 unsigned long idx = z_spsc_out(spsc) + (spsc)->_spsc.consume; \
234 bool has_consumable = (idx != z_spsc_in(spsc)); \
235 if (has_consumable) { \
236 (spsc)->_spsc.consume += 1; \
238 has_consumable ? &((spsc)->buffer[z_spsc_mask(spsc, idx)]) : NULL; \
246#define spsc_release(spsc) \
248 if ((spsc)->_spsc.consume > 0) { \
249 (spsc)->_spsc.consume -= 1; \
250 atomic_add(&(spsc)->_spsc.out, 1); \
259#define spsc_release_all(spsc) \
261 if ((spsc)->_spsc.consume > 0) { \
262 unsigned long consumed = (spsc)->_spsc.consume; \
263 (spsc)->_spsc.consume = 0; \
264 atomic_add(&(spsc)->_spsc.out, consumed); \
273#define spsc_acquirable(spsc) \
274 ({ (((spsc)->_spsc.in + (spsc)->_spsc.acquire) - (spsc)->_spsc.out) - spsc_size(spsc); })
281#define spsc_consumable(spsc) ({ (spsc)->_spsc.in - (spsc)->_spsc.out - (spsc)->_spsc.consume; })
290#define spsc_peek(spsc) \
292 unsigned long idx = z_spsc_out(spsc) + (spsc)->_spsc.consume; \
293 bool has_consumable = (idx != z_spsc_in(spsc)); \
294 has_consumable ? &((spsc)->buffer[z_spsc_mask(spsc, idx)]) : NULL; \
306#define spsc_next(spsc, item) \
308 unsigned long idx = ((item) - (spsc)->buffer); \
310 z_spsc_mask(spsc, (idx + 1)) != (z_spsc_mask(spsc, z_spsc_in(spsc))); \
311 has_next ? &((spsc)->buffer[z_spsc_mask((spsc), idx + 1)]) : NULL; \
322#define spsc_prev(spsc, item) \
324 unsigned long idx = ((item) - &(spsc)->buffer[0]) / sizeof((spsc)->buffer[0]); \
325 bool has_prev = idx != z_spsc_mask(spsc, z_spsc_out(spsc)); \
326 has_prev ? &((spsc)->buffer[z_spsc_mask(spsc, idx - 1)]) : NULL; \
long atomic_t
Definition atomic_types.h:15
Common toolchain abstraction.