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_ */