From 74e06c239281f76e7cf46402552a3f093802ddd0 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Tue, 17 Oct 2017 11:34:21 +0300 Subject: [PATCH] queue: k_queue_get: Fix NULL return k_queue_get shall never return NULL when timeout is K_FOREVER which can happen when a higher priority thread cancel/take an item before the waiting thread. Fixes issue #4358 Signed-off-by: Luiz Augusto von Dentz --- kernel/queue.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/kernel/queue.c b/kernel/queue.c index dcf7132bafad..dd30639c7eed 100644 --- a/kernel/queue.c +++ b/kernel/queue.c @@ -205,21 +205,25 @@ static void *k_queue_poll(struct k_queue *queue, s32_t timeout) k_poll_event_init(&event, K_POLL_TYPE_FIFO_DATA_AVAILABLE, K_POLL_MODE_NOTIFY_ONLY, queue); - event.state = K_POLL_STATE_NOT_READY; + do { + event.state = K_POLL_STATE_NOT_READY; - err = k_poll(&event, 1, timeout); - if (err) { - return NULL; - } + err = k_poll(&event, 1, timeout); + if (err) { + return NULL; + } - __ASSERT_NO_MSG(event.state == K_POLL_STATE_FIFO_DATA_AVAILABLE); + __ASSERT_NO_MSG(event.state == + K_POLL_STATE_FIFO_DATA_AVAILABLE); + + /* sys_slist_* aren't threadsafe, so must be always protected by + * irq_lock. + */ + key = irq_lock(); + val = sys_slist_get(&queue->data_q); + irq_unlock(key); + } while (!val && timeout == K_FOREVER); - /* sys_slist_* aren't threadsafe, so must be always protected by - * irq_lock. - */ - key = irq_lock(); - val = sys_slist_get(&queue->data_q); - irq_unlock(key); return val; } #endif /* CONFIG_POLL */