Line data Source code
1 0 : /*
2 : * Copyright (c) 2021 Nordic Semiconductor ASA
3 : *
4 : * SPDX-License-Identifier: Apache-2.0
5 : */
6 : #ifndef ZEPHYR_INCLUDE_SYS_MPSC_PBUF_H_
7 : #define ZEPHYR_INCLUDE_SYS_MPSC_PBUF_H_
8 :
9 : #include <zephyr/kernel.h>
10 : #include <zephyr/sys/mpsc_packet.h>
11 : #include <string.h>
12 : #include <stdint.h>
13 : #include <stdbool.h>
14 :
15 : #ifdef __cplusplus
16 : extern "C" {
17 : #endif
18 :
19 : /**
20 : * @brief Multi producer, single consumer packet buffer API
21 : * @defgroup mpsc_buf MPSC (Multi producer, single consumer) packet buffer API
22 : * @ingroup datastructure_apis
23 : * @{
24 : */
25 :
26 : /*
27 : * Multi producer, single consumer packet buffer allows to allocate variable
28 : * length consecutive space for storing a packet. When space is allocated
29 : * it can be filled by the user (except for the first 2 bits) and when packet
30 : * is ready it is committed. It is allowed to allocate another packet before
31 : * committing the previous one.
32 : *
33 : * If buffer is full and packet cannot be allocated then null is returned unless
34 : * overwrite mode is selected. In that mode, oldest entry are dropped (user is
35 : * notified) until allocation succeeds. It can happen that candidate for
36 : * dropping is currently being claimed. In that case, it is omitted and next
37 : * packet is dropped and claimed packet is marked as invalid when freeing.
38 : *
39 : * Reading packets is performed in two steps. First packet is claimed. Claiming
40 : * returns pointer to the packet within the buffer. Packet is freed when no
41 : * longer in use.
42 : */
43 :
44 : /**@defgroup MPSC_PBUF_FLAGS MPSC packet buffer flags
45 : * @{
46 : */
47 :
48 : /** @brief Flag indicating that buffer size is power of 2.
49 : *
50 : * When buffer size is power of 2 then optimizations are applied.
51 : */
52 1 : #define MPSC_PBUF_SIZE_POW2 BIT(0)
53 :
54 : /** @brief Flag indicating buffer full policy.
55 : *
56 : * If flag is set then when allocating from a full buffer oldest packets are
57 : * dropped. When flag is not set then allocation returns null.
58 : */
59 1 : #define MPSC_PBUF_MODE_OVERWRITE BIT(1)
60 :
61 : /** @brief Flag indicating that maximum buffer usage is tracked. */
62 1 : #define MPSC_PBUF_MAX_UTILIZATION BIT(2)
63 :
64 : /** @brief Flag indicated that buffer is currently full. */
65 1 : #define MPSC_PBUF_FULL BIT(3)
66 :
67 : /**@} */
68 :
69 : /* Forward declaration */
70 : struct mpsc_pbuf_buffer;
71 :
72 : /** @brief Callback prototype for getting length of a packet.
73 : *
74 : * @param packet User packet.
75 : *
76 : * @return Size of the packet in 32 bit words.
77 : */
78 1 : typedef uint32_t (*mpsc_pbuf_get_wlen)(const union mpsc_pbuf_generic *packet);
79 :
80 : /** @brief Callback called when packet is dropped.
81 : *
82 : * @param buffer Packet buffer.
83 : *
84 : * @param packet Packet that is being dropped.
85 : */
86 1 : typedef void (*mpsc_pbuf_notify_drop)(const struct mpsc_pbuf_buffer *buffer,
87 : const union mpsc_pbuf_generic *packet);
88 :
89 : /** @brief MPSC packet buffer structure. */
90 1 : struct mpsc_pbuf_buffer {
91 : /** Temporary write index. */
92 1 : uint32_t tmp_wr_idx;
93 :
94 : /** Write index. */
95 1 : uint32_t wr_idx;
96 :
97 : /** Temporary read index. */
98 1 : uint32_t tmp_rd_idx;
99 :
100 : /** Read index. */
101 1 : uint32_t rd_idx;
102 :
103 : /** Flags. */
104 1 : uint32_t flags;
105 :
106 : /** Lock. */
107 1 : struct k_spinlock lock;
108 :
109 : /** User callback called whenever packet is dropped.
110 : *
111 : * May be NULL if unneeded.
112 : */
113 1 : mpsc_pbuf_notify_drop notify_drop;
114 :
115 : /** Callback for getting packet length. */
116 1 : mpsc_pbuf_get_wlen get_wlen;
117 :
118 : /* Buffer. */
119 0 : uint32_t *buf;
120 :
121 : /* Buffer size in 32 bit words. */
122 0 : uint32_t size;
123 :
124 : /* Store max buffer usage. */
125 0 : uint32_t max_usage;
126 :
127 0 : struct k_sem sem;
128 : };
129 :
130 : /** @brief MPSC packet buffer configuration. */
131 1 : struct mpsc_pbuf_buffer_config {
132 : /* Pointer to a memory used for storing packets. */
133 0 : uint32_t *buf;
134 :
135 : /* Buffer size in 32 bit words. */
136 0 : uint32_t size;
137 :
138 : /* Callbacks. */
139 0 : mpsc_pbuf_notify_drop notify_drop;
140 0 : mpsc_pbuf_get_wlen get_wlen;
141 :
142 : /* Configuration flags. */
143 0 : uint32_t flags;
144 : };
145 :
146 : /** @brief Initialize a packet buffer.
147 : *
148 : * @param buffer Buffer.
149 : *
150 : * @param config Configuration.
151 : */
152 1 : void mpsc_pbuf_init(struct mpsc_pbuf_buffer *buffer,
153 : const struct mpsc_pbuf_buffer_config *config);
154 :
155 : /** @brief Allocate a packet.
156 : *
157 : * If a buffer is configured to overwrite mode then if there is no space to
158 : * allocate a new buffer, oldest packets are dropped. Otherwise allocation
159 : * fails and null pointer is returned.
160 : *
161 : * @param buffer Buffer.
162 : *
163 : * @param wlen Number of words to allocate.
164 : *
165 : * @param timeout Timeout. If called from thread context it will pend for given
166 : * timeout if packet cannot be allocated before dropping the oldest or
167 : * returning null.
168 : *
169 : * @return Pointer to the allocated space or null if it cannot be allocated.
170 : */
171 1 : union mpsc_pbuf_generic *mpsc_pbuf_alloc(struct mpsc_pbuf_buffer *buffer,
172 : size_t wlen, k_timeout_t timeout);
173 :
174 : /** @brief Commit a packet.
175 : *
176 : * @param buffer Buffer.
177 : *
178 : * @param packet Pointer to a packet allocated by @ref mpsc_pbuf_alloc.
179 : */
180 1 : void mpsc_pbuf_commit(struct mpsc_pbuf_buffer *buffer,
181 : union mpsc_pbuf_generic *packet);
182 :
183 : /** @brief Put single word packet into a buffer.
184 : *
185 : * Function is optimized for storing a packet which fit into a single word.
186 : * Note that 2 bits of that word is used by the buffer.
187 : *
188 : * @param buffer Buffer.
189 : *
190 : * @param word Packet content consisting of MPSC_PBUF_HDR with valid bit set
191 : * and data on remaining bits.
192 : */
193 1 : void mpsc_pbuf_put_word(struct mpsc_pbuf_buffer *buffer,
194 : const union mpsc_pbuf_generic word);
195 :
196 : /** @brief Put a packet consisting of a word and a pointer.
197 : * *
198 : * Function is optimized for storing packet consisting of a word and a pointer.
199 : * Note that 2 bits of a first word is used by the buffer.
200 : *
201 : * @param buffer Buffer.
202 : *
203 : * @param word First word of a packet consisting of MPSC_PBUF_HDR with valid
204 : * bit set and data on remaining bits.
205 : *
206 : * @param data User data.
207 : */
208 1 : void mpsc_pbuf_put_word_ext(struct mpsc_pbuf_buffer *buffer,
209 : const union mpsc_pbuf_generic word,
210 : const void *data);
211 :
212 : /** @brief Put a packet into a buffer.
213 : *
214 : * Copy data into a buffer.
215 : * Note that 2 bits of a first word is used by the buffer.
216 : *
217 : * @param buffer Buffer.
218 : *
219 : * @param data First word of data must contain MPSC_PBUF_HDR with valid bit set.
220 : *
221 : * @param wlen Packet size in words.
222 : */
223 1 : void mpsc_pbuf_put_data(struct mpsc_pbuf_buffer *buffer,
224 : const uint32_t *data, size_t wlen);
225 :
226 : /** @brief Claim the first pending packet.
227 : *
228 : * @param buffer Buffer.
229 : *
230 : * @return Pointer to the claimed packet or null if none available.
231 : */
232 1 : const union mpsc_pbuf_generic *mpsc_pbuf_claim(struct mpsc_pbuf_buffer *buffer);
233 :
234 : /** @brief Free a packet.
235 : *
236 : * @param buffer Buffer.
237 : *
238 : * @param packet Packet.
239 : */
240 1 : void mpsc_pbuf_free(struct mpsc_pbuf_buffer *buffer,
241 : const union mpsc_pbuf_generic *packet);
242 :
243 : /** @brief Check if there are any message pending.
244 : *
245 : * @param buffer Buffer.
246 : *
247 : * @retval true if pending.
248 : * @retval false if no message is pending.
249 : */
250 1 : bool mpsc_pbuf_is_pending(struct mpsc_pbuf_buffer *buffer);
251 :
252 : /** @brief Get current memory utilization.
253 : *
254 : * @param[in, out] buffer Buffer.
255 : * @param[out] size Buffer size in bytes.
256 : * @param[out] now Current buffer usage in bytes.
257 : */
258 1 : void mpsc_pbuf_get_utilization(struct mpsc_pbuf_buffer *buffer,
259 : uint32_t *size, uint32_t *now);
260 :
261 : /** @brief Get maximum memory utilization.
262 : *
263 : * @param[in, out] buffer Buffer.
264 : * @param[out] max Maximum buffer usage in bytes.
265 : *
266 : * retval 0 if utilization data collected successfully.
267 : * retval -ENOTSUP if Collecting utilization data is not supported.
268 : */
269 1 : int mpsc_pbuf_get_max_utilization(struct mpsc_pbuf_buffer *buffer, uint32_t *max);
270 : /**
271 : * @}
272 : */
273 :
274 : #ifdef __cplusplus
275 : }
276 : #endif
277 :
278 : #endif /* ZEPHYR_INCLUDE_SYS_MPSC_PBUF_H_ */
|