Skip to content

Commit 3075a7d

Browse files
Nicolas Pitrekartben
authored andcommitted
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>
1 parent 83279d1 commit 3075a7d

File tree

2 files changed

+70
-93
lines changed

2 files changed

+70
-93
lines changed

include/zephyr/sys/ring_buffer.h

Lines changed: 52 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,6 @@
1414
extern "C" {
1515
#endif
1616

17-
/** @cond INTERNAL_HIDDEN */
18-
/* The limit is used by algorithm for distinguishing between empty and full
19-
* state.
20-
*/
21-
#define RING_BUFFER_MAX_SIZE 0x80000000U
22-
23-
#define RING_BUFFER_SIZE_ASSERT_MSG \
24-
"Size too big"
25-
/** @endcond */
26-
2717
/**
2818
* @file
2919
* @defgroup ring_buffer_apis Ring Buffer APIs
@@ -34,38 +24,57 @@ extern "C" {
3424
* @{
3525
*/
3626

27+
/** @cond INTERNAL_HIDDEN */
28+
29+
/* The limit is used by algorithm for distinguishing between empty and full
30+
* state.
31+
*/
32+
#define RING_BUFFER_MAX_SIZE 0x80000000U
33+
#define RING_BUFFER_SIZE_ASSERT_MSG \
34+
"Size too big"
35+
36+
struct ring_buf_index { int32_t head, tail, base; };
37+
38+
/** @endcond */
39+
3740
/**
3841
* @brief A structure to represent a ring buffer
3942
*/
4043
struct ring_buf {
4144
/** @cond INTERNAL_HIDDEN */
4245
uint8_t *buffer;
43-
int32_t put_head;
44-
int32_t put_tail;
45-
int32_t put_base;
46-
int32_t get_head;
47-
int32_t get_tail;
48-
int32_t get_base;
46+
struct ring_buf_index put;
47+
struct ring_buf_index get;
4948
uint32_t size;
5049
/** @endcond */
5150
};
5251

52+
/** @cond INTERNAL_HIDDEN */
53+
54+
uint32_t ring_buf_area_claim(struct ring_buf *buf, struct ring_buf_index *ring,
55+
uint8_t **data, uint32_t size);
56+
int ring_buf_area_finish(struct ring_buf *buf, struct ring_buf_index *ring,
57+
uint32_t size);
58+
5359
/**
5460
* @brief Function to force ring_buf internal states to given value
5561
*
5662
* Any value other than 0 makes sense only in validation testing context.
5763
*/
5864
static inline void ring_buf_internal_reset(struct ring_buf *buf, int32_t value)
5965
{
60-
buf->put_head = buf->put_tail = buf->put_base = value;
61-
buf->get_head = buf->get_tail = buf->get_base = value;
66+
buf->put.head = buf->put.tail = buf->put.base = value;
67+
buf->get.head = buf->get.tail = buf->get.base = value;
6268
}
6369

70+
/** @endcond */
71+
6472
#define RING_BUF_INIT(buf, size8) \
6573
{ \
6674
.buffer = buf, \
6775
.size = size8, \
6876
}
77+
6978
/**
7079
* @brief Define and initialize a ring buffer for byte data.
7180
*
@@ -196,7 +205,7 @@ static inline void ring_buf_item_init(struct ring_buf *buf,
196205
*/
197206
static inline bool ring_buf_is_empty(struct ring_buf *buf)
198207
{
199-
return buf->get_head == buf->put_tail;
208+
return buf->get.head == buf->put.tail;
200209
}
201210

202211
/**
@@ -218,7 +227,7 @@ static inline void ring_buf_reset(struct ring_buf *buf)
218227
*/
219228
static inline uint32_t ring_buf_space_get(struct ring_buf *buf)
220229
{
221-
return buf->size - (buf->put_head - buf->get_tail);
230+
return buf->size - (buf->put.head - buf->get.tail);
222231
}
223232

224233
/**
@@ -254,7 +263,7 @@ static inline uint32_t ring_buf_capacity_get(struct ring_buf *buf)
254263
*/
255264
static inline uint32_t ring_buf_size_get(struct ring_buf *buf)
256265
{
257-
return buf->put_tail - buf->get_head;
266+
return buf->put.tail - buf->get.head;
258267
}
259268

260269
/**
@@ -281,9 +290,13 @@ static inline uint32_t ring_buf_size_get(struct ring_buf *buf)
281290
* @return Size of allocated buffer which can be smaller than requested if
282291
* there is not enough free space or buffer wraps.
283292
*/
284-
uint32_t ring_buf_put_claim(struct ring_buf *buf,
285-
uint8_t **data,
286-
uint32_t size);
293+
static inline uint32_t ring_buf_put_claim(struct ring_buf *buf,
294+
uint8_t **data,
295+
uint32_t size)
296+
{
297+
return ring_buf_area_claim(buf, &buf->put, data,
298+
MIN(size, ring_buf_space_get(buf)));
299+
}
287300

288301
/**
289302
* @brief Indicate number of bytes written to allocated buffers.
@@ -307,7 +320,10 @@ uint32_t ring_buf_put_claim(struct ring_buf *buf,
307320
* @retval 0 Successful operation.
308321
* @retval -EINVAL Provided @a size exceeds free space in the ring buffer.
309322
*/
310-
int ring_buf_put_finish(struct ring_buf *buf, uint32_t size);
323+
static inline int ring_buf_put_finish(struct ring_buf *buf, uint32_t size)
324+
{
325+
return ring_buf_area_finish(buf, &buf->put, size);
326+
}
311327

312328
/**
313329
* @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);
355371
* @return Number of valid bytes in the provided buffer which can be smaller
356372
* than requested if there is not enough free space or buffer wraps.
357373
*/
358-
uint32_t ring_buf_get_claim(struct ring_buf *buf,
359-
uint8_t **data,
360-
uint32_t size);
374+
static inline uint32_t ring_buf_get_claim(struct ring_buf *buf,
375+
uint8_t **data,
376+
uint32_t size)
377+
{
378+
return ring_buf_area_claim(buf, &buf->get, data,
379+
MIN(size, ring_buf_size_get(buf)));
380+
}
361381

362382
/**
363383
* @brief Indicate number of bytes read from claimed buffer.
@@ -381,7 +401,10 @@ uint32_t ring_buf_get_claim(struct ring_buf *buf,
381401
* @retval 0 Successful operation.
382402
* @retval -EINVAL Provided @a size exceeds valid bytes in the ring buffer.
383403
*/
384-
int ring_buf_get_finish(struct ring_buf *buf, uint32_t size);
404+
static inline int ring_buf_get_finish(struct ring_buf *buf, uint32_t size)
405+
{
406+
return ring_buf_area_finish(buf, &buf->get, size);
407+
}
385408

386409
/**
387410
* @brief Read data from a ring buffer.

lib/utils/ring_buffer.c

Lines changed: 18 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -9,46 +9,45 @@
99
#include <zephyr/sys/ring_buffer.h>
1010
#include <string.h>
1111

12-
uint32_t ring_buf_put_claim(struct ring_buf *buf, uint8_t **data, uint32_t size)
12+
uint32_t ring_buf_area_claim(struct ring_buf *buf, struct ring_buf_index *ring,
13+
uint8_t **data, uint32_t size)
1314
{
14-
uint32_t free_space, wrap_size;
15+
uint32_t wrap_size;
1516
int32_t base;
1617

17-
base = buf->put_base;
18-
wrap_size = buf->put_head - base;
18+
base = ring->base;
19+
wrap_size = ring->head - base;
1920
if (unlikely(wrap_size >= buf->size)) {
20-
/* put_base is not yet adjusted */
21+
/* ring->base is not yet adjusted */
2122
wrap_size -= buf->size;
2223
base += buf->size;
2324
}
2425
wrap_size = buf->size - wrap_size;
25-
26-
free_space = ring_buf_space_get(buf);
27-
size = MIN(size, free_space);
2826
size = MIN(size, wrap_size);
2927

30-
*data = &buf->buffer[buf->put_head - base];
31-
buf->put_head += size;
28+
*data = &buf->buffer[ring->head - base];
29+
ring->head += size;
3230

3331
return size;
3432
}
3533

36-
int ring_buf_put_finish(struct ring_buf *buf, uint32_t size)
34+
int ring_buf_area_finish(struct ring_buf *buf, struct ring_buf_index *ring,
35+
uint32_t size)
3736
{
38-
uint32_t finish_space, wrap_size;
37+
uint32_t claimed_size, wrap_size;
3938

40-
finish_space = buf->put_head - buf->put_tail;
41-
if (unlikely(size > finish_space)) {
39+
claimed_size = ring->head - ring->tail;
40+
if (unlikely(size > claimed_size)) {
4241
return -EINVAL;
4342
}
4443

45-
buf->put_tail += size;
46-
buf->put_head = buf->put_tail;
44+
ring->tail += size;
45+
ring->head = ring->tail;
4746

48-
wrap_size = buf->put_tail - buf->put_base;
47+
wrap_size = ring->tail - ring->base;
4948
if (unlikely(wrap_size >= buf->size)) {
50-
/* we wrapped: adjust put_base */
51-
buf->put_base += buf->size;
49+
/* we wrapped: adjust ring->base */
50+
ring->base += buf->size;
5251
}
5352

5453
return 0;
@@ -79,51 +78,6 @@ uint32_t ring_buf_put(struct ring_buf *buf, const uint8_t *data, uint32_t size)
7978
return total_size;
8079
}
8180

82-
uint32_t ring_buf_get_claim(struct ring_buf *buf, uint8_t **data, uint32_t size)
83-
{
84-
uint32_t available_size, wrap_size;
85-
int32_t base;
86-
87-
base = buf->get_base;
88-
wrap_size = buf->get_head - base;
89-
if (unlikely(wrap_size >= buf->size)) {
90-
/* get_base is not yet adjusted */
91-
wrap_size -= buf->size;
92-
base += buf->size;
93-
}
94-
wrap_size = buf->size - wrap_size;
95-
96-
available_size = ring_buf_size_get(buf);
97-
size = MIN(size, available_size);
98-
size = MIN(size, wrap_size);
99-
100-
*data = &buf->buffer[buf->get_head - base];
101-
buf->get_head += size;
102-
103-
return size;
104-
}
105-
106-
int ring_buf_get_finish(struct ring_buf *buf, uint32_t size)
107-
{
108-
uint32_t finish_space, wrap_size;
109-
110-
finish_space = buf->get_head - buf->get_tail;
111-
if (unlikely(size > finish_space)) {
112-
return -EINVAL;
113-
}
114-
115-
buf->get_tail += size;
116-
buf->get_head = buf->get_tail;
117-
118-
wrap_size = buf->get_tail - buf->get_base;
119-
if (unlikely(wrap_size >= buf->size)) {
120-
/* we wrapped: adjust get_base */
121-
buf->get_base += buf->size;
122-
}
123-
124-
return 0;
125-
}
126-
12781
uint32_t ring_buf_get(struct ring_buf *buf, uint8_t *data, uint32_t size)
12882
{
12983
uint8_t *src;

0 commit comments

Comments
 (0)