Zephyr Project API
3.2.0
A Scalable Open Source RTOS
rtio_spsc.h
Go to the documentation of this file.
1
/*
2
* Copyright (c) 2022 Intel Corporation
3
*
4
* SPDX-License-Identifier: Apache-2.0
5
*/
6
7
8
#ifndef ZEPHYR_RTIO_SPSC_H_
9
#define ZEPHYR_RTIO_SPSC_H_
10
11
#include <
stdint.h
>
12
#include <
stdbool.h
>
13
#include <
zephyr/sys/atomic.h
>
14
58
struct
rtio_spsc {
59
/* private value only the producer thread should mutate */
60
unsigned
long
acquire;
61
62
/* private value only the consumer thread should mutate */
63
unsigned
long
consume;
64
65
/* producer mutable, consumer readable */
66
atomic_t
in;
67
68
/* consumer mutable, producer readable */
69
atomic_t
out;
70
71
/* mask used to automatically wrap values */
72
const
unsigned
long
mask;
73
};
74
82
#define RTIO_SPSC_INITIALIZER(name, type, sz) \
83
{ ._spsc = { \
84
.acquire = 0, \
85
.consume = 0, \
86
.in = ATOMIC_INIT(0), \
87
.out = ATOMIC_INIT(0), \
88
.mask = sz - 1, \
89
} \
90
}
91
99
#define RTIO_SPSC_DECLARE(name, type, sz) \
100
struct rtio_spsc_ ## name { \
101
struct rtio_spsc _spsc; \
102
type buffer[sz]; \
103
}
104
112
#define RTIO_SPSC_DEFINE(name, type, sz) \
113
RTIO_SPSC_DECLARE(name, type, sz) name = RTIO_SPSC_INITIALIZER(name, type, sz);
114
120
#define rtio_spsc_size(spsc) ((spsc)->_spsc.mask + 1)
121
129
#define z_rtio_spsc_mask(spsc, i) ((i) & (spsc)->_spsc.mask)
130
139
#define rtio_spsc_reset(spsc) \
140
({ \
141
(spsc)->_spsc.consume = 0; \
142
(spsc)->_spsc.acquire = 0; \
143
atomic_set(&(spsc)->_spsc.in, 0); \
144
atomic_set(&(spsc)->_spsc.out, 0); \
145
})
146
154
#define rtio_spsc_acquire(spsc) \
155
({ \
156
unsigned long idx = atomic_get(&(spsc)->_spsc.in) + (spsc)->_spsc.acquire; \
157
bool acq = (idx - atomic_get(&(spsc)->_spsc.out)) < rtio_spsc_size(spsc); \
158
if (acq) { \
159
(spsc)->_spsc.acquire += 1; \
160
} \
161
acq ? &((spsc)->buffer[z_rtio_spsc_mask(spsc, idx)]) : NULL; \
162
})
163
171
#define rtio_spsc_produce(spsc) \
172
({ \
173
if ((spsc)->_spsc.acquire > 0) { \
174
(spsc)->_spsc.acquire -= 1; \
175
atomic_add(&(spsc)->_spsc.in, 1); \
176
} \
177
})
178
187
#define rtio_spsc_produce_all(spsc) \
188
({ \
189
if ((spsc)->_spsc.acquire > 0) { \
190
unsigned long acquired = (spsc)->_spsc.acquire; \
191
(spsc)->_spsc.acquire = 0; \
192
atomic_add(&(spsc)->_spsc.in, acquired); \
193
} \
194
})
195
203
#define rtio_spsc_consume(spsc) \
204
({ \
205
unsigned long idx = atomic_get(&(spsc)->_spsc.out) + (spsc)->_spsc.consume; \
206
bool has_consumable = (idx != atomic_get(&(spsc)->_spsc.in)); \
207
if (has_consumable) { \
208
(spsc)->_spsc.consume += 1; \
209
} \
210
has_consumable ? &((spsc)->buffer[z_rtio_spsc_mask(spsc, idx)]) : NULL; \
211
})
212
218
#define rtio_spsc_release(spsc) \
219
({ \
220
if ((spsc)->_spsc.consume > 0) { \
221
(spsc)->_spsc.consume -= 1; \
222
atomic_add(&(spsc)->_spsc.out, 1); \
223
} \
224
})
225
231
#define rtio_spsc_consumable(spsc) \
232
({ (spsc)->_spsc.in - (spsc)->_spsc.out - (spsc)->_spsc.consume; })
233
241
#define rtio_spsc_peek(spsc) \
242
({ \
243
unsigned long idx = atomic_get(&(spsc)->_spsc.out) + (spsc)->_spsc.consume; \
244
bool has_consumable = (idx != atomic_get(&(spsc)->_spsc.in)); \
245
has_consumable ? &((spsc)->buffer[z_rtio_spsc_mask(spsc, idx)]) : NULL; \
246
})
247
257
#define rtio_spsc_next(spsc, item) \
258
({ \
259
unsigned long idx = ((item) - (spsc)->buffer); \
260
bool has_next = z_rtio_spsc_mask(spsc, (idx + 1)) != \
261
(z_rtio_spsc_mask(spsc, atomic_get(&(spsc)->_spsc.in))); \
262
has_next ? &((spsc)->buffer[z_rtio_spsc_mask((spsc), idx + 1)]) : NULL; \
263
})
264
273
#define rtio_spsc_prev(spsc, item) \
274
({ \
275
unsigned long idx = ((item) - &(spsc)->buffer[0]) / sizeof((spsc)->buffer[0]); \
276
bool has_prev = idx != z_rtio_spsc_mask(spsc, atomic_get(&(spsc)->_spsc.out)); \
277
has_prev ? &((spsc)->buffer[z_rtio_spsc_mask(spsc, idx - 1)]) : NULL; \
278
})
279
284
#endif
/* ZEPHYR_RTIO_SPSC_H_ */
atomic.h
atomic_t
long atomic_t
Definition:
atomic.h:22
stdbool.h
stdint.h
include
zephyr
rtio
rtio_spsc.h
Generated on Tue Feb 28 2023 16:45:26 for Zephyr Project API by
1.9.2