diff --git a/include/zephyr/sys/ring_buffer.h b/include/zephyr/sys/ring_buffer.h index ee63976d784..e104fd5443e 100644 --- a/include/zephyr/sys/ring_buffer.h +++ b/include/zephyr/sys/ring_buffer.h @@ -14,16 +14,6 @@ extern "C" { #endif -/** @cond INTERNAL_HIDDEN */ -/* The limit is used by algorithm for distinguishing between empty and full - * state. - */ -#define RING_BUFFER_MAX_SIZE 0x80000000U - -#define RING_BUFFER_SIZE_ASSERT_MSG \ - "Size too big" -/** @endcond */ - /** * @file * @defgroup ring_buffer_apis Ring Buffer APIs @@ -34,22 +24,38 @@ extern "C" { * @{ */ +/** @cond INTERNAL_HIDDEN */ + +/* The limit is used by algorithm for distinguishing between empty and full + * state. + */ +#define RING_BUFFER_MAX_SIZE 0x80000000U +#define RING_BUFFER_SIZE_ASSERT_MSG \ + "Size too big" + +struct ring_buf_index { int32_t head, tail, base; }; + +/** @endcond */ + /** * @brief A structure to represent a ring buffer */ struct ring_buf { /** @cond INTERNAL_HIDDEN */ uint8_t *buffer; - int32_t put_head; - int32_t put_tail; - int32_t put_base; - int32_t get_head; - int32_t get_tail; - int32_t get_base; + struct ring_buf_index put; + struct ring_buf_index get; uint32_t size; /** @endcond */ }; +/** @cond INTERNAL_HIDDEN */ + +uint32_t ring_buf_area_claim(struct ring_buf *buf, struct ring_buf_index *ring, + uint8_t **data, uint32_t size); +int ring_buf_area_finish(struct ring_buf *buf, struct ring_buf_index *ring, + uint32_t size); + /** * @brief Function to force ring_buf internal states to given value * @@ -57,15 +63,18 @@ struct ring_buf { */ static inline void ring_buf_internal_reset(struct ring_buf *buf, int32_t value) { - buf->put_head = buf->put_tail = buf->put_base = value; - buf->get_head = buf->get_tail = buf->get_base = value; + buf->put.head = buf->put.tail = buf->put.base = value; + buf->get.head = buf->get.tail = buf->get.base = value; } +/** @endcond */ + #define RING_BUF_INIT(buf, size8) \ { \ .buffer = buf, \ .size = size8, \ } + /** * @brief Define and initialize a ring buffer for byte data. * @@ -196,7 +205,7 @@ static inline void ring_buf_item_init(struct ring_buf *buf, */ static inline bool ring_buf_is_empty(struct ring_buf *buf) { - return buf->get_head == buf->put_tail; + return buf->get.head == buf->put.tail; } /** @@ -218,7 +227,7 @@ static inline void ring_buf_reset(struct ring_buf *buf) */ static inline uint32_t ring_buf_space_get(struct ring_buf *buf) { - return buf->size - (buf->put_head - buf->get_tail); + return buf->size - (buf->put.head - buf->get.tail); } /** @@ -254,7 +263,7 @@ static inline uint32_t ring_buf_capacity_get(struct ring_buf *buf) */ static inline uint32_t ring_buf_size_get(struct ring_buf *buf) { - return buf->put_tail - buf->get_head; + return buf->put.tail - buf->get.head; } /** @@ -281,9 +290,13 @@ static inline uint32_t ring_buf_size_get(struct ring_buf *buf) * @return Size of allocated buffer which can be smaller than requested if * there is not enough free space or buffer wraps. */ -uint32_t ring_buf_put_claim(struct ring_buf *buf, - uint8_t **data, - uint32_t size); +static inline uint32_t ring_buf_put_claim(struct ring_buf *buf, + uint8_t **data, + uint32_t size) +{ + return ring_buf_area_claim(buf, &buf->put, data, + MIN(size, ring_buf_space_get(buf))); +} /** * @brief Indicate number of bytes written to allocated buffers. @@ -307,7 +320,10 @@ uint32_t ring_buf_put_claim(struct ring_buf *buf, * @retval 0 Successful operation. * @retval -EINVAL Provided @a size exceeds free space in the ring buffer. */ -int ring_buf_put_finish(struct ring_buf *buf, uint32_t size); +static inline int ring_buf_put_finish(struct ring_buf *buf, uint32_t size) +{ + return ring_buf_area_finish(buf, &buf->put, size); +} /** * @brief Write (copy) data to a ring buffer. @@ -355,9 +371,13 @@ uint32_t ring_buf_put(struct ring_buf *buf, const uint8_t *data, uint32_t size); * @return Number of valid bytes in the provided buffer which can be smaller * than requested if there is not enough free space or buffer wraps. */ -uint32_t ring_buf_get_claim(struct ring_buf *buf, - uint8_t **data, - uint32_t size); +static inline uint32_t ring_buf_get_claim(struct ring_buf *buf, + uint8_t **data, + uint32_t size) +{ + return ring_buf_area_claim(buf, &buf->get, data, + MIN(size, ring_buf_size_get(buf))); +} /** * @brief Indicate number of bytes read from claimed buffer. @@ -381,7 +401,10 @@ uint32_t ring_buf_get_claim(struct ring_buf *buf, * @retval 0 Successful operation. * @retval -EINVAL Provided @a size exceeds valid bytes in the ring buffer. */ -int ring_buf_get_finish(struct ring_buf *buf, uint32_t size); +static inline int ring_buf_get_finish(struct ring_buf *buf, uint32_t size) +{ + return ring_buf_area_finish(buf, &buf->get, size); +} /** * @brief Read data from a ring buffer. diff --git a/lib/utils/ring_buffer.c b/lib/utils/ring_buffer.c index 43071887c41..32d997205a2 100644 --- a/lib/utils/ring_buffer.c +++ b/lib/utils/ring_buffer.c @@ -9,46 +9,45 @@ #include #include -uint32_t ring_buf_put_claim(struct ring_buf *buf, uint8_t **data, uint32_t size) +uint32_t ring_buf_area_claim(struct ring_buf *buf, struct ring_buf_index *ring, + uint8_t **data, uint32_t size) { - uint32_t free_space, wrap_size; + uint32_t wrap_size; int32_t base; - base = buf->put_base; - wrap_size = buf->put_head - base; + base = ring->base; + wrap_size = ring->head - base; if (unlikely(wrap_size >= buf->size)) { - /* put_base is not yet adjusted */ + /* ring->base is not yet adjusted */ wrap_size -= buf->size; base += buf->size; } wrap_size = buf->size - wrap_size; - - free_space = ring_buf_space_get(buf); - size = MIN(size, free_space); size = MIN(size, wrap_size); - *data = &buf->buffer[buf->put_head - base]; - buf->put_head += size; + *data = &buf->buffer[ring->head - base]; + ring->head += size; return size; } -int ring_buf_put_finish(struct ring_buf *buf, uint32_t size) +int ring_buf_area_finish(struct ring_buf *buf, struct ring_buf_index *ring, + uint32_t size) { - uint32_t finish_space, wrap_size; + uint32_t claimed_size, wrap_size; - finish_space = buf->put_head - buf->put_tail; - if (unlikely(size > finish_space)) { + claimed_size = ring->head - ring->tail; + if (unlikely(size > claimed_size)) { return -EINVAL; } - buf->put_tail += size; - buf->put_head = buf->put_tail; + ring->tail += size; + ring->head = ring->tail; - wrap_size = buf->put_tail - buf->put_base; + wrap_size = ring->tail - ring->base; if (unlikely(wrap_size >= buf->size)) { - /* we wrapped: adjust put_base */ - buf->put_base += buf->size; + /* we wrapped: adjust ring->base */ + ring->base += buf->size; } return 0; @@ -79,51 +78,6 @@ uint32_t ring_buf_put(struct ring_buf *buf, const uint8_t *data, uint32_t size) return total_size; } -uint32_t ring_buf_get_claim(struct ring_buf *buf, uint8_t **data, uint32_t size) -{ - uint32_t available_size, wrap_size; - int32_t base; - - base = buf->get_base; - wrap_size = buf->get_head - base; - if (unlikely(wrap_size >= buf->size)) { - /* get_base is not yet adjusted */ - wrap_size -= buf->size; - base += buf->size; - } - wrap_size = buf->size - wrap_size; - - available_size = ring_buf_size_get(buf); - size = MIN(size, available_size); - size = MIN(size, wrap_size); - - *data = &buf->buffer[buf->get_head - base]; - buf->get_head += size; - - return size; -} - -int ring_buf_get_finish(struct ring_buf *buf, uint32_t size) -{ - uint32_t finish_space, wrap_size; - - finish_space = buf->get_head - buf->get_tail; - if (unlikely(size > finish_space)) { - return -EINVAL; - } - - buf->get_tail += size; - buf->get_head = buf->get_tail; - - wrap_size = buf->get_tail - buf->get_base; - if (unlikely(wrap_size >= buf->size)) { - /* we wrapped: adjust get_base */ - buf->get_base += buf->size; - } - - return 0; -} - uint32_t ring_buf_get(struct ring_buf *buf, uint8_t *data, uint32_t size) { uint8_t *src;