Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 | /* ring_buffer.h: Simple ring buffer API */ /* * Copyright (c) 2015 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ /** @file */ #ifndef __RING_BUFFER_H__ #define __RING_BUFFER_H__ #include <kernel.h> #include <misc/util.h> #include <errno.h> #ifdef __cplusplus extern "C" { #endif #define SIZE32_OF(x) (sizeof((x))/sizeof(u32_t)) /** * @brief A structure to represent a ring buffer */ struct ring_buf { u32_t head; /**< Index in buf for the head element */ u32_t tail; /**< Index in buf for the tail element */ u32_t dropped_put_count; /**< Running tally of the number of failed * put attempts */ u32_t size; /**< Size of buf in 32-bit chunks */ u32_t *buf; /**< Memory region for stored entries */ u32_t mask; /**< Modulo mask if size is a power of 2 */ }; /** * @defgroup ring_buffer_apis Ring Buffer APIs * @ingroup kernel_apis * @{ */ /** * @brief Statically define and initialize a high performance ring buffer. * * This macro establishes a ring buffer whose size must be a power of 2; * that is, the ring buffer contains 2^pow 32-bit words, where @a pow is * the specified ring buffer size exponent. A high performance ring buffer * doesn't require the use of modulo arithmetic operations to maintain itself. * * The ring buffer can be accessed outside the module where it is defined * using: * * @code extern struct ring_buf <name>; @endcode * * @param name Name of the ring buffer. * @param pow Ring buffer size exponent. */ #define SYS_RING_BUF_DECLARE_POW2(name, pow) \ static u32_t _ring_buffer_data_##name[1 << (pow)]; \ struct ring_buf name = { \ .size = (1 << (pow)), \ .mask = (1 << (pow)) - 1, \ .buf = _ring_buffer_data_##name \ }; /** * @brief Statically define and initialize a standard ring buffer. * * This macro establishes a ring buffer of an arbitrary size. A standard * ring buffer uses modulo arithmetic operations to maintain itself. * * The ring buffer can be accessed outside the module where it is defined * using: * * @code extern struct ring_buf <name>; @endcode * * @param name Name of the ring buffer. * @param size32 Size of ring buffer (in 32-bit words). */ #define SYS_RING_BUF_DECLARE_SIZE(name, size32) \ static u32_t _ring_buffer_data_##name[size32]; \ struct ring_buf name = { \ .size = size32, \ .buf = _ring_buffer_data_##name \ }; /** * @brief Initialize a ring buffer. * * This routine initializes a ring buffer, prior to its first use. It is only * used for ring buffers not defined using SYS_RING_BUF_DECLARE_POW2 or * SYS_RING_BUF_DECLARE_SIZE. * * Setting @a size to a power of 2 establishes a high performance ring buffer * that doesn't require the use of modulo arithmetic operations to maintain * itself. * * @param buf Address of ring buffer. * @param size Ring buffer size (in 32-bit words). * @param data Ring buffer data area (typically u32_t data[size]). */ static inline void sys_ring_buf_init(struct ring_buf *buf, u32_t size, u32_t *data) { buf->head = 0; buf->tail = 0; buf->dropped_put_count = 0; buf->size = size; buf->buf = data; if (is_power_of_two(size)) { buf->mask = size - 1; } else { buf->mask = 0; } } /** * @brief Determine if a ring buffer is empty. * * @param buf Address of ring buffer. * * @return 1 if the ring buffer is empty, or 0 if not. */ static inline int sys_ring_buf_is_empty(struct ring_buf *buf) { return (buf->head == buf->tail); } /** * @brief Determine free space in a ring buffer. * * @param buf Address of ring buffer. * * @return Ring buffer free space (in 32-bit words). */ static inline int sys_ring_buf_space_get(struct ring_buf *buf) { if (sys_ring_buf_is_empty(buf)) { return buf->size - 1; } if (buf->tail < buf->head) { return buf->head - buf->tail - 1; } /* buf->tail > buf->head */ return (buf->size - buf->tail) + buf->head - 1; } /** * @brief Write a data item to a ring buffer. * * This routine writes a data item to ring buffer @a buf. The data item * is an array of 32-bit words (from zero to 1020 bytes in length), * coupled with a 16-bit type identifier and an 8-bit integer value. * * @warning * Use cases involving multiple writers to the ring buffer must prevent * concurrent write operations, either by preventing all writers from * being preempted or by using a mutex to govern writes to the ring buffer. * * @param buf Address of ring buffer. * @param type Data item's type identifier (application specific). * @param value Data item's integer value (application specific). * @param data Address of data item. * @param size32 Data item size (number of 32-bit words). * * @retval 0 Data item was written. * @retval -EMSGSIZE Ring buffer has insufficient free space. */ int sys_ring_buf_put(struct ring_buf *buf, u16_t type, u8_t value, u32_t *data, u8_t size32); /** * @brief Read a data item from a ring buffer. * * This routine reads a data item from ring buffer @a buf. The data item * is an array of 32-bit words (up to 1020 bytes in length), * coupled with a 16-bit type identifier and an 8-bit integer value. * * @warning * Use cases involving multiple reads of the ring buffer must prevent * concurrent read operations, either by preventing all readers from * being preempted or by using a mutex to govern reads to the ring buffer. * * @param buf Address of ring buffer. * @param type Area to store the data item's type identifier. * @param value Area to store the data item's integer value. * @param data Area to store the data item. * @param size32 Size of the data item storage area (number of 32-bit chunks). * * @retval 0 Data item was fetched; @a size32 now contains the number of * 32-bit words read into data area @a data. * @retval -EAGAIN Ring buffer is empty. * @retval -EMSGSIZE Data area @a data is too small; @a size32 now contains * the number of 32-bit words needed. */ int sys_ring_buf_get(struct ring_buf *buf, u16_t *type, u8_t *value, u32_t *data, u8_t *size32); /** * @} */ #ifdef __cplusplus } #endif #endif /* __RING_BUFFER_H__ */ |