Re-implemented poll() using sem_timedwait()
This commit is contained in:
parent
365d604463
commit
c652092ac4
94
fs/fs_poll.c
94
fs/fs_poll.c
@ -46,11 +46,12 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
#include <nuttx/wdog.h>
|
|
||||||
#include <nuttx/sched.h>
|
#include <nuttx/sched.h>
|
||||||
#include <nuttx/clock.h>
|
#include <nuttx/clock.h>
|
||||||
#include <nuttx/fs/fs.h>
|
#include <nuttx/fs/fs.h>
|
||||||
|
|
||||||
|
#include <arch/irq.h>
|
||||||
|
|
||||||
#include "fs_internal.h"
|
#include "fs_internal.h"
|
||||||
|
|
||||||
#ifndef CONFIG_DISABLE_POLL
|
#ifndef CONFIG_DISABLE_POLL
|
||||||
@ -191,39 +192,6 @@ 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
|
||||||
*
|
*
|
||||||
@ -327,7 +295,8 @@ static void poll_timeout(int argc, uint32_t isem, ...)
|
|||||||
|
|
||||||
int poll(FAR struct pollfd *fds, nfds_t nfds, int timeout)
|
int poll(FAR struct pollfd *fds, nfds_t nfds, int timeout)
|
||||||
{
|
{
|
||||||
WDOG_ID wdog;
|
struct timespec abstime;
|
||||||
|
irqstate_t flags;
|
||||||
sem_t sem;
|
sem_t sem;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
int ret;
|
int ret;
|
||||||
@ -338,36 +307,47 @@ int poll(FAR struct pollfd *fds, nfds_t nfds, int timeout)
|
|||||||
{
|
{
|
||||||
if (timeout == 0)
|
if (timeout == 0)
|
||||||
{
|
{
|
||||||
/* Poll returns immediately whether we have a poll event or not.
|
/* Poll returns immediately whether we have a poll event or not. */
|
||||||
*
|
|
||||||
* ATTENTION: This branch is explicitly necessary to avoid the
|
ret = sem_trywait(&sem);
|
||||||
* 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)
|
else if (timeout > 0)
|
||||||
{
|
{
|
||||||
/* Either wait for poll event(s) with specified timeout if no
|
time_t sec;
|
||||||
* events are currently available or return immediately. Note
|
uint32-_t nsec;
|
||||||
* that the millisecond timeout has to be converted to system
|
|
||||||
* clock ticks for wd_start
|
/* Either wait for either a poll event(s) to occur or for the
|
||||||
|
* specified timeout to elapse with no event.
|
||||||
|
*
|
||||||
|
* NOTE: If a poll event is pending (i.e., the semaphore has already
|
||||||
|
* been incremented), sem_timedwait() will not wait, but will return
|
||||||
|
* immediately.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (poll_peek(fds, nfds) == FALSE)
|
sec = timeout / MSEC_PER_SEC;
|
||||||
{
|
nsec = (timout - MSEC_PER_SEC * sec) * NSEC_PER_MSEC;
|
||||||
wdog = wd_create();
|
|
||||||
wd_start(wdog, MSEC2TICK(timeout), poll_timeout, 1,
|
/* Make sure that the following are atomic by disabling interrupts.
|
||||||
(uint32_t)&sem);
|
* Interrupts will be re-enabled while we are waiting.
|
||||||
poll_semtake(&sem);
|
*/
|
||||||
wd_delete(wdog);
|
|
||||||
}
|
flags = irqsave();
|
||||||
|
(void)clock_gettime(CLOCK_REALTIME, &abstime);
|
||||||
|
|
||||||
|
abstime.tv_sec += sec;
|
||||||
|
abstime.tv_nsec += nsec;
|
||||||
|
if (abstime.tv_nsec > NSEC_PER_SEC)
|
||||||
|
{
|
||||||
|
abstime.tv_sec++;
|
||||||
|
abstime.tv_nsec -= NSEC_PER_SEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = sem_timedwai&sem, &abstime);
|
||||||
|
irqrestore(flags);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Wait for the poll event with no timeout (blocking indefinitely) */
|
/* Wait for the poll event with no timeout */
|
||||||
|
|
||||||
poll_semtake(&sem);
|
poll_semtake(&sem);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user