Add poll() method
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@1262 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
efff6fa8d2
commit
68ec2ba098
@ -45,6 +45,7 @@
|
|||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <poll.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <nuttx/fs.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_read(FAR struct file *, FAR char *, size_t);
|
||||||
static ssize_t devnull_write(FAR struct file *, FAR const 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
|
* Private Data
|
||||||
@ -66,8 +70,10 @@ static struct file_operations devnull_fops =
|
|||||||
devnull_read, /* read */
|
devnull_read, /* read */
|
||||||
devnull_write, /* write */
|
devnull_write, /* write */
|
||||||
0, /* seek */
|
0, /* seek */
|
||||||
0, /* ioctl */
|
0 /* ioctl */
|
||||||
0 /* poll */
|
#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 */
|
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
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
@ -45,6 +45,7 @@
|
|||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <poll.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <nuttx/fs.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_read(FAR struct file *, FAR char *, size_t);
|
||||||
static ssize_t devzero_write(FAR struct file *, FAR const 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
|
* Private Data
|
||||||
@ -66,25 +70,54 @@ static struct file_operations devzero_fops =
|
|||||||
devzero_read, /* read */
|
devzero_read, /* read */
|
||||||
devzero_write, /* write */
|
devzero_write, /* write */
|
||||||
0, /* seek */
|
0, /* seek */
|
||||||
0, /* ioctl */
|
0 /* ioctl */
|
||||||
0 /* poll */
|
#ifndef CONFIG_DISABLE_POLL
|
||||||
|
, devzero_poll /* poll */
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: devzero_read
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t devzero_read(FAR struct file *filp, FAR char *buffer, size_t len)
|
static ssize_t devzero_read(FAR struct file *filp, FAR char *buffer, size_t len)
|
||||||
{
|
{
|
||||||
memset(buffer, 0, len);
|
memset(buffer, 0, len);
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: devzero_write
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t devzero_write(FAR struct file *filp, FAR const char *buffer, size_t len)
|
static ssize_t devzero_write(FAR struct file *filp, FAR const char *buffer, size_t len)
|
||||||
{
|
{
|
||||||
return 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
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
@ -74,8 +74,10 @@ static struct file_operations fifo_fops =
|
|||||||
pipecommon_read, /* read */
|
pipecommon_read, /* read */
|
||||||
pipecommon_write, /* write */
|
pipecommon_write, /* write */
|
||||||
0, /* seek */
|
0, /* seek */
|
||||||
0, /* ioctl */
|
0 /* ioctl */
|
||||||
0 /* poll */
|
#ifndef CONFIG_DISABLE_POLL
|
||||||
|
, pipecommon_poll /* poll */
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
@ -82,8 +82,10 @@ static struct file_operations pipe_fops =
|
|||||||
pipecommon_read, /* read */
|
pipecommon_read, /* read */
|
||||||
pipecommon_write, /* write */
|
pipecommon_write, /* write */
|
||||||
0, /* seek */
|
0, /* seek */
|
||||||
0, /* ioctl */
|
0 /* ioctl */
|
||||||
0, /* pipe */
|
#ifndef CONFIG_DISABLE_POLL
|
||||||
|
, pipecommon_poll /* poll */
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static sem_t g_pipesem = { 1 };
|
static sem_t g_pipesem = { 1 };
|
||||||
|
@ -52,6 +52,8 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
#include <nuttx/fs.h>
|
#include <nuttx/fs.h>
|
||||||
|
|
||||||
#include "pipe_common.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
|
* 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 */
|
/* Increment the reference count on the pipe instance */
|
||||||
|
|
||||||
dev->d_refs++;
|
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);
|
sem_post(&dev->d_bfsem);
|
||||||
ret = sem_wait(&dev->d_rdsem);
|
ret = sem_wait(&dev->d_rdsem);
|
||||||
sched_unlock();
|
sched_unlock();
|
||||||
|
|
||||||
if (ret < 0 || sem_wait(&dev->d_bfsem) < 0)
|
if (ret < 0 || sem_wait(&dev->d_bfsem) < 0)
|
||||||
{
|
{
|
||||||
return ERROR;
|
return ERROR;
|
||||||
@ -361,6 +395,10 @@ ssize_t pipecommon_read(FAR struct file *filep, FAR char *buffer, size_t len)
|
|||||||
sem_post(&dev->d_wrsem);
|
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);
|
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);
|
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 */
|
/* Return the number of bytes written */
|
||||||
|
|
||||||
sem_post(&dev->d_bfsem);
|
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 */
|
#endif /* CONFIG_DEV_PIPE_SIZE > 0 */
|
||||||
|
@ -42,16 +42,24 @@
|
|||||||
|
|
||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <poll.h>
|
||||||
|
|
||||||
#ifndef CONFIG_DEV_PIPE_SIZE
|
#ifndef CONFIG_DEV_PIPE_SIZE
|
||||||
# define CONFIG_DEV_PIPE_SIZE 1024
|
# define CONFIG_DEV_PIPE_SIZE 1024
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if CONFIG_DEV_PIPE_SIZE > 0
|
#if CONFIG_DEV_PIPE_SIZE > 0
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Definitions
|
* 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 */
|
/* Maximum number of open's supported on pipe */
|
||||||
|
|
||||||
#define CONFIG_DEV_PIPE_MAXUSER 255
|
#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 */
|
typedef ubyte pipe_ndx_t; /* 8-bit index */
|
||||||
#endif
|
#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
|
struct pipe_dev_s
|
||||||
{
|
{
|
||||||
sem_t d_bfsem; /* Used to serialize access to d_buffer and indices */
|
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_refs; /* References counts on pipe (limited to 255) */
|
||||||
ubyte d_nwriters; /* Number of reference counts for write access */
|
ubyte d_nwriters; /* Number of reference counts for write access */
|
||||||
ubyte d_pipeno; /* Pipe minor number */
|
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
|
* Public Function Prototypes
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -100,6 +125,9 @@ EXTERN int pipecommon_open(FAR struct file *filep);
|
|||||||
EXTERN int pipecommon_close(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_read(FAR struct file *, FAR char *, size_t);
|
||||||
EXTERN ssize_t pipecommon_write(FAR struct file *, FAR const 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
|
#undef EXTERN
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
Loading…
Reference in New Issue
Block a user