Browse Source

kernel: k_poll: Introduce separate status for cancelled events

Previously (as introduced in 48fadfe62), if k_poll() waited on a
queue (or subclass like fifo), and wait was cancelled on queue's
side using k_queue_cancel_wait(), k_poll returned -EINTR. But it
did not set event->state field (to anything else but
K_POLL_STATE_NOT_READY), so in case of waiting on multiple queues,
it was not possible to differentiate which of them was cancelled.

This in particular broke detection of network socket EOF conditions
in POSIX poll() implementation.

This situation is now resolved with introduction of explicit
K_POLL_STATE_CANCELLED state, which is now set for cancelled queue
(-EINTR return remains the same).

This change also elaborates docstring for the functions mentioned, to
document this behavior.

Fixes: #9032

Signed-off-by: Paul Sokolovsky <paul.sokolovsky@linaro.org>
pull/9733/head
Paul Sokolovsky 7 years ago committed by Anas Nashif
parent
commit
45c0b20470
  1. 13
      include/kernel.h
  2. 2
      kernel/poll.c
  3. 2
      kernel/queue.c

13
include/kernel.h

@ -1815,6 +1815,9 @@ __syscall void k_queue_init(struct k_queue *queue); @@ -1815,6 +1815,9 @@ __syscall void k_queue_init(struct k_queue *queue);
*
* This routine causes first thread pending on @a queue, if any, to
* return from k_queue_get() call with NULL value (as if timeout expired).
* If the queue is being waited on by k_poll(), it will return with
* -EINTR and K_POLL_STATE_CANCELLED state (and per above, subsequent
* k_queue_get() will return NULL).
*
* @note Can be called by ISRs.
*
@ -4242,6 +4245,9 @@ enum _poll_states_bits { @@ -4242,6 +4245,9 @@ enum _poll_states_bits {
/* data is available to read on queue/fifo/lifo */
_POLL_STATE_DATA_AVAILABLE,
/* queue/fifo/lifo wait was cancelled */
_POLL_STATE_CANCELLED,
_POLL_NUM_STATES
};
@ -4287,6 +4293,7 @@ enum k_poll_modes { @@ -4287,6 +4293,7 @@ enum k_poll_modes {
#define K_POLL_STATE_SEM_AVAILABLE _POLL_STATE_BIT(_POLL_STATE_SEM_AVAILABLE)
#define K_POLL_STATE_DATA_AVAILABLE _POLL_STATE_BIT(_POLL_STATE_DATA_AVAILABLE)
#define K_POLL_STATE_FIFO_DATA_AVAILABLE K_POLL_STATE_DATA_AVAILABLE
#define K_POLL_STATE_CANCELLED _POLL_STATE_BIT(_POLL_STATE_CANCELLED)
/* public - poll signal object */
struct k_poll_signal {
@ -4418,7 +4425,11 @@ extern void k_poll_event_init(struct k_poll_event *event, u32_t type, @@ -4418,7 +4425,11 @@ extern void k_poll_event_init(struct k_poll_event *event, u32_t type,
*
* @retval 0 One or more events are ready.
* @retval -EAGAIN Waiting period timed out.
* @retval -EINTR Poller thread has been interrupted.
* @retval -EINTR Polling has been interrupted, e.g. with
* k_queue_cancel_wait(). All output events are still set and valid,
* cancelled event(s) will be set to K_POLL_STATE_CANCELLED. In other
* words, -EINTR status means that at least one of output events is
* K_POLL_STATE_CANCELLED.
* @retval -ENOMEM Thread resource pool insufficient memory (user mode only)
* @retval -EINVAL Bad parameters (user mode only)
* @req K-POLL-001

2
kernel/poll.c

@ -337,7 +337,7 @@ static int signal_poll_event(struct k_poll_event *event, u32_t state) @@ -337,7 +337,7 @@ static int signal_poll_event(struct k_poll_event *event, u32_t state)
_unpend_thread(thread);
_set_thread_return_value(thread,
state == K_POLL_STATE_NOT_READY ? -EINTR : 0);
state == K_POLL_STATE_CANCELLED ? -EINTR : 0);
if (!_is_thread_ready(thread)) {
goto ready_event;

2
kernel/queue.c

@ -131,7 +131,7 @@ void _impl_k_queue_cancel_wait(struct k_queue *queue) @@ -131,7 +131,7 @@ void _impl_k_queue_cancel_wait(struct k_queue *queue)
prepare_thread_to_run(first_pending_thread, NULL);
}
#else
handle_poll_events(queue, K_POLL_STATE_NOT_READY);
handle_poll_events(queue, K_POLL_STATE_CANCELLED);
#endif /* !CONFIG_POLL */
_reschedule(key);

Loading…
Cancel
Save