Skip to content

Commit ca92770

Browse files
author
Fei Wang
committed
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 de183df commit ca92770

File tree

1 file changed

+11
-0
lines changed

1 file changed

+11
-0
lines changed

lib/os/mpsc_pbuf.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,9 @@ const union mpsc_pbuf_generic *mpsc_pbuf_claim(struct mpsc_pbuf_buffer *buffer)
537537
{
538538
union mpsc_pbuf_generic *item;
539539
bool cont;
540+
#ifdef CONFIG_MULTITHREADING
541+
bool need_post = false;
542+
#endif
540543

541544
do {
542545
uint32_t a;
@@ -562,6 +565,9 @@ const union mpsc_pbuf_generic *mpsc_pbuf_claim(struct mpsc_pbuf_buffer *buffer)
562565
idx_inc(buffer, buffer->tmp_rd_idx, inc);
563566
rd_idx_inc(buffer, inc);
564567
cont = true;
568+
#ifdef CONFIG_MULTITHREADING
569+
need_post = true;
570+
#endif
565571
} else {
566572
item->hdr.busy = 1;
567573
buffer->tmp_rd_idx =
@@ -576,6 +582,11 @@ const union mpsc_pbuf_generic *mpsc_pbuf_claim(struct mpsc_pbuf_buffer *buffer)
576582
k_spin_unlock(&buffer->lock, key);
577583
} while (cont);
578584

585+
#ifdef CONFIG_MULTITHREADING
586+
if (need_post && item == NULL) {
587+
k_sem_give(&buffer->sem);
588+
}
589+
#endif
579590
return item;
580591
}
581592

0 commit comments

Comments
 (0)