Skip to content

Commit fc67877

Browse files
committed
[components][ipc][rb] add utests and fix stability corner cases
1 parent 6a635e3 commit fc67877

File tree

5 files changed

+1061
-24
lines changed

5 files changed

+1061
-24
lines changed

components/drivers/ipc/ringbuffer.c

Lines changed: 58 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
* 2016-08-18 heyuanjie add interface
1111
* 2021-07-20 arminker fix write_index bug in function rt_ringbuffer_put_force
1212
* 2021-08-14 Jackistang add comments for function interface.
13+
* 2026-03-16 RyanCW(Codex) fix put_force overwrite in wrapped state
1314
*/
1415

1516
#include <rtdevice.h>
@@ -39,7 +40,8 @@ void rt_ringbuffer_init(struct rt_ringbuffer *rb,
3940
rt_int32_t size)
4041
{
4142
RT_ASSERT(rb != RT_NULL);
42-
RT_ASSERT(size > 0);
43+
RT_ASSERT(pool != RT_NULL);
44+
RT_ASSERT(size >= RT_ALIGN_SIZE);
4345

4446
/* initialize read and write index */
4547
rb->read_mirror = rb->read_index = 0;
@@ -67,6 +69,9 @@ rt_size_t rt_ringbuffer_put(struct rt_ringbuffer *rb,
6769
rt_uint32_t size;
6870

6971
RT_ASSERT(rb != RT_NULL);
72+
if (length == 0)
73+
return 0;
74+
RT_ASSERT(ptr != RT_NULL);
7075

7176
/* whether has enough space */
7277
size = rt_ringbuffer_space_len(rb);
@@ -118,49 +123,71 @@ rt_size_t rt_ringbuffer_put_force(struct rt_ringbuffer *rb,
118123
rt_uint32_t length)
119124
{
120125
rt_uint32_t space_length;
126+
rt_uint32_t drop_length;
121127

122128
RT_ASSERT(rb != RT_NULL);
123129

124-
space_length = rt_ringbuffer_space_len(rb);
130+
if (length == 0)
131+
return 0;
132+
RT_ASSERT(ptr != RT_NULL);
125133

134+
/* Oversize write keeps the latest bytes. */
126135
if (length > rb->buffer_size)
127136
{
128137
ptr = &ptr[length - rb->buffer_size];
129138
length = rb->buffer_size;
130139
}
131140

141+
space_length = rt_ringbuffer_space_len(rb);
142+
143+
rt_bool_t overflow = (length > space_length);
144+
145+
if (overflow)
146+
{
147+
/* Drop the oldest bytes to make room for the incoming data. */
148+
drop_length = length - space_length;
149+
if (rb->buffer_size - rb->read_index > drop_length)
150+
{
151+
rb->read_index += drop_length;
152+
}
153+
else
154+
{
155+
drop_length -= (rb->buffer_size - rb->read_index);
156+
rb->read_index = drop_length;
157+
/* Read pointer wraps to the other side of the mirror. */
158+
rb->read_mirror = ~rb->read_mirror;
159+
}
160+
}
161+
132162
if (rb->buffer_size - rb->write_index > length)
133163
{
134164
/* read_index - write_index = empty space */
135165
rt_memcpy(&rb->buffer_ptr[rb->write_index], ptr, length);
136166
/* this should not cause overflow because there is enough space for
137167
* length of data in current mirror */
138168
rb->write_index += length;
139-
140-
if (length > space_length)
141-
rb->read_index = rb->write_index;
142-
143-
return length;
144169
}
170+
else
171+
{
172+
rt_uint32_t tail = rb->buffer_size - rb->write_index;
145173

146-
rt_memcpy(&rb->buffer_ptr[rb->write_index],
147-
&ptr[0],
148-
rb->buffer_size - rb->write_index);
149-
rt_memcpy(&rb->buffer_ptr[0],
150-
&ptr[rb->buffer_size - rb->write_index],
151-
length - (rb->buffer_size - rb->write_index));
152-
153-
/* we are going into the other side of the mirror */
154-
rb->write_mirror = ~rb->write_mirror;
155-
rb->write_index = length - (rb->buffer_size - rb->write_index);
174+
rt_memcpy(&rb->buffer_ptr[rb->write_index], ptr, tail);
175+
rt_memcpy(&rb->buffer_ptr[0], &ptr[tail], length - tail);
156176

157-
if (length > space_length)
158-
{
159-
if (rb->write_index <= rb->read_index)
160-
rb->read_mirror = ~rb->read_mirror;
161-
rb->read_index = rb->write_index;
177+
/* we are going into the other side of the mirror */
178+
rb->write_mirror = ~rb->write_mirror;
179+
rb->write_index = length - tail;
162180
}
163181

182+
/*
183+
* If we dropped data and write catches up to read, we must keep
184+
* "full" distinct from "empty" by flipping the write mirror.
185+
*/
186+
if (overflow &&
187+
(rb->write_index == rb->read_index) &&
188+
(rb->write_mirror == rb->read_mirror))
189+
rb->write_mirror = ~rb->write_mirror;
190+
164191
return length;
165192
}
166193
RTM_EXPORT(rt_ringbuffer_put_force);
@@ -181,6 +208,9 @@ rt_size_t rt_ringbuffer_get(struct rt_ringbuffer *rb,
181208
rt_size_t size;
182209

183210
RT_ASSERT(rb != RT_NULL);
211+
if (length == 0)
212+
return 0;
213+
RT_ASSERT(ptr != RT_NULL);
184214

185215
/* whether has enough data */
186216
size = rt_ringbuffer_data_len(rb);
@@ -235,6 +265,7 @@ rt_size_t rt_ringbuffer_get_direct(struct rt_ringbuffer *rb, rt_uint8_t **ptr)
235265
rt_size_t size;
236266

237267
RT_ASSERT(rb != RT_NULL);
268+
RT_ASSERT(ptr != RT_NULL);
238269

239270
*ptr = RT_NULL;
240271

@@ -278,6 +309,7 @@ rt_size_t rt_ringbuffer_peek(struct rt_ringbuffer *rb, rt_uint8_t **ptr)
278309
rt_size_t size;
279310

280311
RT_ASSERT(rb != RT_NULL);
312+
RT_ASSERT(ptr != RT_NULL);
281313

282314
*ptr = RT_NULL;
283315

@@ -386,6 +418,7 @@ RTM_EXPORT(rt_ringbuffer_putchar_force);
386418
rt_size_t rt_ringbuffer_getchar(struct rt_ringbuffer *rb, rt_uint8_t *ch)
387419
{
388420
RT_ASSERT(rb != RT_NULL);
421+
RT_ASSERT(ch != RT_NULL);
389422

390423
/* ringbuffer is empty */
391424
if (!rt_ringbuffer_data_len(rb))
@@ -417,6 +450,8 @@ RTM_EXPORT(rt_ringbuffer_getchar);
417450
*/
418451
rt_size_t rt_ringbuffer_data_len(struct rt_ringbuffer *rb)
419452
{
453+
RT_ASSERT(rb != RT_NULL);
454+
420455
switch (rt_ringbuffer_status(rb))
421456
{
422457
case RT_RINGBUFFER_EMPTY:
@@ -467,7 +502,7 @@ struct rt_ringbuffer *rt_ringbuffer_create(rt_uint32_t size)
467502
struct rt_ringbuffer *rb;
468503
rt_uint8_t *pool;
469504

470-
RT_ASSERT(size > 0);
505+
RT_ASSERT(size >= RT_ALIGN_SIZE);
471506

472507
size = RT_ALIGN_DOWN(size, RT_ALIGN_SIZE);
473508

components/drivers/ipc/utest/Kconfig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,8 @@ config RT_UTEST_WORKQUEUE
99
bool "IPC Workqueue Test"
1010
default n
1111

12+
config RT_UTEST_RINGBUFFER
13+
bool "IPC Ringbuffer Test"
14+
default n
15+
1216
endmenu

components/drivers/ipc/utest/SConscript

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ if GetDepend(['RT_UTEST_COMPLETION']):
1111
if GetDepend(['RT_UTEST_WORKQUEUE']):
1212
src += ['workqueue_tc.c']
1313

14+
if GetDepend(['RT_UTEST_RINGBUFFER']):
15+
src += ['ringbuffer_tc.c']
16+
1417
group = DefineGroup('utestcases', src, depend = ['RT_USING_UTESTCASES'], CPPPATH = CPPPATH)
1518

1619
Return('group')

0 commit comments

Comments
 (0)