kernel: queue, fifo: Add cancel_wait operation.

Currently, a queue/fifo getter chooses how long to wait for an
element. But there are scenarios when putter would know better,
there should be a way to expire getter's timeout to make it run
again. k_queue_cancel_wait() and k_fifo_cancel_wait() functions
do just that. They cause corresponding *_get() functions to return
with NULL value, as if timeout expired on getter's side (even
K_FOREVER).

This can be used to signal out of band conditions from putter to
getter, e.g. end of processing, error, configuration change, etc.
A specific event would be communicated to getter by other means
(e.g. using existing shared context structures).

Without this call, achieving the same effect would require e.g.
calling k_fifo_put() with a pointer to a special sentinal memory
structure - such structure would need to be allocated somewhere
and somehow, and getter would need to recognize it from a normal
data item. Having cancel_wait() functions offers an elegant
alternative. From this perspective, these calls can be seen as
an equivalent to e.g. k_fifo_put(fifo, NULL), except that such
call won't work in practice.

Change-Id: I47b7f690dc325a80943082bcf5345c41649e7024
Signed-off-by: Paul Sokolovsky <paul.sokolovsky@linaro.org>
This commit is contained in:
Paul Sokolovsky 2017-04-25 17:54:31 +03:00 committed by Anas Nashif
commit 3f50707672
5 changed files with 115 additions and 1 deletions

View file

@ -77,6 +77,31 @@ static inline int handle_poll_event(struct k_queue *queue)
#endif
}
void k_queue_cancel_wait(struct k_queue *queue)
{
struct k_thread *first_pending_thread;
unsigned int key;
key = irq_lock();
first_pending_thread = _unpend_first_thread(&queue->wait_q);
if (first_pending_thread) {
prepare_thread_to_run(first_pending_thread, NULL);
if (!_is_in_isr() && _must_switch_threads()) {
(void)_Swap(key);
return;
}
} else {
if (handle_poll_event(queue)) {
(void)_Swap(key);
return;
}
}
irq_unlock(key);
}
void k_queue_insert(struct k_queue *queue, void *prev, void *data)
{
struct k_thread *first_pending_thread;