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 i;
unsigned int j; unsigned int j;
int ret; int ret = OK;
/* Process each descriptor in the list */ /* 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. * 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 */ case POLLFD:
if (fds[i].fd >= 0)
ret = poll_fdsetup(fds[i].fd, &fds[i], true);
if (ret < 0)
{ {
/* Setup failed for fds[i]. We now need to teardown previously ret = poll_fdsetup(fds[i].fd, &fds[i], true);
* 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;
} }
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) int ret)
{ {
unsigned int i; unsigned int i;
int status; int status = OK;
/* Process each descriptor in the list */ /* Process each descriptor in the list */
*count = 0; *count = 0;
for (i = 0; i < nfds; i++) for (i = 0; i < nfds; i++)
{ {
/* Ignore negative descriptors */ switch (fds[i].events & POLLMASK)
if (fds[i].fd >= 0)
{ {
/* Teardown the poll */ case POLLFD:
if (fds[i].fd >= 0)
status = poll_fdsetup(fds[i].fd, &fds[i], false);
if (status < 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 */ /* 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 * Name: file_poll
* *
* Description: * 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 * support detached file, and also (2) by fdesc_poll() to perform all
* normal operations on file descriptors descriptors. * normal operations on file descriptors descriptors.
* *

View File

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