diff --git a/fs/vfs/fs_poll.c b/fs/vfs/fs_poll.c index eb8d3ec9b38..7494b751cfa 100644 --- a/fs/vfs/fs_poll.c +++ b/fs/vfs/fs_poll.c @@ -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. * diff --git a/include/poll.h b/include/poll.h index 859163af395..fb6269e20c2 100644 --- a/include/poll.h +++ b/include/poll.h @@ -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 * * 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 */ }; /****************************************************************************