Zephyr Project API
3.3.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_drop_all(spsc) \
204
do { \
205
(spsc)->_spsc.acquire = 0; \
206
} while (false)
207
215
#define rtio_spsc_consume(spsc) \
216
({ \
217
unsigned long idx = atomic_get(&(spsc)->_spsc.out) + (spsc)->_spsc.consume; \
218
bool has_consumable = (idx != atomic_get(&(spsc)->_spsc.in)); \
219
if (has_consumable) { \
220
(spsc)->_spsc.consume += 1; \
221
} \
222
has_consumable ? &((spsc)->buffer[z_rtio_spsc_mask(spsc, idx)]) : NULL; \
223
})
224
230
#define rtio_spsc_release(spsc) \
231
({ \
232
if ((spsc)->_spsc.consume > 0) { \
233
(spsc)->_spsc.consume -= 1; \
234
atomic_add(&(spsc)->_spsc.out, 1); \
235
} \
236
})
237
238
244
#define rtio_spsc_release_all(spsc) \
245
({ \
246
if ((spsc)->_spsc.consume > 0) { \
247
unsigned long consumed = (spsc)->_spsc.consume; \
248
(spsc)->_spsc.consume = 0; \
249
atomic_add(&(spsc)->_spsc.out, consumed); \
250
} \
251
})
252
258
#define rtio_spsc_acquirable(spsc) \
259
({ \
260
(((spsc)->_spsc.in + (spsc)->_spsc.acquire) - (spsc)->_spsc.out) - \
261
rtio_spsc_size(spsc); \
262
})
263
269
#define rtio_spsc_consumable(spsc) \
270
({ (spsc)->_spsc.in - (spsc)->_spsc.out - (spsc)->_spsc.consume; })
271
279
#define rtio_spsc_peek(spsc) \
280
({ \
281
unsigned long idx = atomic_get(&(spsc)->_spsc.out) + (spsc)->_spsc.consume; \
282
bool has_consumable = (idx != atomic_get(&(spsc)->_spsc.in)); \
283
has_consumable ? &((spsc)->buffer[z_rtio_spsc_mask(spsc, idx)]) : NULL; \
284
})
285
295
#define rtio_spsc_next(spsc, item) \
296
({ \
297
unsigned long idx = ((item) - (spsc)->buffer); \
298
bool has_next = z_rtio_spsc_mask(spsc, (idx + 1)) != \
299
(z_rtio_spsc_mask(spsc, atomic_get(&(spsc)->_spsc.in))); \
300
has_next ? &((spsc)->buffer[z_rtio_spsc_mask((spsc), idx + 1)]) : NULL; \
301
})
302
311
#define rtio_spsc_prev(spsc, item) \
312
({ \
313
unsigned long idx = ((item) - &(spsc)->buffer[0]) / sizeof((spsc)->buffer[0]); \
314
bool has_prev = idx != z_rtio_spsc_mask(spsc, atomic_get(&(spsc)->_spsc.out)); \
315
has_prev ? &((spsc)->buffer[z_rtio_spsc_mask(spsc, idx - 1)]) : NULL; \
316
})
317
322
#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 Fri Jun 9 2023 14:09:43 for Zephyr Project API by
1.9.2