Skip to content

Commit 8af60c6

Browse files
Fei Wangnashif
authored andcommitted
lib: os: mpsc_pbuf: fix potential semaphore wait forever
One thread calls mpsc_pbuf_alloc to produce data, which invokes add_skip_item and steps into k_sem_take. Another thread calls mpsc_pbuf_claim to consume data. In this condition, mpsc_pbuf_claim has only small remaining space and needs to call rd_idx_inc to reserve space, but there is still no data available. The consumer should call k_sem_give to wake mpsc_pbuf_alloc again, so the producer can allocate space and continue producing data. Without this wake-up, the producer thread may wait forever in k_sem_take, leading to a deadlock situation. Signed-off-by: Fei Wang <[email protected]>
1 parent 598b904 commit 8af60c6

File tree

1 file changed

+6
-0
lines changed

1 file changed

+6
-0
lines changed

lib/os/mpsc_pbuf.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,7 @@ const union mpsc_pbuf_generic *mpsc_pbuf_claim(struct mpsc_pbuf_buffer *buffer)
537537
{
538538
union mpsc_pbuf_generic *item;
539539
bool cont;
540+
bool need_post = false;
540541

541542
do {
542543
uint32_t a;
@@ -562,6 +563,7 @@ const union mpsc_pbuf_generic *mpsc_pbuf_claim(struct mpsc_pbuf_buffer *buffer)
562563
idx_inc(buffer, buffer->tmp_rd_idx, inc);
563564
rd_idx_inc(buffer, inc);
564565
cont = true;
566+
need_post = true;
565567
} else {
566568
item->hdr.busy = 1;
567569
buffer->tmp_rd_idx =
@@ -576,6 +578,10 @@ const union mpsc_pbuf_generic *mpsc_pbuf_claim(struct mpsc_pbuf_buffer *buffer)
576578
k_spin_unlock(&buffer->lock, key);
577579
} while (cont);
578580

581+
if (IS_ENABLED(CONFIG_MULTITHREADING) && need_post && item == NULL) {
582+
k_sem_give(&buffer->sem);
583+
}
584+
579585
return item;
580586
}
581587

0 commit comments

Comments
 (0)