summaryrefslogtreecommitdiff
path: root/nuttx
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2008-11-17 20:24:28 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2008-11-17 20:24:28 +0000
commitcff1141190d60f819078be1ad0ed0186b47fd637 (patch)
tree487fc2ad11a4e20eb21f1ad746ed16d88541c05e /nuttx
parent33f0979adc4165594164fb13611961d60f0f2cfc (diff)
downloadpx4-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')
-rw-r--r--nuttx/drivers/dev_null.c29
-rw-r--r--nuttx/drivers/dev_zero.c37
-rw-r--r--nuttx/drivers/fifo.c6
-rw-r--r--nuttx/drivers/pipe.c6
-rw-r--r--nuttx/drivers/pipe_common.c137
-rw-r--r--nuttx/drivers/pipe_common.h30
6 files changed, 235 insertions, 10 deletions
diff --git a/nuttx/drivers/dev_null.c b/nuttx/drivers/dev_null.c
index f097f76c9..8db8c3cbb 100644
--- a/nuttx/drivers/dev_null.c
+++ b/nuttx/drivers/dev_null.c
@@ -45,6 +45,7 @@
#include <sys/types.h>
#include <string.h>
+#include <poll.h>
#include <errno.h>
#include <nuttx/fs.h>
@@ -54,6 +55,9 @@
static ssize_t devnull_read(FAR struct file *, FAR char *, size_t);
static ssize_t devnull_write(FAR struct file *, FAR const char *, size_t);
+#ifndef CONFIG_DISABLE_POLL
+static int devnull_poll(FAR struct file *filp, FAR struct pollfd *poll);
+#endif
/****************************************************************************
* Private Data
@@ -66,8 +70,10 @@ static struct file_operations devnull_fops =
devnull_read, /* read */
devnull_write, /* write */
0, /* seek */
- 0, /* ioctl */
- 0 /* poll */
+ 0 /* ioctl */
+#ifndef CONFIG_DISABLE_POLL
+ , devnull_poll /* poll */
+#endif
};
/****************************************************************************
@@ -93,6 +99,25 @@ static ssize_t devnull_write(FAR struct file *filp, FAR const char *buffer, size
}
/****************************************************************************
+ * Name: devnull_poll
+ ****************************************************************************/
+
+#ifndef CONFIG_DISABLE_POLL
+static int devnull_poll(FAR struct file *filp, FAR struct pollfd *fds)
+{
+ if (fds)
+ {
+ fds->revents |= (fds->events & (POLLIN|POLLOUT));
+ if (fds->revents != 0)
+ {
+ sem_post(fds->sem);
+ }
+ }
+ return OK;
+}
+#endif
+
+/****************************************************************************
* Public Functions
****************************************************************************/
diff --git a/nuttx/drivers/dev_zero.c b/nuttx/drivers/dev_zero.c
index 876734770..08815ace5 100644
--- a/nuttx/drivers/dev_zero.c
+++ b/nuttx/drivers/dev_zero.c
@@ -45,6 +45,7 @@
#include <sys/types.h>
#include <string.h>
+#include <poll.h>
#include <errno.h>
#include <nuttx/fs.h>
@@ -54,6 +55,9 @@
static ssize_t devzero_read(FAR struct file *, FAR char *, size_t);
static ssize_t devzero_write(FAR struct file *, FAR const char *, size_t);
+#ifndef CONFIG_DISABLE_POLL
+static int devzero_poll(FAR struct file *filp, FAR struct pollfd *fds);
+#endif
/****************************************************************************
* Private Data
@@ -66,26 +70,55 @@ static struct file_operations devzero_fops =
devzero_read, /* read */
devzero_write, /* write */
0, /* seek */
- 0, /* ioctl */
- 0 /* poll */
+ 0 /* ioctl */
+#ifndef CONFIG_DISABLE_POLL
+ , devzero_poll /* poll */
+#endif
};
/****************************************************************************
* Private Functions
****************************************************************************/
+/****************************************************************************
+ * Name: devzero_read
+ ****************************************************************************/
+
static ssize_t devzero_read(FAR struct file *filp, FAR char *buffer, size_t len)
{
memset(buffer, 0, len);
return len;
}
+/****************************************************************************
+ * Name: devzero_write
+ ****************************************************************************/
+
static ssize_t devzero_write(FAR struct file *filp, FAR const char *buffer, size_t len)
{
return len;
}
/****************************************************************************
+ * Name: devzero_poll
+ ****************************************************************************/
+
+#ifndef CONFIG_DISABLE_POLL
+static int devzero_poll(FAR struct file *filp, FAR struct pollfd *fds)
+{
+ if (fds)
+ {
+ fds->revents |= (fds->events & (POLLIN|POLLOUT));
+ if (fds->revents != 0)
+ {
+ sem_post(fds->sem);
+ }
+ }
+ return OK;
+}
+#endif
+
+/****************************************************************************
* Public Functions
****************************************************************************/
diff --git a/nuttx/drivers/fifo.c b/nuttx/drivers/fifo.c
index fb17e3461..7775af9ae 100644
--- a/nuttx/drivers/fifo.c
+++ b/nuttx/drivers/fifo.c
@@ -74,8 +74,10 @@ static struct file_operations fifo_fops =
pipecommon_read, /* read */
pipecommon_write, /* write */
0, /* seek */
- 0, /* ioctl */
- 0 /* poll */
+ 0 /* ioctl */
+#ifndef CONFIG_DISABLE_POLL
+ , pipecommon_poll /* poll */
+#endif
};
/****************************************************************************
diff --git a/nuttx/drivers/pipe.c b/nuttx/drivers/pipe.c
index 7e4581c8a..4ad5f0f99 100644
--- a/nuttx/drivers/pipe.c
+++ b/nuttx/drivers/pipe.c
@@ -82,8 +82,10 @@ static struct file_operations pipe_fops =
pipecommon_read, /* read */
pipecommon_write, /* write */
0, /* seek */
- 0, /* ioctl */
- 0, /* pipe */
+ 0 /* ioctl */
+#ifndef CONFIG_DISABLE_POLL
+ , pipecommon_poll /* poll */
+#endif
};
static sem_t g_pipesem = { 1 };
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 */
diff --git a/nuttx/drivers/pipe_common.h b/nuttx/drivers/pipe_common.h
index 34bde18c3..3b43b97b9 100644
--- a/nuttx/drivers/pipe_common.h
+++ b/nuttx/drivers/pipe_common.h
@@ -42,16 +42,24 @@
#include <nuttx/config.h>
#include <sys/types.h>
+#include <poll.h>
#ifndef CONFIG_DEV_PIPE_SIZE
# define CONFIG_DEV_PIPE_SIZE 1024
#endif
+
#if CONFIG_DEV_PIPE_SIZE > 0
/****************************************************************************
* Definitions
****************************************************************************/
+/* Maximum number of threads than can be waiting for POLL events */
+
+#ifndef CONFIG_DEV_PIPE_NPOLLWAITERS
+# define CONFIG_DEV_PIPE_NPOLLWAITERS 2
+#endif
+
/* Maximum number of open's supported on pipe */
#define CONFIG_DEV_PIPE_MAXUSER 255
@@ -70,6 +78,11 @@ typedef uint16 pipe_ndx_t; /* 16-bit index */
typedef ubyte pipe_ndx_t; /* 8-bit index */
#endif
+/* This structure represents the state of one pipe. A reference to this
+ * structure is retained in the i_private field of the inode whenthe pipe/fifo
+ * device is registered.
+ */
+
struct pipe_dev_s
{
sem_t d_bfsem; /* Used to serialize access to d_buffer and indices */
@@ -80,9 +93,21 @@ struct pipe_dev_s
ubyte d_refs; /* References counts on pipe (limited to 255) */
ubyte d_nwriters; /* Number of reference counts for write access */
ubyte d_pipeno; /* Pipe minor number */
- ubyte *d_buffer; /* Buffer alloated when device opend */
+ ubyte *d_buffer; /* Buffer allocated when device opened */
+
+ /* The following is a list if poll structures of threads waiting for
+ * driver events. The 'struct pollfd' reference for each open is also
+ * retained in the f_priv field of the 'struct file'.
+ */
+
+#ifndef CONFIG_DISABLE_POLL
+ struct pollfd *d_fds[CONFIG_DEV_PIPE_NPOLLWAITERS];
+#endif
};
+/*
+ */
+
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
@@ -100,6 +125,9 @@ EXTERN int pipecommon_open(FAR struct file *filep);
EXTERN int pipecommon_close(FAR struct file *filep);
EXTERN ssize_t pipecommon_read(FAR struct file *, FAR char *, size_t);
EXTERN ssize_t pipecommon_write(FAR struct file *, FAR const char *, size_t);
+#ifndef CONFIG_DISABLE_POLL
+EXTERN int pipecommon_poll(FAR struct file *filep, FAR struct pollfd *fds);
+#endif
#undef EXTERN
#ifdef __cplusplus