Zephyr API Documentation
3.6.99
A Scalable Open Source RTOS
Loading...
Searching...
No Matches
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/toolchain/common.h
>
14
#include <
zephyr/sys/atomic.h
>
15
#include <
zephyr/sys/util_macro.h
>
16
60
struct
rtio_spsc {
61
/* private value only the producer thread should mutate */
62
unsigned
long
acquire;
63
64
/* private value only the consumer thread should mutate */
65
unsigned
long
consume;
66
67
/* producer mutable, consumer readable */
68
atomic_t
in;
69
70
/* consumer mutable, producer readable */
71
atomic_t
out;
72
73
/* mask used to automatically wrap values */
74
const
unsigned
long
mask;
75
};
76
83
#define RTIO_SPSC_INITIALIZER(sz, buf) \
84
{ \
85
._spsc = { \
86
.acquire = 0, \
87
.consume = 0, \
88
.in = ATOMIC_INIT(0), \
89
.out = ATOMIC_INIT(0), \
90
.mask = sz - 1, \
91
}, \
92
.buffer = buf, \
93
}
94
101
#define RTIO_SPSC_DECLARE(name, type) \
102
static struct rtio_spsc_##name { \
103
struct rtio_spsc _spsc; \
104
type * const buffer; \
105
}
106
114
#define RTIO_SPSC_DEFINE(name, type, sz) \
115
BUILD_ASSERT(IS_POWER_OF_TWO(sz)); \
116
static type __spsc_buf_##name[sz]; \
117
RTIO_SPSC_DECLARE(name, type) name = RTIO_SPSC_INITIALIZER(sz, __spsc_buf_##name);
118
124
#define rtio_spsc_size(spsc) ((spsc)->_spsc.mask + 1)
125
133
#define z_rtio_spsc_mask(spsc, i) ((i) & (spsc)->_spsc.mask)
134
135
140
#define z_rtio_spsc_in(spsc) (unsigned long)atomic_get(&(spsc)->_spsc.in)
141
146
#define z_rtio_spsc_out(spsc) (unsigned long)atomic_get(&(spsc)->_spsc.out)
147
156
#define rtio_spsc_reset(spsc) \
157
({ \
158
(spsc)->_spsc.consume = 0; \
159
(spsc)->_spsc.acquire = 0; \
160
atomic_set(&(spsc)->_spsc.in, 0); \
161
atomic_set(&(spsc)->_spsc.out, 0); \
162
})
163
171
#define rtio_spsc_acquire(spsc) \
172
({ \
173
unsigned long idx = z_rtio_spsc_in(spsc) + (spsc)->_spsc.acquire; \
174
bool spsc_acq = (idx - z_rtio_spsc_out(spsc)) < rtio_spsc_size(spsc); \
175
if (spsc_acq) { \
176
(spsc)->_spsc.acquire += 1; \
177
} \
178
spsc_acq ? &((spsc)->buffer[z_rtio_spsc_mask(spsc, idx)]) : NULL; \
179
})
180
188
#define rtio_spsc_produce(spsc) \
189
({ \
190
if ((spsc)->_spsc.acquire > 0) { \
191
(spsc)->_spsc.acquire -= 1; \
192
atomic_add(&(spsc)->_spsc.in, 1); \
193
} \
194
})
195
204
#define rtio_spsc_produce_all(spsc) \
205
({ \
206
if ((spsc)->_spsc.acquire > 0) { \
207
unsigned long acquired = (spsc)->_spsc.acquire; \
208
(spsc)->_spsc.acquire = 0; \
209
atomic_add(&(spsc)->_spsc.in, acquired); \
210
} \
211
})
212
220
#define rtio_spsc_drop_all(spsc) \
221
do { \
222
(spsc)->_spsc.acquire = 0; \
223
} while (false)
224
232
#define rtio_spsc_consume(spsc) \
233
({ \
234
unsigned long idx = z_rtio_spsc_out(spsc) + (spsc)->_spsc.consume; \
235
bool has_consumable = (idx != z_rtio_spsc_in(spsc)); \
236
if (has_consumable) { \
237
(spsc)->_spsc.consume += 1; \
238
} \
239
has_consumable ? &((spsc)->buffer[z_rtio_spsc_mask(spsc, idx)]) : NULL; \
240
})
241
247
#define rtio_spsc_release(spsc) \
248
({ \
249
if ((spsc)->_spsc.consume > 0) { \
250
(spsc)->_spsc.consume -= 1; \
251
atomic_add(&(spsc)->_spsc.out, 1); \
252
} \
253
})
254
255
261
#define rtio_spsc_release_all(spsc) \
262
({ \
263
if ((spsc)->_spsc.consume > 0) { \
264
unsigned long consumed = (spsc)->_spsc.consume; \
265
(spsc)->_spsc.consume = 0; \
266
atomic_add(&(spsc)->_spsc.out, consumed); \
267
} \
268
})
269
275
#define rtio_spsc_acquirable(spsc) \
276
({ \
277
(((spsc)->_spsc.in + (spsc)->_spsc.acquire) - (spsc)->_spsc.out) - \
278
rtio_spsc_size(spsc); \
279
})
280
286
#define rtio_spsc_consumable(spsc) \
287
({ (spsc)->_spsc.in - (spsc)->_spsc.out - (spsc)->_spsc.consume; })
288
296
#define rtio_spsc_peek(spsc) \
297
({ \
298
unsigned long idx = z_rtio_spsc_out(spsc) + (spsc)->_spsc.consume; \
299
bool has_consumable = (idx != z_rtio_spsc_in(spsc)); \
300
has_consumable ? &((spsc)->buffer[z_rtio_spsc_mask(spsc, idx)]) : NULL; \
301
})
302
312
#define rtio_spsc_next(spsc, item) \
313
({ \
314
unsigned long idx = ((item) - (spsc)->buffer); \
315
bool has_next = z_rtio_spsc_mask(spsc, (idx + 1)) != \
316
(z_rtio_spsc_mask(spsc, z_rtio_spsc_in(spsc))); \
317
has_next ? &((spsc)->buffer[z_rtio_spsc_mask((spsc), idx + 1)]) : NULL; \
318
})
319
328
#define rtio_spsc_prev(spsc, item) \
329
({ \
330
unsigned long idx = ((item) - &(spsc)->buffer[0]) / sizeof((spsc)->buffer[0]); \
331
bool has_prev = idx != z_rtio_spsc_mask(spsc, z_rtio_spsc_out(spsc)); \
332
has_prev ? &((spsc)->buffer[z_rtio_spsc_mask(spsc, idx - 1)]) : NULL; \
333
})
334
339
#endif
/* ZEPHYR_RTIO_SPSC_H_ */
atomic.h
atomic_t
long atomic_t
Definition:
atomic_types.h:15
common.h
Common toolchain abstraction.
stdbool.h
stdint.h
util_macro.h
Macro utilities.
zephyr
rtio
rtio_spsc.h
Generated on Thu Sep 26 2024 10:47:06 for Zephyr API Documentation by
1.9.6