Implement poll/select for sockets
git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@1277 7fd9a85b-ad96-42d3-883c-3090e2eb8679
This commit is contained in:
parent
c23d514aab
commit
a5161eb56f
|
@ -571,4 +571,5 @@
|
|||
full buffer of read data before return. This means that getc would stall when it needed
|
||||
to refill the input buffer. The old behavior (read full blocks) might be useful in other
|
||||
contexts, so it is still available within the driver as a configuration option.
|
||||
* Implement poll() and select() support for TCP/IP sockets
|
||||
|
||||
|
|
|
@ -1207,6 +1207,7 @@ nuttx-0.3.19 2008-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr>
|
|||
full buffer of read data before return. This means that getc would stall when it needed
|
||||
to refill the input buffer. The old behavior (read full blocks) might be useful in other
|
||||
contexts, so it is still available within the driver as a configuration option.
|
||||
* Implement poll() and select() support for TCP/IP sockets
|
||||
|
||||
pascal-0.1.3 2008-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
static ssize_t devconsole_read(struct file *, char *, size_t);
|
||||
static ssize_t devconsole_write(struct file *, const char *, size_t);
|
||||
#ifndef CONFIG_DISABLE_POLL
|
||||
static int devconsole_poll(FAR struct file *filep, FAR struct pollfd *fds);
|
||||
static int devconsole_poll(FAR struct file *filep, FAR struct pollfd *fds, boolean setup);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -85,7 +85,7 @@ static ssize_t devconsole_write(struct file *filp, const char *buffer, size_t le
|
|||
}
|
||||
|
||||
#ifndef CONFIG_DISABLE_POLL
|
||||
static int devconsole_poll(FAR struct file *filep, FAR struct pollfd *fds)
|
||||
static int devconsole_poll(FAR struct file *filep, FAR struct pollfd *fds, boolean setup)
|
||||
{
|
||||
return OK;
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
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);
|
||||
static int devnull_poll(FAR struct file *filp, FAR struct pollfd *fds, boolean setup);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -103,9 +103,9 @@ static ssize_t devnull_write(FAR struct file *filp, FAR const char *buffer, size
|
|||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_DISABLE_POLL
|
||||
static int devnull_poll(FAR struct file *filp, FAR struct pollfd *fds)
|
||||
static int devnull_poll(FAR struct file *filp, FAR struct pollfd *fds, boolean setup)
|
||||
{
|
||||
if (fds)
|
||||
if (setup)
|
||||
{
|
||||
fds->revents |= (fds->events & (POLLIN|POLLOUT));
|
||||
if (fds->revents != 0)
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
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);
|
||||
static int devzero_poll(FAR struct file *filp, FAR struct pollfd *fds, boolean setup);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -104,9 +104,9 @@ static ssize_t devzero_write(FAR struct file *filp, FAR const char *buffer, size
|
|||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_DISABLE_POLL
|
||||
static int devzero_poll(FAR struct file *filp, FAR struct pollfd *fds)
|
||||
static int devzero_poll(FAR struct file *filp, FAR struct pollfd *fds, boolean setup)
|
||||
{
|
||||
if (fds)
|
||||
if (setup)
|
||||
{
|
||||
fds->revents |= (fds->events & (POLLIN|POLLOUT));
|
||||
if (fds->revents != 0)
|
||||
|
|
|
@ -517,7 +517,7 @@ ssize_t pipecommon_write(FAR struct file *filep, FAR const char *buffer, size_t
|
|||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_DISABLE_POLL
|
||||
int pipecommon_poll(FAR struct file *filep, FAR struct pollfd *fds)
|
||||
int pipecommon_poll(FAR struct file *filep, FAR struct pollfd *fds, boolean setup)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct pipe_dev_s *dev = inode->i_private;
|
||||
|
@ -539,7 +539,7 @@ int pipecommon_poll(FAR struct file *filep, FAR struct pollfd *fds)
|
|||
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
|
||||
* is no 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.
|
||||
|
@ -547,14 +547,14 @@ int pipecommon_poll(FAR struct file *filep, FAR struct pollfd *fds)
|
|||
|
||||
if (dev->d_fds[i] == filep->f_priv)
|
||||
{
|
||||
dev->d_fds[i] = fds;
|
||||
dev->d_fds[i] = (setup ? fds : NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= CONFIG_DEV_PIPE_NPOLLWAITERS)
|
||||
{
|
||||
DEBUGASSERT(fds == NULL);
|
||||
DEBUGASSERT(setup);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
|
@ -562,13 +562,16 @@ int pipecommon_poll(FAR struct file *filep, FAR struct pollfd *fds)
|
|||
* private data.
|
||||
*/
|
||||
|
||||
filep->f_priv = fds;
|
||||
|
||||
/* Check if we should immediately notify on any of the requested events */
|
||||
|
||||
if (fds)
|
||||
filep->f_priv = NULL; /* Assume teardown */
|
||||
if (setup)
|
||||
{
|
||||
/* Determine how many bytes are in the buffer */
|
||||
/* Set 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. First,
|
||||
* Determine how many bytes are in the buffer
|
||||
*/
|
||||
|
||||
if (dev->d_wrndx >= dev->d_rdndx)
|
||||
{
|
||||
|
|
|
@ -123,7 +123,7 @@ 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);
|
||||
EXTERN int pipecommon_poll(FAR struct file *filep, FAR struct pollfd *fds, boolean setup);
|
||||
#endif
|
||||
|
||||
#undef EXTERN
|
||||
|
|
|
@ -79,7 +79,7 @@ static ssize_t uart_read(FAR struct file *filep, FAR char *buffer, size_t buflen
|
|||
static ssize_t uart_write(FAR struct file *filep, FAR const char *buffer, size_t buflen);
|
||||
static int uart_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
|
||||
#ifndef CONFIG_DISABLE_POLL
|
||||
static int uart_poll(FAR struct file *filep, FAR struct pollfd *fds);
|
||||
static int uart_poll(FAR struct file *filep, FAR struct pollfd *fds, boolean setup);
|
||||
#endif
|
||||
|
||||
/************************************************************************************
|
||||
|
@ -400,7 +400,7 @@ static int uart_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
|||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_DISABLE_POLL
|
||||
int uart_poll(FAR struct file *filep, FAR struct pollfd *fds)
|
||||
int uart_poll(FAR struct file *filep, FAR struct pollfd *fds, boolean setup)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR uart_dev_t *dev = inode->i_private;
|
||||
|
@ -422,7 +422,7 @@ int uart_poll(FAR struct file *filep, FAR struct pollfd *fds)
|
|||
for (i = 0; i < CONFIG_DEV_CONSOLE_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
|
||||
* is no 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.
|
||||
|
@ -430,14 +430,14 @@ int uart_poll(FAR struct file *filep, FAR struct pollfd *fds)
|
|||
|
||||
if (dev->fds[i] == filep->f_priv)
|
||||
{
|
||||
dev->fds[i] = fds;
|
||||
dev->fds[i] = (setup ? fds : NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= CONFIG_DEV_CONSOLE_NPOLLWAITERS)
|
||||
{
|
||||
DEBUGASSERT(fds == NULL);
|
||||
DEBUGASSERT(setup);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
|
@ -445,13 +445,12 @@ int uart_poll(FAR struct file *filep, FAR struct pollfd *fds)
|
|||
* private data.
|
||||
*/
|
||||
|
||||
filep->f_priv = fds;
|
||||
|
||||
/* Check if we should immediately notify on any of the requested events */
|
||||
|
||||
if (fds)
|
||||
filep->f_priv = NULL; /* Assume teardown */
|
||||
if (setup)
|
||||
{
|
||||
/* Check if the xmit buffer is full. */
|
||||
/* Check if we should immediately notify on any of the requested events.
|
||||
* First, check if the xmit buffer is full.
|
||||
*/
|
||||
|
||||
eventset = 0;
|
||||
|
||||
|
|
|
@ -93,7 +93,7 @@ static void poll_semtake(FAR sem_t *sem)
|
|||
****************************************************************************/
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
static int poll_fdsetup(int fd, FAR struct pollfd *fds)
|
||||
static int poll_fdsetup(int fd, FAR struct pollfd *fds, boolean setup)
|
||||
{
|
||||
FAR struct filelist *list;
|
||||
FAR struct file *this_file;
|
||||
|
@ -137,7 +137,7 @@ static int poll_fdsetup(int fd, FAR struct pollfd *fds)
|
|||
{
|
||||
/* Yes, then setup the poll */
|
||||
|
||||
ret = (int)inode->u.i_ops->poll(this_file, fds);
|
||||
ret = (int)inode->u.i_ops->poll(this_file, fds, setup);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -168,7 +168,7 @@ static inline int poll_setup(FAR struct pollfd *fds, nfds_t nfds, sem_t *sem)
|
|||
|
||||
/* Set up the poll */
|
||||
|
||||
ret = poll_fdsetup(fds[i].fd, &fds[i]);
|
||||
ret = poll_fdsetup(fds[i].fd, &fds[i], TRUE);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
|
@ -201,7 +201,7 @@ static inline int poll_teardown(FAR struct pollfd *fds, nfds_t nfds, int *count)
|
|||
{
|
||||
/* Teardown the poll */
|
||||
|
||||
status = poll_fdsetup(fds[i].fd, NULL);
|
||||
status = poll_fdsetup(fds[i].fd, &fds[i], FALSE);
|
||||
if (status < 0)
|
||||
{
|
||||
ret = status;
|
||||
|
|
|
@ -118,6 +118,7 @@
|
|||
|
||||
struct uip_driver_s; /* Forward reference */
|
||||
struct uip_callback_s; /* Forward reference */
|
||||
|
||||
struct uip_conn
|
||||
{
|
||||
dq_entry_t node; /* Implements a doubly linked list */
|
||||
|
@ -179,13 +180,13 @@ struct uip_conn
|
|||
|
||||
/* accept() is called when the TCP logic has created a connection */
|
||||
|
||||
void *accept_private;
|
||||
int (*accept)(struct uip_conn *listener, struct uip_conn *conn);
|
||||
FAR void *accept_private;
|
||||
int (*accept)(FAR struct uip_conn *listener, struct uip_conn *conn);
|
||||
|
||||
/* connection_event() is called on any of the subset of connection-related events */
|
||||
|
||||
void *connection_private;
|
||||
void (*connection_event)(struct uip_conn *conn, uint16 flags);
|
||||
FAR void *connection_private;
|
||||
void (*connection_event)(FAR struct uip_conn *conn, uint16 flags);
|
||||
};
|
||||
|
||||
/* The following structure is used to handle read-ahead buffering for TCP
|
||||
|
|
|
@ -76,7 +76,7 @@ struct file_operations
|
|||
off_t (*seek)(FAR struct file *filp, off_t offset, int whence);
|
||||
int (*ioctl)(FAR struct file *filp, int cmd, unsigned long arg);
|
||||
#ifndef CONFIG_DISABLE_POLL
|
||||
int (*poll)(FAR struct file *filp, struct pollfd *fds);
|
||||
int (*poll)(FAR struct file *filp, struct pollfd *fds, boolean setup);
|
||||
#endif
|
||||
|
||||
/* The two structures need not be common after this point */
|
||||
|
|
|
@ -84,17 +84,17 @@ typedef uint16 socktimeo_t;
|
|||
|
||||
struct socket
|
||||
{
|
||||
int s_crefs; /* Reference count on the socket */
|
||||
uint8 s_type; /* Protocol type: Only SOCK_STREAM or SOCK_DGRAM */
|
||||
uint8 s_flags; /* See _SF_* definitions */
|
||||
int s_crefs; /* Reference count on the socket */
|
||||
uint8 s_type; /* Protocol type: Only SOCK_STREAM or SOCK_DGRAM */
|
||||
uint8 s_flags; /* See _SF_* definitions */
|
||||
#ifdef CONFIG_NET_SOCKOPTS
|
||||
sockopt_t s_options; /* Selected socket options */
|
||||
sockopt_t s_options; /* Selected socket options */
|
||||
#ifndef CONFIG_DISABLE_CLOCK
|
||||
socktimeo_t s_rcvtimeo; /* Receive timeout value (in deciseconds) */
|
||||
socktimeo_t s_sndtimeo; /* Send timeout value (in deciseconds) */
|
||||
socktimeo_t s_rcvtimeo; /* Receive timeout value (in deciseconds) */
|
||||
socktimeo_t s_sndtimeo; /* Send timeout value (in deciseconds) */
|
||||
#endif
|
||||
#endif
|
||||
void *s_conn; /* Connection: struct uip_conn or uip_udp_conn */
|
||||
void *s_conn; /* Connection: struct uip_conn or uip_udp_conn */
|
||||
};
|
||||
|
||||
/* This defines a list of sockets indexed by the socket descriptor */
|
||||
|
|
|
@ -108,6 +108,12 @@ struct pollfd
|
|||
sem_t *sem; /* Pointer to semaphore used to post output event */
|
||||
pollevent_t events; /* The input event flags */
|
||||
pollevent_t revents; /* The output event flags */
|
||||
|
||||
/* The socket poll logic needs a place to retain state info */
|
||||
|
||||
#if CONFIG_NSOCKET_DESCRIPTORS > 0 && defined(CONFIG_NET_TCP) && CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0
|
||||
FAR void *private;
|
||||
#endif
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/****************************************************************************
|
||||
* net-internal.h
|
||||
* net/net-internal.h
|
||||
*
|
||||
* Copyright (C) 2007 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -14,7 +14,7 @@
|
|||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name Gregory Nutt nor the names of its contributors may be
|
||||
* 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.
|
||||
*
|
||||
|
|
|
@ -49,7 +49,231 @@
|
|||
#include "net-internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Global Functions
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Network polling can only be supported on TCP and only if read-ahead buffering
|
||||
* is enabled (it could be supported on UDP as will if it also had read-ahead
|
||||
* buffering.
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_DISABLE_POLL) && CONFIG_NSOCKET_DESCRIPTORS > 0 && \
|
||||
defined(CONFIG_NET_TCP) && CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0
|
||||
# define HAVE_NETPOLL 1
|
||||
#else
|
||||
# undef HAVE_NETPOLL
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
struct net_poll_s
|
||||
{
|
||||
FAR struct pollfd *fds; /* The descriptor poll info */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Function: poll_interrupt
|
||||
*
|
||||
* Description:
|
||||
* This function is called from the interrupt level to perform the actual
|
||||
* TCP receive operation via by the uIP layer.
|
||||
*
|
||||
* Parameters:
|
||||
* dev The structure of the network driver that caused the interrupt
|
||||
* conn The connection structure associated with the socket
|
||||
* flags Set of events describing why the callback was invoked
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
* Assumptions:
|
||||
* Running at the interrupt level
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_NETPOLL
|
||||
static uint16 poll_interrupt(struct uip_driver_s *dev, FAR void *conn,
|
||||
FAR void *pvprivate, uint16 flags)
|
||||
{
|
||||
struct pollfd *fds = (struct recvfrom_s *)pvprivate;
|
||||
|
||||
nvdbg("flags: %04x\n", flags);
|
||||
|
||||
/* 'private' might be null in some race conditions (?) */
|
||||
|
||||
if (fds)
|
||||
{
|
||||
pollevent_t eventset = 0;
|
||||
|
||||
/* Check for data availability events. */
|
||||
|
||||
if ((flags & UIP_NEWDATA) != 0)
|
||||
{
|
||||
eventset |= POLLIN & fds->events;
|
||||
}
|
||||
|
||||
/* A poll is a sign that we are free to send data. */
|
||||
|
||||
if ((flags & UIP_POLL) != 0)
|
||||
{
|
||||
eventset |= POLLOUT & fds->events;
|
||||
}
|
||||
|
||||
/* Check for a loss of connection events */
|
||||
|
||||
if ((flags & (UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT)) != 0)
|
||||
{
|
||||
eventset |= (POLLERR|POLLHUP);
|
||||
}
|
||||
|
||||
if (eventset)
|
||||
{
|
||||
fds->revevents |= eventset;
|
||||
sem_post(fds->sem);
|
||||
}
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
#endif /* HAVE_NETPOLL */
|
||||
|
||||
/****************************************************************************
|
||||
* Function: net_pollsetup
|
||||
*
|
||||
* Description:
|
||||
* Setup to monitor events on one TCP/IP socket
|
||||
*
|
||||
* Input Parameters:
|
||||
* conn - The TCP/IP connection of interest
|
||||
* fds - The structure describing the events to be monitored, OR NULL if
|
||||
* this is a request to stop monitoring events.
|
||||
*
|
||||
* Returned Value:
|
||||
* 0: Success; Negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_NETPOLL
|
||||
static inline int net_pollsetup((FAR struct uip_conn *)conn, struct pollfd *fds)
|
||||
{
|
||||
FAR struct uip_callback_s *cb;
|
||||
irqstate_t flags;
|
||||
int ret;
|
||||
|
||||
/* Sanity check */
|
||||
|
||||
#ifdef CONFIG_DEBUG
|
||||
if (!conn || !fds || fds->private)
|
||||
{
|
||||
ret = -EINVAL;
|
||||
goto errout;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Some of the following must be atomic */
|
||||
|
||||
flags = irqsave();
|
||||
|
||||
/* Allocate a TCP/IP callback structure */
|
||||
|
||||
cb = uip_tcpcallbackalloc(conn);
|
||||
if (!cb)
|
||||
{
|
||||
ret = -EBUSY;
|
||||
goto errout_with_irq;
|
||||
}
|
||||
|
||||
/* Initialize the callbcack structure */
|
||||
|
||||
cb->flags = UIP_NEWDATA|UIP_POLL|UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT;
|
||||
cb->private = (FAR void *)fds;
|
||||
cb->event = poll_interrupt;
|
||||
|
||||
/* Save the nps reference in the poll structure for use at teardown as well */
|
||||
|
||||
fds->private = (FAR void *)cb;
|
||||
|
||||
/* Check for read data availability now */
|
||||
|
||||
if (!sq_empty(&conn->readahead))
|
||||
{
|
||||
fds->revents = fds->events & POLLIN;
|
||||
if (fds->revents != 0)
|
||||
{
|
||||
/* If data is available now, the signal the poll logic */
|
||||
|
||||
sem_post(fds->sem);
|
||||
}
|
||||
}
|
||||
irqrestore(flags);
|
||||
return OK;
|
||||
|
||||
errout_with_irq:
|
||||
irqrestore(flags);
|
||||
free(nps);
|
||||
errout:
|
||||
return ret;
|
||||
}
|
||||
#endif /* HAVE_NETPOLL */
|
||||
|
||||
/****************************************************************************
|
||||
* Function: net_pollteardown
|
||||
*
|
||||
* Description:
|
||||
* Teardown monitoring of events on an TCP/IP socket
|
||||
*
|
||||
* Input Parameters:
|
||||
* conn - The TCP/IP connection of interest
|
||||
*
|
||||
* Returned Value:
|
||||
* 0: Success; Negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_NETPOLL
|
||||
static inline int net_pollteardown((FAR struct uip_conn *)conn, struct pollfd *fds)
|
||||
{
|
||||
FAR struct uip_callback_s *cb;
|
||||
irqstate_t flags;
|
||||
int ret;
|
||||
|
||||
/* Sanity check */
|
||||
|
||||
#ifdef CONFIG_DEBUG
|
||||
if (!conn || !fds || !fds->private)
|
||||
{
|
||||
ret = -EINVAL;
|
||||
goto errout;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Recover the socket descriptor poll state info from the poll structure */
|
||||
|
||||
cb = (FAR struct uip_callback_s *)fds->private;
|
||||
if (cb)
|
||||
{
|
||||
/* Release the callback */
|
||||
|
||||
flags = irqsave();
|
||||
uip_tcpcallbackfree(conn, cb);
|
||||
irqrestore(flags);
|
||||
|
||||
/* Release the poll/select data slot */
|
||||
|
||||
fds->private = NULL;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
#endif /* HAVE_NETPOLL */
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -59,22 +283,74 @@
|
|||
* The standard poll() operation redirects operations on socket descriptors
|
||||
* to this function.
|
||||
*
|
||||
* Parameters:
|
||||
* Input Parameters:
|
||||
* fd - The socket descriptor of interest
|
||||
* fds - The structures describing events to be monitored, OR NULL if
|
||||
* fds - The structure describing the events to be monitored, OR NULL if
|
||||
* this is a request to stop monitoring events.
|
||||
*
|
||||
* Returned Value:
|
||||
* TBD
|
||||
* 0: Success; Negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_DISABLE_POLL
|
||||
int net_poll(int sockfd, struct pollfd *fds)
|
||||
{
|
||||
#ifdef CONFIG_CPP_HAVE_WARNING
|
||||
# warning To be provided
|
||||
#endif
|
||||
#ifndef HAVE_NETPOLL
|
||||
return -ENOSYS;
|
||||
}
|
||||
#else
|
||||
FAR struct socket *psock;
|
||||
int ret;
|
||||
|
||||
#endif /* CONFIG_NET&& !CONFIG_DISABLE_POLL */
|
||||
/* Verify that non-NULL pointers were passed */
|
||||
|
||||
#ifdef CONFIG_DEBUG
|
||||
if (!fds)
|
||||
{
|
||||
ret = -EINVAL;
|
||||
goto errout;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Get the underlying socket structure and verify that the sockfd
|
||||
* corresponds to valid, allocated socket
|
||||
*/
|
||||
|
||||
psock = sockfd_socket(sockfd);
|
||||
if (!psock || psock->s_crefs <= 0)
|
||||
{
|
||||
ret = -EBADF;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_UDP
|
||||
/* poll() not supported for UDP */
|
||||
|
||||
if (psock->s_type != SOCK_STREAM)
|
||||
{
|
||||
ret = -ENOSYS;
|
||||
goto errout;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Check if we are setting up or tearing down the poll */
|
||||
if (fds)
|
||||
{
|
||||
/* Perform the TCP/IP poll() setup */
|
||||
|
||||
ret = net_pollsetup((FAR struct uip_conn *)psock->conn, fds);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Perform the TCP/IP poll() teardown */
|
||||
|
||||
ret = net_pollteardown((FAR struct uip_conn *)psock->conn);
|
||||
}
|
||||
|
||||
errout:
|
||||
return ret;
|
||||
#endif /* HAVE_NETPOLL */
|
||||
}
|
||||
#endif /* !CONFIG_DISABLE_POLL */
|
||||
|
||||
#endif /* CONFIG_NET && !CONFIG_DISABLE_POLL */
|
||||
|
|
Loading…
Reference in New Issue