fs/vfs/fs_poll.c: Add poll use in kernel space.

This commit is contained in:
dongjianli 2018-08-26 13:44:07 -06:00 committed by Gregory Nutt
parent 3f50451046
commit 56883eef3b
2 changed files with 115 additions and 37 deletions

View File

@ -136,7 +136,7 @@ static inline int poll_setup(FAR struct pollfd *fds, nfds_t nfds, sem_t *sem)
{
unsigned int i;
unsigned int j;
int ret;
int ret = OK;
/* Process each descriptor in the list */
@ -157,29 +157,71 @@ static inline int poll_setup(FAR struct pollfd *fds, nfds_t nfds, sem_t *sem)
* spec, that appears to be the correct behavior.
*/
if (fds[i].fd >= 0)
switch (fds[i].events & POLLMASK)
{
/* Set up the poll on this valid file descriptor */
ret = poll_fdsetup(fds[i].fd, &fds[i], true);
if (ret < 0)
case POLLFD:
if (fds[i].fd >= 0)
{
/* Setup failed for fds[i]. We now need to teardown previously
* setup fds[0 .. (i - 1)] to release allocated resources and
* to prevent memory corruption by access to freed/released 'fds'
* and 'sem'.
*/
for (j = 0; j < i; j++)
{
(void)poll_fdsetup(fds[j].fd, &fds[j], false);
}
/* Indicate an error on the file descriptor */
fds[i].revents |= POLLERR;
return ret;
ret = poll_fdsetup(fds[i].fd, &fds[i], true);
}
break;
case POLLFILE:
if (fds[i].ptr != NULL)
{
ret = file_poll(fds[i].ptr, &fds[i], true);
}
break;
#ifdef CONFIG_NET
case POLLSOCK:
if (fds[i].ptr != NULL)
{
ret = psock_poll(fds[i].ptr, &fds[i], true);
}
break;
#endif
default:
ret = -EINVAL;
break;
}
if (ret < 0)
{
/* Setup failed for fds[i]. We now need to teardown previously
* setup fds[0 .. (i - 1)] to release allocated resources and
* to prevent memory corruption by access to freed/released 'fds'
* and 'sem'.
*/
for (j = 0; j < i; j++)
{
switch (fds[j].events & POLLMASK)
{
case POLLFD:
(void)poll_fdsetup(fds[j].fd, &fds[j], false);
break;
case POLLFILE:
(void)file_poll(fds[j].ptr, &fds[j], false);
break;
#ifdef CONFIG_NET
case POLLSOCK:
(void)psock_poll(fds[j].ptr, &fds[j], false);
break;
#endif
default:
break;
}
}
/* Indicate an error on the file descriptor */
fds[i].revents |= POLLERR;
return ret;
}
}
@ -201,24 +243,46 @@ static inline int poll_teardown(FAR struct pollfd *fds, nfds_t nfds, int *count,
int ret)
{
unsigned int i;
int status;
int status = OK;
/* Process each descriptor in the list */
*count = 0;
for (i = 0; i < nfds; i++)
{
/* Ignore negative descriptors */
if (fds[i].fd >= 0)
switch (fds[i].events & POLLMASK)
{
/* Teardown the poll */
status = poll_fdsetup(fds[i].fd, &fds[i], false);
if (status < 0)
case POLLFD:
if (fds[i].fd >= 0)
{
ret = status;
status = poll_fdsetup(fds[i].fd, &fds[i], false);
}
break;
case POLLFILE:
if (fds[i].ptr != NULL)
{
status = file_poll(fds[i].ptr, &fds[i], false);
}
break;
#ifdef CONFIG_NET
case POLLSOCK:
if (fds[i].ptr != NULL)
{
status = psock_poll(fds[i].ptr, &fds[i], false);
}
break;
#endif
default:
status = -EINVAL;
break;
}
if (status < 0)
{
ret = status;
}
/* Check if any events were posted */
@ -245,7 +309,7 @@ static inline int poll_teardown(FAR struct pollfd *fds, nfds_t nfds, int *count,
* Name: file_poll
*
* Description:
* Low-level poll operation based on struc file. This is used both to (1)
* Low-level poll operation based on struct file. This is used both to (1)
* support detached file, and also (2) by fdesc_poll() to perform all
* normal operations on file descriptors descriptors.
*

View File

@ -1,7 +1,7 @@
/****************************************************************************
* include/poll.h
*
* Copyright (C) 2008-2009 Gregory Nutt. All rights reserved.
* Copyright (C) 2008-2009, 2018 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -88,6 +88,11 @@
#define POLLHUP (0x08)
#define POLLNVAL (0x10)
#define POLLFD (0x00)
#define POLLFILE (0x40)
#define POLLSOCK (0x80)
#define POLLMASK (0xC0)
/****************************************************************************
* Public Type Definitions
****************************************************************************/
@ -107,11 +112,20 @@ typedef uint8_t pollevent_t;
struct pollfd
{
int fd; /* The descriptor being polled */
sem_t *sem; /* Pointer to semaphore used to post output event */
pollevent_t events; /* The input event flags */
pollevent_t revents; /* The output event flags */
FAR void *priv; /* For use by drivers */
/* REVISIT: Un-named unions are forbidden by the coding standard because
* they are not available in C89.
*/
union
{
int fd; /* The descriptor being polled */
FAR void *ptr; /* The psock or file being polled */
};
FAR sem_t *sem; /* Pointer to semaphore used to post output event */
pollevent_t events; /* The input event flags */
pollevent_t revents; /* The output event flags */
FAR void *priv; /* For use by drivers */
};
/****************************************************************************