LCOV - code coverage report
Current view: top level - zephyr/sys - ring_buffer.h Coverage Total Hit
Test: new.info Lines: 92.0 % 25 23
Test Date: 2025-09-05 16:43:28

            Line data    Source code
       1            0 : /*
       2              :  * Copyright (c) 2015 Intel Corporation
       3              :  *
       4              :  * SPDX-License-Identifier: Apache-2.0
       5              :  */
       6              : 
       7              : #ifndef ZEPHYR_INCLUDE_SYS_RING_BUFFER_H_
       8              : #define ZEPHYR_INCLUDE_SYS_RING_BUFFER_H_
       9              : 
      10              : #include <zephyr/sys/util.h>
      11              : #include <errno.h>
      12              : 
      13              : #ifdef __cplusplus
      14              : extern "C" {
      15              : #endif
      16              : 
      17              : /**
      18              :  * @file
      19              :  * @defgroup ring_buffer_apis Ring Buffer APIs
      20              :  * @ingroup datastructure_apis
      21              :  *
      22              :  * @brief Simple ring buffer implementation.
      23              :  *
      24              :  * @{
      25              :  */
      26              : 
      27              : /** @cond INTERNAL_HIDDEN */
      28              : 
      29              : /* The limit is used by algorithm for distinguishing between empty and full
      30              :  * state.
      31              :  */
      32              : #ifdef CONFIG_RING_BUFFER_LARGE
      33              : typedef uint32_t ring_buf_idx_t;
      34              : #define RING_BUFFER_MAX_SIZE (UINT32_MAX / 2)
      35              : #else
      36              : typedef uint16_t ring_buf_idx_t;
      37              : #define RING_BUFFER_MAX_SIZE (UINT16_MAX / 2)
      38              : #endif
      39              : 
      40              : #define RING_BUFFER_SIZE_ASSERT_MSG "Size too big"
      41              : 
      42              : struct ring_buf_index { ring_buf_idx_t head, tail, base; };
      43              : 
      44              : /** @endcond */
      45              : 
      46              : /**
      47              :  * @brief A structure to represent a ring buffer
      48              :  */
      49            1 : struct ring_buf {
      50              :         /** @cond INTERNAL_HIDDEN */
      51              :         uint8_t *buffer;
      52              :         struct ring_buf_index put;
      53              :         struct ring_buf_index get;
      54              :         uint32_t size;
      55              :         /** @endcond */
      56              : };
      57              : 
      58              : /** @cond INTERNAL_HIDDEN */
      59              : 
      60              : uint32_t ring_buf_area_claim(struct ring_buf *buf, struct ring_buf_index *ring,
      61              :                              uint8_t **data, uint32_t size);
      62              : int ring_buf_area_finish(struct ring_buf *buf, struct ring_buf_index *ring,
      63              :                          uint32_t size);
      64              : 
      65              : /**
      66              :  * @brief Function to force ring_buf internal states to given value
      67              :  *
      68              :  * Any value other than 0 makes sense only in validation testing context.
      69              :  */
      70              : static inline void ring_buf_internal_reset(struct ring_buf *buf, ring_buf_idx_t value)
      71              : {
      72              :         buf->put.head = buf->put.tail = buf->put.base = value;
      73              :         buf->get.head = buf->get.tail = buf->get.base = value;
      74              : }
      75              : 
      76              : /** @endcond */
      77              : 
      78            0 : #define RING_BUF_INIT(buf, size8)       \
      79              : {                                       \
      80              :         .buffer = buf,                  \
      81              :         .size = size8,                  \
      82              : }
      83              : 
      84              : /**
      85              :  * @brief Define and initialize a ring buffer for byte data.
      86              :  *
      87              :  * This macro establishes a ring buffer of an arbitrary size.
      88              :  * The basic storage unit is a byte.
      89              :  *
      90              :  * The ring buffer can be accessed outside the module where it is defined
      91              :  * using:
      92              :  *
      93              :  * @code extern struct ring_buf <name>; @endcode
      94              :  *
      95              :  * @param name  Name of the ring buffer.
      96              :  * @param size8 Size of ring buffer (in bytes).
      97              :  */
      98            1 : #define RING_BUF_DECLARE(name, size8) \
      99              :         BUILD_ASSERT(size8 <= RING_BUFFER_MAX_SIZE,\
     100              :                 RING_BUFFER_SIZE_ASSERT_MSG); \
     101              :         static uint8_t __noinit _ring_buffer_data_##name[size8]; \
     102              :         struct ring_buf name = RING_BUF_INIT(_ring_buffer_data_##name, size8)
     103              : 
     104              : /**
     105              :  * @brief Define and initialize an "item based" ring buffer.
     106              :  *
     107              :  * This macro establishes an "item based" ring buffer. Each data item is
     108              :  * an array of 32-bit words (from zero to 1020 bytes in length), coupled
     109              :  * with a 16-bit type identifier and an 8-bit integer value.
     110              :  *
     111              :  * The ring buffer can be accessed outside the module where it is defined
     112              :  * using:
     113              :  *
     114              :  * @code extern struct ring_buf <name>; @endcode
     115              :  *
     116              :  * @param name Name of the ring buffer.
     117              :  * @param size32 Size of ring buffer (in 32-bit words).
     118              :  */
     119            1 : #define RING_BUF_ITEM_DECLARE(name, size32) \
     120              :         BUILD_ASSERT((size32) <= RING_BUFFER_MAX_SIZE / 4, \
     121              :                 RING_BUFFER_SIZE_ASSERT_MSG); \
     122              :         static uint32_t __noinit _ring_buffer_data_##name[size32]; \
     123              :         struct ring_buf name = { \
     124              :                 .buffer = (uint8_t *) _ring_buffer_data_##name, \
     125              :                 .size = 4 * (size32) \
     126              :         }
     127              : 
     128              : /**
     129              :  * @brief Define and initialize an "item based" ring buffer.
     130              :  *
     131              :  * This exists for backward compatibility reasons. @ref RING_BUF_ITEM_DECLARE
     132              :  * should be used instead.
     133              :  *
     134              :  * @param name Name of the ring buffer.
     135              :  * @param size32 Size of ring buffer (in 32-bit words).
     136              :  */
     137            1 : #define RING_BUF_ITEM_DECLARE_SIZE(name, size32) \
     138              :         RING_BUF_ITEM_DECLARE(name, size32)
     139              : 
     140              : /**
     141              :  * @brief Define and initialize a power-of-2 sized "item based" ring buffer.
     142              :  *
     143              :  * This macro establishes an "item based" ring buffer by specifying its
     144              :  * size using a power of 2. This exists mainly for backward compatibility
     145              :  * reasons. @ref RING_BUF_ITEM_DECLARE should be used instead.
     146              :  *
     147              :  * @param name Name of the ring buffer.
     148              :  * @param pow Ring buffer size exponent.
     149              :  */
     150            1 : #define RING_BUF_ITEM_DECLARE_POW2(name, pow) \
     151              :         RING_BUF_ITEM_DECLARE(name, BIT(pow))
     152              : 
     153              : /**
     154              :  * @brief Compute the ring buffer size in 32-bit needed to store an element
     155              :  *
     156              :  * The argument can be a type or an expression.
     157              :  * Note: rounds up if the size is not a multiple of 32 bits.
     158              :  *
     159              :  * @param expr Expression or type to compute the size of
     160              :  */
     161            1 : #define RING_BUF_ITEM_SIZEOF(expr) DIV_ROUND_UP(sizeof(expr), sizeof(uint32_t))
     162              : 
     163              : /**
     164              :  * @brief Initialize a ring buffer for byte data.
     165              :  *
     166              :  * This routine initializes a ring buffer, prior to its first use. It is only
     167              :  * used for ring buffers not defined using RING_BUF_DECLARE.
     168              :  *
     169              :  * @param buf Address of ring buffer.
     170              :  * @param size Ring buffer size (in bytes).
     171              :  * @param data Ring buffer data area (uint8_t data[size]).
     172              :  */
     173            1 : static inline void ring_buf_init(struct ring_buf *buf,
     174              :                                  uint32_t size,
     175              :                                  uint8_t *data)
     176              : {
     177              :         __ASSERT(size <= RING_BUFFER_MAX_SIZE, RING_BUFFER_SIZE_ASSERT_MSG);
     178              : 
     179              :         buf->size = size;
     180              :         buf->buffer = data;
     181              :         ring_buf_internal_reset(buf, 0);
     182              : }
     183              : 
     184              : /**
     185              :  * @brief Initialize an "item based" ring buffer.
     186              :  *
     187              :  * This routine initializes a ring buffer, prior to its first use. It is only
     188              :  * used for ring buffers not defined using RING_BUF_ITEM_DECLARE.
     189              :  *
     190              :  * Each data item is an array of 32-bit words (from zero to 1020 bytes in
     191              :  * length), coupled with a 16-bit type identifier and an 8-bit integer value.
     192              :  *
     193              :  * @param buf Address of ring buffer.
     194              :  * @param size Ring buffer size (in 32-bit words)
     195              :  * @param data Ring buffer data area (uint32_t data[size]).
     196              :  */
     197            1 : static inline void ring_buf_item_init(struct ring_buf *buf,
     198              :                                       uint32_t size,
     199              :                                       uint32_t *data)
     200              : {
     201              :         __ASSERT(size <= RING_BUFFER_MAX_SIZE / 4, RING_BUFFER_SIZE_ASSERT_MSG);
     202              :         ring_buf_init(buf, 4 * size, (uint8_t *)data);
     203              : }
     204              : 
     205              : /**
     206              :  * @brief Determine if a ring buffer is empty.
     207              :  *
     208              :  * @param buf Address of ring buffer.
     209              :  *
     210              :  * @return true if the ring buffer is empty, or false if not.
     211              :  */
     212            1 : static inline bool ring_buf_is_empty(const struct ring_buf *buf)
     213              : {
     214              :         return buf->get.head == buf->put.tail;
     215              : }
     216              : 
     217              : /**
     218              :  * @brief Reset ring buffer state.
     219              :  *
     220              :  * @param buf Address of ring buffer.
     221              :  */
     222            1 : static inline void ring_buf_reset(struct ring_buf *buf)
     223              : {
     224              :         ring_buf_internal_reset(buf, 0);
     225              : }
     226              : 
     227              : /**
     228              :  * @brief Determine free space in a ring buffer.
     229              :  *
     230              :  * @param buf Address of ring buffer.
     231              :  *
     232              :  * @return Ring buffer free space (in bytes).
     233              :  */
     234            1 : static inline uint32_t ring_buf_space_get(const struct ring_buf *buf)
     235              : {
     236              :         ring_buf_idx_t allocated = buf->put.head - buf->get.tail;
     237              : 
     238              :         return buf->size - allocated;
     239              : }
     240              : 
     241              : /**
     242              :  * @brief Determine free space in an "item based" ring buffer.
     243              :  *
     244              :  * @param buf Address of ring buffer.
     245              :  *
     246              :  * @return Ring buffer free space (in 32-bit words).
     247              :  */
     248            1 : static inline uint32_t ring_buf_item_space_get(const struct ring_buf *buf)
     249              : {
     250              :         return ring_buf_space_get(buf) / 4;
     251              : }
     252              : 
     253              : /**
     254              :  * @brief Return ring buffer capacity.
     255              :  *
     256              :  * @param buf Address of ring buffer.
     257              :  *
     258              :  * @return Ring buffer capacity (in bytes).
     259              :  */
     260            1 : static inline uint32_t ring_buf_capacity_get(const struct ring_buf *buf)
     261              : {
     262              :         return buf->size;
     263              : }
     264              : 
     265              : /**
     266              :  * @brief Determine size of available data in a ring buffer.
     267              :  *
     268              :  * @param buf Address of ring buffer.
     269              :  *
     270              :  * @return Ring buffer data size (in bytes).
     271              :  */
     272            1 : static inline uint32_t ring_buf_size_get(const struct ring_buf *buf)
     273              : {
     274              :         ring_buf_idx_t available = buf->put.tail - buf->get.head;
     275              : 
     276              :         return available;
     277              : }
     278              : 
     279              : /**
     280              :  * @brief Allocate buffer for writing data to a ring buffer.
     281              :  *
     282              :  * With this routine, memory copying can be reduced since internal ring buffer
     283              :  * can be used directly by the user. Once data is written to allocated area
     284              :  * number of bytes written must be confirmed (see @ref ring_buf_put_finish).
     285              :  *
     286              :  * @warning
     287              :  * Use cases involving multiple writers to the ring buffer must prevent
     288              :  * concurrent write operations, either by preventing all writers from
     289              :  * being preempted or by using a mutex to govern writes to the ring buffer.
     290              :  *
     291              :  * @warning
     292              :  * Ring buffer instance should not mix byte access and item access
     293              :  * (calls prefixed with ring_buf_item_).
     294              :  *
     295              :  * @param[in]  buf  Address of ring buffer.
     296              :  * @param[out] data Pointer to the address. It is set to a location within
     297              :  *                  ring buffer.
     298              :  * @param[in]  size Requested allocation size (in bytes).
     299              :  *
     300              :  * @return Size of allocated buffer which can be smaller than requested if
     301              :  *         there is not enough free space or buffer wraps.
     302              :  */
     303            1 : static inline uint32_t ring_buf_put_claim(struct ring_buf *buf,
     304              :                                           uint8_t **data,
     305              :                                           uint32_t size)
     306              : {
     307              :         uint32_t space = ring_buf_space_get(buf);
     308              :         return ring_buf_area_claim(buf, &buf->put, data,
     309              :                                    MIN(size, space));
     310              : }
     311              : 
     312              : /**
     313              :  * @brief Indicate number of bytes written to allocated buffers.
     314              :  *
     315              :  * The number of bytes must be equal to or lower than the sum corresponding
     316              :  * to all preceding @ref ring_buf_put_claim invocations (or even 0). Surplus
     317              :  * bytes will be returned to the available free buffer space.
     318              :  *
     319              :  * @warning
     320              :  * Use cases involving multiple writers to the ring buffer must prevent
     321              :  * concurrent write operations, either by preventing all writers from
     322              :  * being preempted or by using a mutex to govern writes to the ring buffer.
     323              :  *
     324              :  * @warning
     325              :  * Ring buffer instance should not mix byte access and item access
     326              :  * (calls prefixed with ring_buf_item_).
     327              :  *
     328              :  * @param  buf  Address of ring buffer.
     329              :  * @param  size Number of valid bytes in the allocated buffers.
     330              :  *
     331              :  * @retval 0 Successful operation.
     332              :  * @retval -EINVAL Provided @a size exceeds free space in the ring buffer.
     333              :  */
     334            1 : static inline int ring_buf_put_finish(struct ring_buf *buf, uint32_t size)
     335              : {
     336              :         return ring_buf_area_finish(buf, &buf->put, size);
     337              : }
     338              : 
     339              : /**
     340              :  * @brief Write (copy) data to a ring buffer.
     341              :  *
     342              :  * This routine writes data to a ring buffer @a buf.
     343              :  *
     344              :  * @warning
     345              :  * Use cases involving multiple writers to the ring buffer must prevent
     346              :  * concurrent write operations, either by preventing all writers from
     347              :  * being preempted or by using a mutex to govern writes to the ring buffer.
     348              :  *
     349              :  * @warning
     350              :  * Ring buffer instance should not mix byte access and item access
     351              :  * (calls prefixed with ring_buf_item_).
     352              :  *
     353              :  * @param buf Address of ring buffer.
     354              :  * @param data Address of data.
     355              :  * @param size Data size (in bytes).
     356              :  *
     357              :  * @retval Number of bytes written.
     358              :  */
     359            1 : uint32_t ring_buf_put(struct ring_buf *buf, const uint8_t *data, uint32_t size);
     360              : 
     361              : /**
     362              :  * @brief Get address of a valid data in a ring buffer.
     363              :  *
     364              :  * With this routine, memory copying can be reduced since internal ring buffer
     365              :  * can be used directly by the user. Once data is processed it must be freed
     366              :  * using @ref ring_buf_get_finish.
     367              :  *
     368              :  * @warning
     369              :  * Use cases involving multiple reads of the ring buffer must prevent
     370              :  * concurrent read operations, either by preventing all readers from
     371              :  * being preempted or by using a mutex to govern reads to the ring buffer.
     372              :  *
     373              :  * @warning
     374              :  * Ring buffer instance should not mix byte access and item access
     375              :  * (calls prefixed with ring_buf_item_).
     376              :  *
     377              :  * @param[in]  buf  Address of ring buffer.
     378              :  * @param[out] data Pointer to the address. It is set to a location within
     379              :  *                  ring buffer.
     380              :  * @param[in]  size Requested size (in bytes).
     381              :  *
     382              :  * @return Number of valid bytes in the provided buffer which can be smaller
     383              :  *         than requested if there is not enough free space or buffer wraps.
     384              :  */
     385            1 : static inline uint32_t ring_buf_get_claim(struct ring_buf *buf,
     386              :                                           uint8_t **data,
     387              :                                           uint32_t size)
     388              : {
     389              :         uint32_t buf_size = ring_buf_size_get(buf);
     390              :         return ring_buf_area_claim(buf, &buf->get, data,
     391              :                                    MIN(size, buf_size));
     392              : }
     393              : 
     394              : /**
     395              :  * @brief Indicate number of bytes read from claimed buffer.
     396              :  *
     397              :  * The number of bytes must be equal or lower than the sum corresponding to
     398              :  * all preceding @ref ring_buf_get_claim invocations (or even 0). Surplus
     399              :  * bytes will remain available in the buffer.
     400              :  *
     401              :  * @warning
     402              :  * Use cases involving multiple reads of the ring buffer must prevent
     403              :  * concurrent read operations, either by preventing all readers from
     404              :  * being preempted or by using a mutex to govern reads to the ring buffer.
     405              :  *
     406              :  * @warning
     407              :  * Ring buffer instance should not mix byte access and  item mode
     408              :  * (calls prefixed with ring_buf_item_).
     409              :  *
     410              :  * @param  buf  Address of ring buffer.
     411              :  * @param  size Number of bytes that can be freed.
     412              :  *
     413              :  * @retval 0 Successful operation.
     414              :  * @retval -EINVAL Provided @a size exceeds valid bytes in the ring buffer.
     415              :  */
     416            1 : static inline int ring_buf_get_finish(struct ring_buf *buf, uint32_t size)
     417              : {
     418              :         return ring_buf_area_finish(buf, &buf->get, size);
     419              : }
     420              : 
     421              : /**
     422              :  * @brief Read data from a ring buffer.
     423              :  *
     424              :  * This routine reads data from a ring buffer @a buf.
     425              :  *
     426              :  * @warning
     427              :  * Use cases involving multiple reads of the ring buffer must prevent
     428              :  * concurrent read operations, either by preventing all readers from
     429              :  * being preempted or by using a mutex to govern reads to the ring buffer.
     430              :  *
     431              :  * @warning
     432              :  * Ring buffer instance should not mix byte access and  item mode
     433              :  * (calls prefixed with ring_buf_item_).
     434              :  *
     435              :  * @param buf  Address of ring buffer.
     436              :  * @param data Address of the output buffer. Can be NULL to discard data.
     437              :  * @param size Data size (in bytes).
     438              :  *
     439              :  * @retval Number of bytes written to the output buffer.
     440              :  */
     441            1 : uint32_t ring_buf_get(struct ring_buf *buf, uint8_t *data, uint32_t size);
     442              : 
     443              : /**
     444              :  * @brief Peek at data from a ring buffer.
     445              :  *
     446              :  * This routine reads data from a ring buffer @a buf without removal.
     447              :  *
     448              :  * @warning
     449              :  * Use cases involving multiple reads of the ring buffer must prevent
     450              :  * concurrent read operations, either by preventing all readers from
     451              :  * being preempted or by using a mutex to govern reads to the ring buffer.
     452              :  *
     453              :  * @warning
     454              :  * Ring buffer instance should not mix byte access and  item mode
     455              :  * (calls prefixed with ring_buf_item_).
     456              :  *
     457              :  * @warning
     458              :  * Multiple calls to peek will result in the same data being 'peeked'
     459              :  * multiple times. To remove data, use either @ref ring_buf_get or
     460              :  * @ref ring_buf_get_claim followed by @ref ring_buf_get_finish with a
     461              :  * non-zero `size`.
     462              :  *
     463              :  * @param buf  Address of ring buffer.
     464              :  * @param data Address of the output buffer. Cannot be NULL.
     465              :  * @param size Data size (in bytes).
     466              :  *
     467              :  * @retval Number of bytes written to the output buffer.
     468              :  */
     469            1 : uint32_t ring_buf_peek(struct ring_buf *buf, uint8_t *data, uint32_t size);
     470              : 
     471              : /**
     472              :  * @brief Write a data item to a ring buffer.
     473              :  *
     474              :  * This routine writes a data item to ring buffer @a buf. The data item
     475              :  * is an array of 32-bit words (from zero to 1020 bytes in length),
     476              :  * coupled with a 16-bit type identifier and an 8-bit integer value.
     477              :  *
     478              :  * @warning
     479              :  * Use cases involving multiple writers to the ring buffer must prevent
     480              :  * concurrent write operations, either by preventing all writers from
     481              :  * being preempted or by using a mutex to govern writes to the ring buffer.
     482              :  *
     483              :  * @param buf Address of ring buffer.
     484              :  * @param type Data item's type identifier (application specific).
     485              :  * @param value Data item's integer value (application specific).
     486              :  * @param data Address of data item.
     487              :  * @param size32 Data item size (number of 32-bit words).
     488              :  *
     489              :  * @retval 0 Data item was written.
     490              :  * @retval -EMSGSIZE Ring buffer has insufficient free space.
     491              :  */
     492            1 : int ring_buf_item_put(struct ring_buf *buf, uint16_t type, uint8_t value,
     493              :                       uint32_t *data, uint8_t size32);
     494              : 
     495              : /**
     496              :  * @brief Read a data item from a ring buffer.
     497              :  *
     498              :  * This routine reads a data item from ring buffer @a buf. The data item
     499              :  * is an array of 32-bit words (up to 1020 bytes in length),
     500              :  * coupled with a 16-bit type identifier and an 8-bit integer value.
     501              :  *
     502              :  * @warning
     503              :  * Use cases involving multiple reads of the ring buffer must prevent
     504              :  * concurrent read operations, either by preventing all readers from
     505              :  * being preempted or by using a mutex to govern reads to the ring buffer.
     506              :  *
     507              :  * @param buf Address of ring buffer.
     508              :  * @param type Area to store the data item's type identifier.
     509              :  * @param value Area to store the data item's integer value.
     510              :  * @param data Area to store the data item. Can be NULL to discard data.
     511              :  * @param size32 Size of the data item storage area (number of 32-bit chunks).
     512              :  *
     513              :  * @retval 0 Data item was fetched; @a size32 now contains the number of
     514              :  *         32-bit words read into data area @a data.
     515              :  * @retval -EAGAIN Ring buffer is empty.
     516              :  * @retval -EMSGSIZE Data area @a data is too small; @a size32 now contains
     517              :  *         the number of 32-bit words needed.
     518              :  */
     519            1 : int ring_buf_item_get(struct ring_buf *buf, uint16_t *type, uint8_t *value,
     520              :                       uint32_t *data, uint8_t *size32);
     521              : 
     522              : /**
     523              :  * @}
     524              :  */
     525              : 
     526              : #ifdef __cplusplus
     527              : }
     528              : #endif
     529              : 
     530              : #endif /* ZEPHYR_INCLUDE_SYS_RING_BUFFER_H_ */
        

Generated by: LCOV version 2.0-1