diff --git a/lib/os/mpsc_pbuf.c b/lib/os/mpsc_pbuf.c index bdd7010b128c05..06eb5d92338c7e 100644 --- a/lib/os/mpsc_pbuf.c +++ b/lib/os/mpsc_pbuf.c @@ -373,7 +373,7 @@ union mpsc_pbuf_generic *mpsc_pbuf_alloc(struct mpsc_pbuf_buffer *buffer, add_skip_item(buffer, free_wlen); cont = true; } else if (IS_ENABLED(CONFIG_MULTITHREADING) && !K_TIMEOUT_EQ(timeout, K_NO_WAIT) && - !k_is_in_isr()) { + !k_is_in_isr() && arch_irq_unlocked(key.key)) { int err; k_spin_unlock(&buffer->lock, key); diff --git a/tests/lib/mpsc_pbuf/src/main.c b/tests/lib/mpsc_pbuf/src/main.c index 201eced47f9e76..923050b1b6d42e 100644 --- a/tests/lib/mpsc_pbuf/src/main.c +++ b/tests/lib/mpsc_pbuf/src/main.c @@ -1294,5 +1294,28 @@ ZTEST(log_buffer, test_utilization) zassert_true(packet == NULL); } +/* Make sure that `mpsc_pbuf_alloc()` works in spinlock-held context when buf is not available */ +ZTEST(log_buffer, test_alloc_in_spinlock) +{ + struct mpsc_pbuf_buffer buffer; + struct test_data_var *packet; + struct k_spinlock l = {0}; + + init(&buffer, 32, false); + + /* Allocate all available buffer */ + packet = (struct test_data_var *)mpsc_pbuf_alloc( + &buffer, 32, K_MSEC(10)); + zassert_not_null(packet); + + K_SPINLOCK(&l) { + /* Try to allocate another buf */ + packet = (struct test_data_var *)mpsc_pbuf_alloc( + &buffer, 32, K_MSEC(10)); + /* No buf is available this time */ + zassert_is_null(packet); + } +} + /*test case main entry*/ ZTEST_SUITE(log_buffer, NULL, NULL, NULL, NULL, NULL);