ring_buffer: factorize almost identical code
Factorize almost identical code. May even improve performance due to CPU cache locality. Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
This commit is contained in:
parent
83279d1524
commit
3075a7d906
@ -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.
|
||||
|
||||
@ -9,46 +9,45 @@
|
||||
#include <zephyr/sys/ring_buffer.h>
|
||||
#include <string.h>
|
||||
|
||||
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;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user