9
0
Fork 0

Add poll() method

git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@1262 7fd9a85b-ad96-42d3-883c-3090e2eb8679
This commit is contained in:
patacongo 2008-11-17 20:24:28 +00:00
parent 5ea7999ffc
commit 89f66f0728
6 changed files with 235 additions and 10 deletions

View File

@ -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
};
/****************************************************************************
@ -92,6 +98,25 @@ static ssize_t devnull_write(FAR struct file *filp, FAR const char *buffer, size
return len; /* Say that everything was written */
}
/****************************************************************************
* 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
****************************************************************************/

View File

@ -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,25 +70,54 @@ 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
****************************************************************************/

View File

@ -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
};
/****************************************************************************

View File

@ -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 };

View File

@ -52,6 +52,8 @@
#include <fcntl.h>
#include <errno.h>
#include <assert.h>
#include <debug.h>
#include <nuttx/fs.h>
#include "pipe_common.h"
@ -96,6 +98,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 */

View File

@ -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