Fix unecessary delays and timing jitter in the implementation of poll(): No delay if timeout is zero; If timeout is greater than zero, first check if events are already pending events before starting the delay. From Johannes Hampel

This commit is contained in:
Gregory Nutt 2014-09-25 06:30:25 -06:00
parent add4753c08
commit c4978f7ef0

View File

@ -191,6 +191,39 @@ static inline int poll_setup(FAR struct pollfd *fds, nfds_t nfds, sem_t *sem)
} }
#endif #endif
/****************************************************************************
* Name: poll_peek
*
* Description:
* Peek into each file descriptor whether poll events are already available.
*
* Return values:
* TRUE : Poll events available.
* FALSE: No poll events available.
*
****************************************************************************/
#if CONFIG_NFILE_DESCRIPTORS > 0
static inline int poll_peek(FAR struct pollfd *fds, nfds_t nfds)
{
int i = 0;
/* Process each descriptor in the list */
for (i = 0; i < nfds; i++)
{
/* Peek if any events are currently posted */
if (fds[i].revents != 0)
{
return TRUE;
}
}
return FALSE;
}
#endif
/**************************************************************************** /****************************************************************************
* Name: poll_teardown * Name: poll_teardown
* *
@ -278,7 +311,7 @@ static void poll_timeout(int argc, uint32_t isem, ...)
* timeout. * timeout.
* *
* Return: * Return:
* On success, the number of structures that have nonzero revents fields. * On success, the number of structures that have non-zero revents fields.
* A value of 0 indicates that the call timed out and no file descriptors * A value of 0 indicates that the call timed out and no file descriptors
* were ready. On error, -1 is returned, and errno is set appropriately: * were ready. On error, -1 is returned, and errno is set appropriately:
* *
@ -303,21 +336,38 @@ int poll(FAR struct pollfd *fds, nfds_t nfds, int timeout)
ret = poll_setup(fds, nfds, &sem); ret = poll_setup(fds, nfds, &sem);
if (ret >= 0) if (ret >= 0)
{ {
if (timeout >= 0) if (timeout == 0)
{ {
/* Wait for the poll event with a timeout. Note that the /* Poll returns immediately whether we have a poll event or not.
* millisecond timeout has to be converted to system clock *
* ticks for wd_start * ATTENTION: This branch is explicitly necessary to avoid the
* blocking behavior of the watchdog implementation which results
* in an event jittering until the current time-slice has been
* finished because watchdog events are only evaluated during the
* execution of the Timer-ISR (SysTick/Time-Slice = 10ms -->
* Jitter up to 10ms).
*/
}
else if (timeout > 0)
{
/* Either wait for poll event(s) with specified timeout if no
* events are currently available or return immediately. Note
* that the millisecond timeout has to be converted to system
* clock ticks for wd_start
*/ */
wdog = wd_create(); if (poll_peek(fds, nfds) == FALSE)
wd_start(wdog, MSEC2TICK(timeout), poll_timeout, 1, (uint32_t)&sem); {
poll_semtake(&sem); wdog = wd_create();
wd_delete(wdog); wd_start(wdog, MSEC2TICK(timeout), poll_timeout, 1,
(uint32_t)&sem);
poll_semtake(&sem);
wd_delete(wdog);
}
} }
else else
{ {
/* Wait for the poll event with no timeout */ /* Wait for the poll event with no timeout (blocking indefinitely) */
poll_semtake(&sem); poll_semtake(&sem);
} }