From eeb84bc3e196548c3c09bd049a648a19e2836f1d Mon Sep 17 00:00:00 2001 From: patacongo Date: Sun, 16 Nov 2008 18:48:29 +0000 Subject: Add infrastructure to support poll() git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@1258 42af7a65-404d-4744-a932-0658087f49c3 --- nuttx/ChangeLog | 1 + nuttx/Documentation/NuttX.html | 1 + nuttx/drivers/bch/bchdev_driver.c | 3 +- nuttx/drivers/can.c | 5 +- nuttx/drivers/dev_null.c | 3 +- nuttx/drivers/dev_zero.c | 3 +- nuttx/drivers/fifo.c | 3 +- nuttx/drivers/lowconsole.c | 3 +- nuttx/drivers/pipe.c | 3 +- nuttx/drivers/serial.c | 3 +- nuttx/examples/pashello/device.c | 3 +- nuttx/fs/fs_poll.c | 228 +++++++++++++++++++++++++++++++++++++- nuttx/include/nuttx/fs.h | 3 + nuttx/include/nuttx/net.h | 8 ++ nuttx/net/Makefile | 2 +- nuttx/net/net-poll.c | 80 +++++++++++++ 16 files changed, 336 insertions(+), 16 deletions(-) create mode 100644 nuttx/net/net-poll.c (limited to 'nuttx') diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index 250d6b7d1..53ea69079 100644 --- a/nuttx/ChangeLog +++ b/nuttx/ChangeLog @@ -564,3 +564,4 @@ types. 0.3.19 2008-xx-xx Gregory Nutt + * Add the basic infrastructure for support the poll() API diff --git a/nuttx/Documentation/NuttX.html b/nuttx/Documentation/NuttX.html index 79420fa15..98920305b 100644 --- a/nuttx/Documentation/NuttX.html +++ b/nuttx/Documentation/NuttX.html @@ -1200,6 +1200,7 @@ buildroot-0.1.2 2007-11-06 <spudmonkey@racsa.co.cr>
    nuttx-0.3.19 2008-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr> + * Add the basic infrastructure for support the poll() API pascal-0.1.3 2008-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr> diff --git a/nuttx/drivers/bch/bchdev_driver.c b/nuttx/drivers/bch/bchdev_driver.c index 9f579bbab..98c7f2991 100644 --- a/nuttx/drivers/bch/bchdev_driver.c +++ b/nuttx/drivers/bch/bchdev_driver.c @@ -85,7 +85,8 @@ struct file_operations bch_fops = bch_read, /* read */ bch_write, /* write */ 0, /* seek */ - bch_ioctl /* ioctl */ + bch_ioctl, /* ioctl */ + 0 /* poll */ }; /**************************************************************************** diff --git a/nuttx/drivers/can.c b/nuttx/drivers/can.c index e68bfd94d..72e3fdd64 100644 --- a/nuttx/drivers/can.c +++ b/nuttx/drivers/can.c @@ -87,8 +87,9 @@ struct file_operations g_canops = can_close, /* close */ can_read, /* read */ can_write, /* write */ - 0, /* seek */ - can_ioctl /* ioctl */ + 0, /* seek */ + can_ioctl, /* ioctl */ + 0 /* poll */ }; /**************************************************************************** diff --git a/nuttx/drivers/dev_null.c b/nuttx/drivers/dev_null.c index 5c495451b..f097f76c9 100644 --- a/nuttx/drivers/dev_null.c +++ b/nuttx/drivers/dev_null.c @@ -66,7 +66,8 @@ static struct file_operations devnull_fops = devnull_read, /* read */ devnull_write, /* write */ 0, /* seek */ - 0 /* ioctl */ + 0, /* ioctl */ + 0 /* poll */ }; /**************************************************************************** diff --git a/nuttx/drivers/dev_zero.c b/nuttx/drivers/dev_zero.c index a18509415..876734770 100644 --- a/nuttx/drivers/dev_zero.c +++ b/nuttx/drivers/dev_zero.c @@ -66,7 +66,8 @@ static struct file_operations devzero_fops = devzero_read, /* read */ devzero_write, /* write */ 0, /* seek */ - 0 /* ioctl */ + 0, /* ioctl */ + 0 /* poll */ }; /**************************************************************************** diff --git a/nuttx/drivers/fifo.c b/nuttx/drivers/fifo.c index 2465d41dc..fb17e3461 100644 --- a/nuttx/drivers/fifo.c +++ b/nuttx/drivers/fifo.c @@ -74,7 +74,8 @@ static struct file_operations fifo_fops = pipecommon_read, /* read */ pipecommon_write, /* write */ 0, /* seek */ - 0 /* ioctl */ + 0, /* ioctl */ + 0 /* poll */ }; /**************************************************************************** diff --git a/nuttx/drivers/lowconsole.c b/nuttx/drivers/lowconsole.c index 0dcfe72b3..8b776da19 100755 --- a/nuttx/drivers/lowconsole.c +++ b/nuttx/drivers/lowconsole.c @@ -75,7 +75,8 @@ struct file_operations g_serialops = lowconsole_read, /* read */ lowconsole_write, /* write */ 0, /* seek */ - lowconsole_ioctl /* ioctl */ + lowconsole_ioctl, /* ioctl */ + 0 /* poll */ }; /**************************************************************************** diff --git a/nuttx/drivers/pipe.c b/nuttx/drivers/pipe.c index 677bcfe4c..7e4581c8a 100644 --- a/nuttx/drivers/pipe.c +++ b/nuttx/drivers/pipe.c @@ -82,7 +82,8 @@ static struct file_operations pipe_fops = pipecommon_read, /* read */ pipecommon_write, /* write */ 0, /* seek */ - 0 /* ioctl */ + 0, /* ioctl */ + 0, /* pipe */ }; static sem_t g_pipesem = { 1 }; diff --git a/nuttx/drivers/serial.c b/nuttx/drivers/serial.c index bd4ca33e7..366c7a208 100644 --- a/nuttx/drivers/serial.c +++ b/nuttx/drivers/serial.c @@ -89,7 +89,8 @@ struct file_operations g_serialops = uart_read, /* read */ uart_write, /* write */ 0, /* seek */ - uart_ioctl /* ioctl */ + uart_ioctl, /* ioctl */ + 0 /* poll */ }; /************************************************************************************ diff --git a/nuttx/examples/pashello/device.c b/nuttx/examples/pashello/device.c index b6db1db5c..fb2deff65 100644 --- a/nuttx/examples/pashello/device.c +++ b/nuttx/examples/pashello/device.c @@ -68,7 +68,8 @@ static struct file_operations hello_fops = hello_read, /* read */ 0, /* write */ 0, /* seek */ - 0 /* ioctl */ + 0, /* ioctl */ + 0 /* poll */ }; /**************************************************************************** diff --git a/nuttx/fs/fs_poll.c b/nuttx/fs/fs_poll.c index 7b1db1f41..2f585d818 100644 --- a/nuttx/fs/fs_poll.c +++ b/nuttx/fs/fs_poll.c @@ -41,15 +41,199 @@ #include #include +#include #include +#include +#include #include +#include + #include "fs_internal.h" +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define poll_semgive(sem) sem_post(sem) + /**************************************************************************** * Private Functions ****************************************************************************/ +/**************************************************************************** + * Name: poll_semtake + ****************************************************************************/ + +static void poll_semtake(FAR sem_t *sem) +{ + /* Take the semaphore (perhaps waiting) */ + + while (sem_wait(sem) != 0) + { + /* The only case that an error should occur here is if + * the wait was awakened by a signal. + */ + + ASSERT(errno == EINTR); + } +} + +/**************************************************************************** + * Name: poll_fdsetup + * + * Description: + * Configure (or unconfigure) one file/socket descriptor for the poll + * operation. If fds and sem are non-null, then the poll is being setup. + * if fds and sem are NULL, then the poll is being torn down. + * + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 +static int poll_fdsetup(int fd, FAR struct pollfd *fds) +{ + FAR struct filelist *list; + FAR struct file *this_file; + FAR struct inode *inode; + int ret = -ENOSYS; + + /* Check for a valid file descriptor */ + + if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS) + { + /* Perform the socket ioctl */ + +#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0 + if ((unsigned int)fd < (CONFIG_NFILE_DESCRIPTORS+CONFIG_NSOCKET_DESCRIPTORS)) + { + return net_poll(fds->fd, fds); + } + else +#endif + { + return -EBADF; + } + } + + /* Get the thread-specific file list */ + + list = sched_getfiles(); + if (!list) + { + return -EMFILE; + } + + /* Is a driver registered? Does it support the poll method? + * If not, return -ENOSYS + */ + + this_file = &list->fl_files[fd]; + inode = this_file->f_inode; + + if (inode && inode->u.i_ops && inode->u.i_ops->poll) + { + /* Yes, then setup the poll */ + + ret = (int)inode->u.i_ops->poll(this_file, fds); + } + return ret; +} +#endif + +/**************************************************************************** + * Name: poll_setup + * + * Description: + * Setup the poll operation for each descriptor in the list. + * + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 +static inline int poll_setup(FAR struct pollfd *fds, nfds_t nfds, sem_t *sem) +{ + int ret; + int i; + + /* Process each descriptor in the list */ + + for (i = 0; i < nfds; i++) + { + /* Setup the poll descriptor */ + + fds->sem = sem; + fds->revents = 0; + + /* Set up the poll */ + + ret = poll_fdsetup(fds->fd, fds); + if (ret < 0) + { + return ret; + } + } + return OK; +} +#endif + +/**************************************************************************** + * Name: poll_teardown + * + * Description: + * Teardown the poll operation for each descriptor in the list and return + * the count of non-zero poll events. + * + ****************************************************************************/ + +#if CONFIG_NFILE_DESCRIPTORS > 0 +static inline int poll_teardown(FAR struct pollfd *fds, nfds_t nfds, int *count) +{ + int status; + int ret = OK; + int i; + + /* Process each descriptor in the list */ + + for (i = 0; i < nfds; i++) + { + /* Teardown the poll */ + + status = poll_fdsetup(fds->fd, NULL); + if (status < 0) + { + ret = status; + } + + /* Check if any events were posted */ + + if (fds->revents != 0) + { + (*count)++; + } + + /* Un-initialize the poll structure */ + + fds->sem = NULL; + } + return ret; +} +#endif + +/**************************************************************************** + * Name: poll_timeout + * + * Description: + * The wdog expired before any other events were received. + * + ****************************************************************************/ + +static void poll_timeout(int argc, uint32 isem) +{ + /* Wake up the poller */ + + FAR sem_t *sem = (FAR sem_t *)isem; + poll_semgive(sem); +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -87,11 +271,45 @@ int poll(FAR struct pollfd *fds, nfds_t nfds, int timeout) { -#ifdef CONFIG_CPP_HAVE_WARNING -# warning To be provided -#endif + WDOG_ID wdog; + sem_t sem; + int count; + int ret; + + sem_init(&sem, 0, 0); + ret = poll_setup(fds, nfds, &sem); + if (ret >= 0) + { + if (timeout >= 0) + { + /* Wait for the poll event with a timeout */ + + wdog = wd_create(); + wd_start(wdog, poll_timeout, 1, (uint32)&sem); + poll_semtake(&sem); + wd_delete(wdog); + } + else + { + /* Wait for the poll event with not timeout */ + + poll_semtake(&sem); + } + + /* Teardown the the poll operation and get the count of events */ + + ret = poll_teardown(fds, nfds, &count); + } + sem_destroy(&sem); + + /* Check for errors */ + + if (ret < 0) + { + errno = -ret; + return ERROR; + } - errno = ENOSYS; - return ERROR; + return count; } diff --git a/nuttx/include/nuttx/fs.h b/nuttx/include/nuttx/fs.h index 946c60589..65e033208 100644 --- a/nuttx/include/nuttx/fs.h +++ b/nuttx/include/nuttx/fs.h @@ -57,6 +57,8 @@ */ struct file; +struct pollfd; + struct file_operations { /* The device driver open method differs from the mountpoint open method */ @@ -73,6 +75,7 @@ struct file_operations ssize_t (*write)(FAR struct file *filp, FAR const char *buffer, size_t buflen); off_t (*seek)(FAR struct file *filp, off_t offset, int whence); int (*ioctl)(FAR struct file *filp, int cmd, unsigned long arg); + int (*poll)(FAR struct file *filp, struct pollfd *poll); /* The two structures need not be common after this point */ }; diff --git a/nuttx/include/nuttx/net.h b/nuttx/include/nuttx/net.h index d4d7ec754..5126e7b65 100644 --- a/nuttx/include/nuttx/net.h +++ b/nuttx/include/nuttx/net.h @@ -153,6 +153,14 @@ EXTERN int net_close(int sockfd); struct ifreq; /* Forward reference -- see net/ioctls.h */ EXTERN int netdev_ioctl(int sockfd, int cmd, struct ifreq *req); +/* net-poll.c ****************************************************************/ +/* The standard poll() operation redirects operations on socket descriptors + * to this function. + */ + +struct pollfd; /* Forward reference -- see poll.h */ +EXTERN int net_poll(int sockfd, struct pollfd *fds); + /* netdev-register.c *********************************************************/ /* This function is called by network interface device drivers to inform the * socket layer of their existence. This registration is necesary to support diff --git a/nuttx/net/Makefile b/nuttx/net/Makefile index b43943396..97c758dd7 100644 --- a/nuttx/net/Makefile +++ b/nuttx/net/Makefile @@ -52,7 +52,7 @@ endif endif NETDEV_ASRCS = -NETDEV_CSRCS = netdev-register.c netdev-ioctl.c netdev-txnotify.c \ +NETDEV_CSRCS = netdev-register.c netdev-ioctl.c net-poll.c netdev-txnotify.c \ netdev-findbyname.c netdev-findbyaddr.c netdev-count.c \ netdev-foreach.c diff --git a/nuttx/net/net-poll.c b/nuttx/net/net-poll.c new file mode 100644 index 000000000..ef4ba9dd3 --- /dev/null +++ b/nuttx/net/net-poll.c @@ -0,0 +1,80 @@ +/**************************************************************************** + * net/net-poll.c + * + * Copyright (C) 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#ifdef CONFIG_NET + +#include +#include +#include +#include + +#include +#include "net-internal.h" + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: net_poll + * + * Description: + * The standard poll() operation redirects operations on socket descriptors + * to this function. + * + * Parameters: + * fd - The socket descriptor of interest + * fds - The structures describing events to be monitored, OR NULL if + * this is a request to stop monitoring events. + * + * Returned Value: + * TBD + * + ****************************************************************************/ + +int net_poll(int sockfd, struct pollfd *fds) +{ +#ifdef CONFIG_CPP_HAVE_WARNING +# warning To be provided +#endif + return -ENOSYS; +} + +#endif /* CONFIG_NET */ -- cgit v1.2.3