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:
parent
add4753c08
commit
c4978f7ef0
70
fs/fs_poll.c
70
fs/fs_poll.c
@ -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);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user