diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2008-11-17 20:24:28 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2008-11-17 20:24:28 +0000 |
commit | cff1141190d60f819078be1ad0ed0186b47fd637 (patch) | |
tree | 487fc2ad11a4e20eb21f1ad746ed16d88541c05e /nuttx/drivers/pipe_common.c | |
parent | 33f0979adc4165594164fb13611961d60f0f2cfc (diff) | |
download | px4-nuttx-cff1141190d60f819078be1ad0ed0186b47fd637.tar.gz px4-nuttx-cff1141190d60f819078be1ad0ed0186b47fd637.tar.bz2 px4-nuttx-cff1141190d60f819078be1ad0ed0186b47fd637.zip |
Add poll() method
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@1262 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/drivers/pipe_common.c')
-rw-r--r-- | nuttx/drivers/pipe_common.c | 137 |
1 files changed, 136 insertions, 1 deletions
diff --git a/nuttx/drivers/pipe_common.c b/nuttx/drivers/pipe_common.c index 59b9f79c8..f00705f70 100644 --- a/nuttx/drivers/pipe_common.c +++ b/nuttx/drivers/pipe_common.c @@ -52,6 +52,8 @@ #include <fcntl.h> #include <errno.h> #include <assert.h> +#include <debug.h> + #include <nuttx/fs.h> #include "pipe_common.h" @@ -97,6 +99,33 @@ static void pipecommon_semtake(sem_t *sem) } /**************************************************************************** + * Name: pipecommon_pollnotify + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_POLL +static void pipecommon_pollnotify(FAR struct pipe_dev_s *dev, pollevent_t eventset) +{ + int i; + + for (i = 0; i < CONFIG_DEV_PIPE_NPOLLWAITERS; i++) + { + struct pollfd *fds = dev->d_fds[i]; + if (fds) + { + fds->revents |= (fds->events & eventset); + if (fds->revents != 0) + { + fvdbg("Report events: %02x\n", fds->revents); + sem_post(fds->sem); + } + } + } +} +#else +# define pipecommon_pollnotify(dev,event) +#endif + +/**************************************************************************** * Public Functions ****************************************************************************/ @@ -168,6 +197,10 @@ int pipecommon_open(FAR struct file *filep) } } + /* There is no, file-specific private data (at least not yet) */ + + filep->f_priv = NULL; + /* Increment the reference count on the pipe instance */ dev->d_refs++; @@ -335,6 +368,7 @@ ssize_t pipecommon_read(FAR struct file *filep, FAR char *buffer, size_t len) sem_post(&dev->d_bfsem); ret = sem_wait(&dev->d_rdsem); sched_unlock(); + if (ret < 0 || sem_wait(&dev->d_bfsem) < 0) { return ERROR; @@ -361,8 +395,12 @@ ssize_t pipecommon_read(FAR struct file *filep, FAR char *buffer, size_t len) sem_post(&dev->d_wrsem); } + /* Notify all poll/select waiters that they can write to the FIFO */ + + pipecommon_pollnotify(dev, POLLOUT); + sem_post(&dev->d_bfsem); - return nread; + return nread; } /**************************************************************************** @@ -426,6 +464,10 @@ ssize_t pipecommon_write(FAR struct file *filep, FAR const char *buffer, size_t sem_post(&dev->d_rdsem); } + /* Notify all poll/select waiters that they can write to the FIFO */ + + pipecommon_pollnotify(dev, POLLIN); + /* Return the number of bytes written */ sem_post(&dev->d_bfsem); @@ -470,4 +512,97 @@ ssize_t pipecommon_write(FAR struct file *filep, FAR const char *buffer, size_t } } +/**************************************************************************** + * Name: pipecommon_poll + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_POLL +int pipecommon_poll(FAR struct file *filep, FAR struct pollfd *fds) +{ + struct inode *inode = filep->f_inode; + struct pipe_dev_s *dev = inode->i_private; + pollevent_t eventset; + pipe_ndx_t nbytes; + int i; + + /* Some sanity checking */ +#if CONFIG_DEBUG + if (!dev) + { + return -ENODEV; + } +#endif + + /* Find an available slot for the poll structure reference */ + + pipecommon_semtake(&dev->d_bfsem); + for (i = 0; i < CONFIG_DEV_PIPE_NPOLLWAITERS; i++) + { + /* Find the slot with the value equal to filep->f_priv. If there + * is not previously installed poll structure, then f_priv will + * be NULL and we will find the first unused slot. If f_priv is + * is non-NULL, then we will find the slot that was used for the + * previous setup. + */ + + if (dev->d_fds[i] == filep->f_priv) + { + dev->d_fds[i] = fds; + break; + } + } + + if (i >= CONFIG_DEV_PIPE_NPOLLWAITERS) + { + DEBUGASSERT(fds == NULL); + return -EBUSY; + } + + /* Set or clear the poll event structure reference in the 'struct file' + * private data. + */ + + filep->f_priv = fds; + + /* Check if we should immediately notify on any of the requested events */ + + if (fds) + { + /* Determine how many bytes are in the buffer */ + + if (dev->d_wrndx >= dev->d_rdndx) + { + nbytes = dev->d_wrndx - dev->d_rdndx; + } + else + { + nbytes = (CONFIG_DEV_PIPE_SIZE-1) + dev->d_wrndx - dev->d_rdndx; + } + + /* Notify the POLLOUT event if the pipe is not full */ + + eventset = 0; + if (nbytes < (CONFIG_DEV_PIPE_SIZE-1)) + { + eventset |= POLLOUT; + } + + /* Notify the POLLIN event if the pipe is not empty */ + + if (nbytes > 0) + { + eventset |= POLLIN; + } + + if (eventset) + { + pipecommon_pollnotify(dev, eventset); + } + } + + sem_post(&dev->d_bfsem); + return OK; +} +#endif + #endif /* CONFIG_DEV_PIPE_SIZE > 0 */ |