Zephyr API Documentation  3.6.99
A Scalable Open Source RTOS
Loading...
Searching...
No Matches
rtio_mpsc.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2010-2011 Dmitry Vyukov
3 * Copyright (c) 2022 Intel Corporation
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8#ifndef ZEPHYR_RTIO_MPSC_H_
9#define ZEPHYR_RTIO_MPSC_H_
10
11#include <stdint.h>
12#include <stdbool.h>
13#include <zephyr/sys/atomic.h>
14#include <zephyr/kernel.h>
15
16#ifdef __cplusplus
17extern "C" {
18#endif
19
27/*
28 * On single core systems atomics are unnecessary
29 * and cause a lot of unnecessary cache invalidation
30 *
31 * Using volatile to at least ensure memory is read/written
32 * by the compiler generated op codes is enough.
33 *
34 * On SMP atomics *must* be used to ensure the pointers
35 * are updated in the correct order and the values are
36 * updated core caches correctly.
37 */
38#if defined(CONFIG_SMP)
39
41
42#define mpsc_ptr_get(ptr) atomic_ptr_get(&(ptr))
43#define mpsc_ptr_set(ptr, val) atomic_ptr_set(&(ptr), val)
44#define mpsc_ptr_set_get(ptr, val) atomic_ptr_set(&(ptr), val)
45
46#else
47
48typedef struct rtio_mpsc_node *mpsc_ptr_t;
49
50#define mpsc_ptr_get(ptr) ptr
51#define mpsc_ptr_set(ptr, val) ptr = val
52#define mpsc_ptr_set_get(ptr, val) \
53 ({ \
54 mpsc_ptr_t tmp = ptr; \
55 ptr = val; \
56 tmp; \
57 })
58
59#endif
60
82};
83
87struct rtio_mpsc {
91};
92
100#define RTIO_MPSC_INIT(symbol) \
101 { \
102 .head = (struct rtio_mpsc_node *)&symbol.stub, \
103 .tail = (struct rtio_mpsc_node *)&symbol.stub, \
104 .stub = { \
105 .next = NULL, \
106 }, \
107 }
108
114static inline void rtio_mpsc_init(struct rtio_mpsc *q)
115{
116 mpsc_ptr_set(q->head, &q->stub);
117 q->tail = &q->stub;
118 mpsc_ptr_set(q->stub.next, NULL);
119}
120
127static ALWAYS_INLINE void rtio_mpsc_push(struct rtio_mpsc *q, struct rtio_mpsc_node *n)
128{
129 struct rtio_mpsc_node *prev;
130 int key;
131
132 mpsc_ptr_set(n->next, NULL);
133
134 key = arch_irq_lock();
135 prev = (struct rtio_mpsc_node *)mpsc_ptr_set_get(q->head, n);
136 mpsc_ptr_set(prev->next, n);
137 arch_irq_unlock(key);
138}
139
146static inline struct rtio_mpsc_node *rtio_mpsc_pop(struct rtio_mpsc *q)
147{
148 struct rtio_mpsc_node *head;
149 struct rtio_mpsc_node *tail = q->tail;
150 struct rtio_mpsc_node *next = (struct rtio_mpsc_node *)mpsc_ptr_get(tail->next);
151
152 /* Skip over the stub/sentinel */
153 if (tail == &q->stub) {
154 if (next == NULL) {
155 return NULL;
156 }
157
158 q->tail = next;
159 tail = next;
160 next = (struct rtio_mpsc_node *)mpsc_ptr_get(next->next);
161 }
162
163 /* If next is non-NULL then a valid node is found, return it */
164 if (next != NULL) {
165 q->tail = next;
166 return tail;
167 }
168
169 head = (struct rtio_mpsc_node *)mpsc_ptr_get(q->head);
170
171 /* If next is NULL, and the tail != HEAD then the queue has pending
172 * updates that can't yet be accessed.
173 */
174 if (tail != head) {
175 return NULL;
176 }
177
178 rtio_mpsc_push(q, &q->stub);
179
180 next = (struct rtio_mpsc_node *)mpsc_ptr_get(tail->next);
181
182 if (next != NULL) {
183 q->tail = next;
184 return tail;
185 }
186
187 return NULL;
188}
189
194#ifdef __cplusplus
195}
196#endif
197
198#endif /* ZEPHYR_RTIO_MPSC_H_ */
static ALWAYS_INLINE unsigned int arch_irq_lock(void)
Disable all interrupts on the local CPU.
Definition: irq.h:168
static ALWAYS_INLINE void arch_irq_unlock(unsigned int key)
Definition: irq.h:176
void * atomic_ptr_t
Definition: atomic_types.h:17
#define ALWAYS_INLINE
Definition: common.h:129
static struct rtio_mpsc_node * rtio_mpsc_pop(struct rtio_mpsc *q)
Pop a node off of the list.
Definition: rtio_mpsc.h:146
atomic_ptr_t mpsc_ptr_t
Definition: rtio_mpsc.h:40
static ALWAYS_INLINE void rtio_mpsc_push(struct rtio_mpsc *q, struct rtio_mpsc_node *n)
Push a node.
Definition: rtio_mpsc.h:127
static void rtio_mpsc_init(struct rtio_mpsc *q)
Initialize queue.
Definition: rtio_mpsc.h:114
#define mpsc_ptr_set(ptr, val)
Definition: rtio_mpsc.h:43
#define mpsc_ptr_get(ptr)
Definition: rtio_mpsc.h:42
#define mpsc_ptr_set_get(ptr, val)
Definition: rtio_mpsc.h:44
Public kernel APIs.
Queue member.
Definition: rtio_mpsc.h:80
mpsc_ptr_t next
Definition: rtio_mpsc.h:81
MPSC Queue.
Definition: rtio_mpsc.h:87
mpsc_ptr_t head
Definition: rtio_mpsc.h:88
struct rtio_mpsc_node stub
Definition: rtio_mpsc.h:90
struct rtio_mpsc_node * tail
Definition: rtio_mpsc.h:89