Squashed commit of the following:

Author: Gregory Nutt <gnutt@nuttx.org>

    Run all .h and .c files modified in last PR through nxstyle.

Author: Xiang Xiao <xiaoxiang@xiaomi.com>

    Net cleanup (#17)

    * Fix the semaphore usage issue found in tcp/udp

    1. The count semaphore need disable priority inheritance
    2. Loop again if net_lockedwait return -EINTR
    3. Call nxsem_trywait to avoid the race condition
    4. Call nxsem_post instead of sem_post

    * Put the work notifier into free list to avoid the heap fragment in the long run.  Since the allocation strategy is encapsulated internally, we can even refine the implementation later.

    * Network stack shouldn't allocate memory in the poll implementation to avoid the heap fragment in the long run, other modification include:

    1. Select MM_IOB automatically since ICMP[v6] socket can't work without the read ahead buffer
    2. Remove the net lock since xxx_callback_free already do the same thing
    3. TCP/UDP poll should work even the read ahead buffer isn't enabled at all

    * Add NET_ prefix for UDP_NOTIFIER and TCP_NOTIFIER option to align with other UDP/TCP option convention

    * Remove the unused _SF_[IDLE|ACCEPT|SEND|RECV|MASK] flags since there are code to set/clear these flags, but nobody check them.
This commit is contained in:
Xiang Xiao 2019-12-31 09:26:14 -06:00 committed by Gregory Nutt
parent e33fc3dc89
commit 90c52e6f8f
52 changed files with 375 additions and 558 deletions

View File

@ -57,6 +57,7 @@ CONFIG_NET_BROADCAST=y
CONFIG_NET_ICMP=y
CONFIG_NET_SOCKOPTS=y
CONFIG_NET_TCP=y
CONFIG_NET_TCP_NOTIFIER=y
CONFIG_NET_TCP_WRITE_BUFFERS=y
CONFIG_NET_UDP=y
CONFIG_NFILE_DESCRIPTORS=8
@ -90,7 +91,6 @@ CONFIG_SYMTAB_ORDEREDBYNAME=y
CONFIG_SYSTEM_MDIO=y
CONFIG_SYSTEM_NSH=y
CONFIG_TASK_NAME_SIZE=0
CONFIG_TCP_NOTIFIER=y
CONFIG_UART0_SERIAL_CONSOLE=y
CONFIG_USERMAIN_STACKSIZE=4096
CONFIG_USER_ENTRYPOINT="nsh_main"

View File

@ -309,36 +309,6 @@ struct work_notifier_s
worker_t worker; /* The worker function to schedule */
};
/* This structure describes one notification list entry. It is cast-
* compatible with struct work_notifier_s. This structure is an allocated
* container for the user notification data. It is allocated because it
* must persist until the work is executed and must be freed using
* kmm_free() by the work.
*
* With the work notification is scheduled, the work function will receive
* the allocated instance of struct work_notifier_entry_s as its input
* argument. When it completes the notification operation, the work function
* is responsible for freeing that instance.
*/
struct work_notifier_entry_s
{
/* This must appear at the beginning of the structure. A reference to
* the struct work_notifier_entry_s instance must be cast-compatible with
* struct dq_entry_s.
*/
struct work_s work; /* Used for scheduling the work */
/* User notification information */
struct work_notifier_s info; /* The notification info */
/* Additional payload needed to manage the notification */
int16_t key; /* Unique ID for the notification */
};
/****************************************************************************
* Public Data
****************************************************************************/

View File

@ -387,10 +387,6 @@ ssize_t bluetooth_recvfrom(FAR struct socket *psock, FAR void *buf,
(void)nxsem_init(&state.ir_sem, 0, 0); /* Doesn't really fail */
(void)nxsem_setprotocol(&state.ir_sem, SEM_PRIO_NONE);
/* Set the socket state to receiving */
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_RECV);
/* Set up the callback in the connection */
state.ir_cb = bluetooth_callback_alloc(&radio->r_dev, conn);
@ -418,9 +414,6 @@ ssize_t bluetooth_recvfrom(FAR struct socket *psock, FAR void *buf,
ret = -EBUSY;
}
/* Set the socket state to idle */
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE);
nxsem_destroy(&state.ir_sem);
errout_with_lock:

View File

@ -283,10 +283,6 @@ ssize_t psock_bluetooth_sendto(FAR struct socket *psock, FAR const void *buf,
return -ENODEV;
}
/* Set the socket state to sending */
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_SEND);
/* Perform the send operation */
/* Initialize the state structure. This is done with the network locked
@ -345,10 +341,6 @@ ssize_t psock_bluetooth_sendto(FAR struct socket *psock, FAR const void *buf,
nxsem_destroy(&state.is_sem);
net_unlock();
/* Set the socket state to idle */
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE);
/* Check for a errors, Errors are signaled by negative errno values
* for the send length
*/

View File

@ -25,6 +25,7 @@ if NET_ICMP && !NET_ICMP_NO_STACK
config NET_ICMP_SOCKET
bool "IPPROTO_ICMP socket support"
default n
select MM_IOB
---help---
Enable support for IPPROTO_ICMP sockets. These sockets are needed
for application level support for sending ECHO (ping) requests and
@ -35,7 +36,10 @@ if NET_ICMP_SOCKET
config NET_ICMP_NCONNS
int "Max ICMP packet sockets"
default 4
depends on MM_IOB
config NET_ICMP_NPOLLWAITERS
int "Number of ICMP poll waiters"
default 1
endif # NET_ICMP_SOCKET
endif # NET_ICMP && !NET_ICMP_NO_STACK

View File

@ -42,10 +42,7 @@ NET_CSRCS += icmp_input.c
ifeq ($(CONFIG_NET_ICMP_SOCKET),y)
SOCK_CSRCS += icmp_sockif.c icmp_poll.c icmp_conn.c icmp_sendto.c
SOCK_CSRCS += icmp_recvfrom.c
ifeq ($(CONFIG_MM_IOB),y)
SOCK_CSRCS += icmp_netpoll.c
endif
SOCK_CSRCS += icmp_recvfrom.c icmp_netpoll.c
endif
# Include ICMP build support

View File

@ -70,11 +70,24 @@
* Public types
****************************************************************************/
struct socket; /* Forward reference */
struct sockaddr; /* Forward reference */
struct pollfd; /* Forward reference */
#ifdef CONFIG_NET_ICMP_SOCKET
/* Representation of a IPPROTO_ICMP socket connection */
struct devif_callback_s; /* Forward reference */
/* This is a container that holds the poll-related information */
struct icmp_poll_s
{
FAR struct socket *psock; /* IPPROTO_ICMP socket structure */
FAR struct pollfd *fds; /* Needed to handle poll events */
FAR struct devif_callback_s *cb; /* Needed to teardown the poll */
};
struct icmp_conn_s
{
/* Common prologue of all connection structures. */
@ -97,14 +110,18 @@ struct icmp_conn_s
FAR struct net_driver_s *dev; /* Needed to free the callback structure */
#ifdef CONFIG_MM_IOB
/* ICMP response read-ahead list. A singly linked list of type struct
* iob_qentry_s where the ICMP read-ahead data for the current ID is
* retained.
*/
struct iob_queue_s readahead; /* Read-ahead buffering */
#endif
/* The following is a list of poll structures of threads waiting for
* socket events.
*/
struct icmp_poll_s pollinfo[CONFIG_NET_ICMP_NPOLLWAITERS];
};
#endif
@ -130,10 +147,6 @@ EXTERN const struct sock_intf_s g_icmp_sockif;
* Public Function Prototypes
****************************************************************************/
struct socket; /* Forward reference */
struct sockaddr; /* Forward reference */
struct pollfd; /* Forward reference */
/****************************************************************************
* Name: icmp_input
*

View File

@ -43,28 +43,12 @@
#include <poll.h>
#include <debug.h>
#include <nuttx/kmalloc.h>
#include <nuttx/net/net.h>
#include <devif/devif.h>
#include "devif/devif.h"
#include "netdev/netdev.h"
#include "icmp/icmp.h"
#ifdef CONFIG_MM_IOB
/****************************************************************************
* Private Types
****************************************************************************/
/* This is an allocated container that holds the poll-related information */
struct icmp_poll_s
{
FAR struct socket *psock; /* IPPROTO_ICMP socket structure */
FAR struct pollfd *fds; /* Needed to handle poll events */
FAR struct devif_callback_s *cb; /* Needed to teardown the poll */
};
/****************************************************************************
* Private Functions
****************************************************************************/
@ -178,18 +162,22 @@ int icmp_pollsetup(FAR struct socket *psock, FAR struct pollfd *fds)
DEBUGASSERT(conn != NULL && fds != NULL);
/* Allocate a container to hold the poll information */
info = (FAR struct icmp_poll_s *)kmm_malloc(sizeof(struct icmp_poll_s));
if (!info)
{
return -ENOMEM;
}
/* Some of the following must be atomic */
net_lock();
/* Find a container to hold the poll information */
info = conn->pollinfo;
while (info->psock != NULL)
{
if (++info >= &conn->pollinfo[CONFIG_NET_ICMP_NPOLLWAITERS])
{
ret = -ENOMEM;
goto errout_with_lock;
}
}
/* Allocate a ICMP callback structure */
cb = icmp_callback_alloc(conn->dev, conn);
@ -249,11 +237,7 @@ int icmp_pollsetup(FAR struct socket *psock, FAR struct pollfd *fds)
nxsem_post(fds->sem);
}
net_unlock();
return OK;
errout_with_lock:
kmm_free(info);
net_unlock();
return ret;
}
@ -293,9 +277,7 @@ int icmp_pollteardown(FAR struct socket *psock, FAR struct pollfd *fds)
{
/* Release the callback */
net_lock();
icmp_callback_free(conn->dev, conn, info->cb);
net_unlock();
/* Release the poll/select data slot */
@ -303,10 +285,8 @@ int icmp_pollteardown(FAR struct socket *psock, FAR struct pollfd *fds)
/* Then free the poll info container */
kmm_free(info);
info->psock = NULL;
}
return OK;
}
#endif /* !CONFIG_MM_IOB */

View File

@ -445,7 +445,6 @@ int icmp_listen(FAR struct socket *psock, int backlog)
static int icmp_netpoll(FAR struct socket *psock, FAR struct pollfd *fds,
bool setup)
{
#ifdef CONFIG_MM_IOB
/* Check if we are setting up or tearing down the poll */
if (setup)
@ -460,9 +459,6 @@ static int icmp_netpoll(FAR struct socket *psock, FAR struct pollfd *fds,
return icmp_pollteardown(psock, fds);
}
#else
return -ENOSYS;
#endif /* CONFIG_MM_IOB */
}
/****************************************************************************

View File

@ -26,6 +26,7 @@ if NET_ICMPv6 && !NET_ICMPv6_NO_STACK
config NET_ICMPv6_SOCKET
bool "IPPROTO_ICMP6 socket support"
default n
select MM_IOB
---help---
Enable support for IPPROTO_ICMP6 sockets. These sockets are needed
for application level support for sending ICMPv7 ECHO requests and
@ -203,7 +204,10 @@ if NET_ICMPv6_SOCKET
config NET_ICMPv6_NCONNS
int "Max ICMPv6 packet sockets"
default 4
depends on MM_IOB
config NET_ICMPv6_NPOLLWAITERS
int "Number of ICMPv6 poll waiters"
default 1
endif # NET_ICMPv6_SOCKET

View File

@ -43,10 +43,7 @@ NET_CSRCS += icmpv6_linkipaddr.c
ifeq ($(CONFIG_NET_ICMPv6_SOCKET),y)
SOCK_CSRCS += icmpv6_sockif.c icmpv6_conn.c icmpv6_sendto.c
SOCK_CSRCS += icmpv6_recvfrom.c
ifeq ($(CONFIG_MM_IOB),y)
SOCK_CSRCS += icmpv6_netpoll.c
endif
SOCK_CSRCS += icmpv6_recvfrom.c icmpv6_netpoll.c
endif
ifeq ($(CONFIG_NET_ICMPv6_NEIGHBOR),y)

View File

@ -71,11 +71,26 @@
* Public Type Definitions
****************************************************************************/
struct timespec; /* Forward reference */
struct net_driver_s; /* Forward reference */
struct socket; /* Forward reference */
struct sockaddr; /* Forward reference */
struct pollfd; /* Forward reference */
#ifdef CONFIG_NET_ICMPv6_SOCKET
/* Representation of a IPPROTO_ICMP socket connection */
struct devif_callback_s; /* Forward reference */
/* This is a container that holds the poll-related information */
struct icmpv6_poll_s
{
FAR struct socket *psock; /* IPPROTO_ICMP6 socket structure */
FAR struct pollfd *fds; /* Needed to handle poll events */
FAR struct devif_callback_s *cb; /* Needed to teardown the poll */
};
struct icmpv6_conn_s
{
/* Common prologue of all connection structures. */
@ -98,14 +113,18 @@ struct icmpv6_conn_s
FAR struct net_driver_s *dev; /* Needed to free the callback structure */
#ifdef CONFIG_MM_IOB
/* ICMPv6 response read-ahead list. A singly linked list of type struct
* iob_qentry_s where the ICMPv6 read-ahead data for the current ID is
* retained.
*/
struct iob_queue_s readahead; /* Read-ahead buffering */
#endif
/* The following is a list of poll structures of threads waiting for
* socket events.
*/
struct icmpv6_poll_s pollinfo[CONFIG_NET_ICMPv6_NPOLLWAITERS];
};
#endif
@ -155,12 +174,6 @@ EXTERN const struct sock_intf_s g_icmpv6_sockif;
* Public Function Prototypes
****************************************************************************/
struct timespec; /* Forward reference */
struct net_driver_s; /* Forward reference */
struct socket; /* Forward reference */
struct sockaddr; /* Forward reference */
struct pollfd; /* Forward reference */
/****************************************************************************
* Name: icmpv6_input
*

View File

@ -43,28 +43,12 @@
#include <poll.h>
#include <debug.h>
#include <nuttx/kmalloc.h>
#include <nuttx/net/net.h>
#include <devif/devif.h>
#include "devif/devif.h"
#include "netdev/netdev.h"
#include "icmpv6/icmpv6.h"
#ifdef CONFIG_MM_IOB
/****************************************************************************
* Private Types
****************************************************************************/
/* This is an allocated container that holds the poll-related information */
struct icmpv6_poll_s
{
FAR struct socket *psock; /* IPPROTO_ICMP6 socket structure */
FAR struct pollfd *fds; /* Needed to handle poll events */
FAR struct devif_callback_s *cb; /* Needed to teardown the poll */
};
/****************************************************************************
* Private Functions
****************************************************************************/
@ -178,18 +162,24 @@ int icmpv6_pollsetup(FAR struct socket *psock, FAR struct pollfd *fds)
DEBUGASSERT(conn != NULL && fds != NULL);
/* Allocate a container to hold the poll information */
info = (FAR struct icmpv6_poll_s *)kmm_malloc(sizeof(struct icmpv6_poll_s));
if (!info)
{
return -ENOMEM;
}
/* Some of the following must be atomic */
net_lock();
/* Find a container to hold the poll information */
info = conn->pollinfo;
while (info->psock != NULL)
{
if (++info >= &conn->pollinfo[CONFIG_NET_ICMPv6_NPOLLWAITERS])
{
ret = -ENOMEM;
goto errout_with_lock;
}
}
/* Allocate a ICMP callback structure */
cb = icmpv6_callback_alloc(conn->dev, conn);
if (cb == NULL)
{
@ -247,11 +237,7 @@ int icmpv6_pollsetup(FAR struct socket *psock, FAR struct pollfd *fds)
nxsem_post(fds->sem);
}
net_unlock();
return OK;
errout_with_lock:
kmm_free(info);
net_unlock();
return ret;
}
@ -291,9 +277,7 @@ int icmpv6_pollteardown(FAR struct socket *psock, FAR struct pollfd *fds)
{
/* Release the callback */
net_lock();
icmpv6_callback_free(conn->dev, conn, info->cb);
net_unlock();
/* Release the poll/select data slot */
@ -301,10 +285,8 @@ int icmpv6_pollteardown(FAR struct socket *psock, FAR struct pollfd *fds)
/* Then free the poll info container */
kmm_free(info);
info->psock = NULL;
}
return OK;
}
#endif /* !CONFIG_MM_IOB */

View File

@ -445,7 +445,6 @@ int icmpv6_listen(FAR struct socket *psock, int backlog)
static int icmpv6_netpoll(FAR struct socket *psock, FAR struct pollfd *fds,
bool setup)
{
#ifdef CONFIG_MM_IOB
/* Check if we are setting up or tearing down the poll */
if (setup)
@ -460,9 +459,6 @@ static int icmpv6_netpoll(FAR struct socket *psock, FAR struct pollfd *fds,
return icmpv6_pollteardown(psock, fds);
}
#else
return -ENOSYS;
#endif /* CONFIG_MM_IOB */
}
/****************************************************************************

View File

@ -385,10 +385,6 @@ ssize_t ieee802154_recvfrom(FAR struct socket *psock, FAR void *buf,
(void)nxsem_init(&state.ir_sem, 0, 0); /* Doesn't really fail */
(void)nxsem_setprotocol(&state.ir_sem, SEM_PRIO_NONE);
/* Set the socket state to receiving */
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_RECV);
/* Set up the callback in the connection */
state.ir_cb = ieee802154_callback_alloc(&radio->r_dev, conn);
@ -416,9 +412,6 @@ ssize_t ieee802154_recvfrom(FAR struct socket *psock, FAR void *buf,
ret = -EBUSY;
}
/* Set the socket state to idle */
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE);
nxsem_destroy(&state.ir_sem);
errout_with_lock:

View File

@ -471,10 +471,6 @@ ssize_t psock_ieee802154_sendto(FAR struct socket *psock, FAR const void *buf,
return -ENODEV;
}
/* Set the socket state to sending */
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_SEND);
/* Perform the send operation */
/* Initialize the state structure. This is done with the network
@ -534,10 +530,6 @@ ssize_t psock_ieee802154_sendto(FAR struct socket *psock, FAR const void *buf,
nxsem_destroy(&state.is_sem);
net_unlock();
/* Set the socket state to idle */
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE);
/* Check for a errors, Errors are signaled by negative errno values
* for the send length
*/

View File

@ -956,29 +956,29 @@ static int inet_accept(FAR struct socket *psock, FAR struct sockaddr *addr,
*
****************************************************************************/
#if defined(HAVE_TCP_POLL) || defined(HAVE_UDP_POLL)
#if defined(NET_TCP_HAVE_STACK) || defined(NET_UDP_HAVE_STACK)
static inline int inet_pollsetup(FAR struct socket *psock,
FAR struct pollfd *fds)
{
#ifdef HAVE_TCP_POLL
#ifdef NET_TCP_HAVE_STACK
if (psock->s_type == SOCK_STREAM)
{
return tcp_pollsetup(psock, fds);
}
else
#endif /* HAVE_TCP_POLL */
#ifdef HAVE_UDP_POLL
#endif /* NET_TCP_HAVE_STACK */
#ifdef NET_UDP_HAVE_STACK
if (psock->s_type != SOCK_STREAM)
{
return udp_pollsetup(psock, fds);
}
else
#endif /* HAVE_UDP_POLL */
#endif /* NET_UDP_HAVE_STACK */
{
return -ENOSYS;
}
}
#endif /* HAVE_TCP_POLL || HAVE_UDP_POLL */
#endif /* NET_TCP_HAVE_STACK || NET_UDP_HAVE_STACK */
/****************************************************************************
* Name: inet_pollteardown
@ -996,29 +996,29 @@ static inline int inet_pollsetup(FAR struct socket *psock,
*
****************************************************************************/
#if defined(HAVE_TCP_POLL) || defined(HAVE_UDP_POLL)
#if defined(NET_TCP_HAVE_STACK) || defined(NET_UDP_HAVE_STACK)
static inline int inet_pollteardown(FAR struct socket *psock,
FAR struct pollfd *fds)
{
#ifdef HAVE_TCP_POLL
#ifdef NET_TCP_HAVE_STACK
if (psock->s_type == SOCK_STREAM)
{
return tcp_pollteardown(psock, fds);
}
else
#endif /* HAVE_TCP_POLL */
#ifdef HAVE_UDP_POLL
#endif /* NET_TCP_HAVE_STACK */
#ifdef NET_UDP_HAVE_STACK
if (psock->s_type == SOCK_DGRAM)
{
return udp_pollteardown(psock, fds);
}
else
#endif /* HAVE_UDP_POLL */
#endif /* NET_UDP_HAVE_STACK */
{
return -ENOSYS;
}
}
#endif /* HAVE_TCP_POLL || HAVE_UDP_POLL */
#endif /* NET_TCP_HAVE_STACK || NET_UDP_HAVE_STACK */
/****************************************************************************
* Name: inet_poll
@ -1041,7 +1041,7 @@ static inline int inet_pollteardown(FAR struct socket *psock,
static int inet_poll(FAR struct socket *psock, FAR struct pollfd *fds,
bool setup)
{
#if defined(HAVE_TCP_POLL) || defined(HAVE_UDP_POLL)
#if defined(NET_TCP_HAVE_STACK) || defined(NET_UDP_HAVE_STACK)
/* Check if we are setting up or tearing down the poll */
@ -1061,7 +1061,7 @@ static int inet_poll(FAR struct socket *psock, FAR struct pollfd *fds,
{
return -ENOSYS;
}
#endif /* HAVE_TCP_POLL || !HAVE_UDP_POLL */
#endif /* NET_TCP_HAVE_STACK || !NET_UDP_HAVE_STACK */
}
/****************************************************************************

View File

@ -61,7 +61,7 @@
****************************************************************************/
#define HAVE_LOCAL_POLL 1
#define LOCAL_ACCEPT_NPOLLWAITERS 2
#define LOCAL_NPOLLWAITERS 2
/* Packet format in FIFO:
*
@ -168,10 +168,11 @@ struct local_conn_s
#ifdef HAVE_LOCAL_POLL
/* The following is a list if poll structures of threads waiting for
* socket accept events.
* socket events.
*/
struct pollfd *lc_accept_fds[LOCAL_ACCEPT_NPOLLWAITERS];
struct pollfd *lc_accept_fds[LOCAL_NPOLLWAITERS];
struct pollfd lc_inout_fds[2*LOCAL_NPOLLWAITERS];
#endif
/* Union of fields unique to SOCK_STREAM client, server, and connected

View File

@ -44,7 +44,6 @@
#include <errno.h>
#include <debug.h>
#include <nuttx/kmalloc.h>
#include <nuttx/net/net.h>
#include <nuttx/fs/fs.h>
@ -73,7 +72,7 @@ static int local_accept_pollsetup(FAR struct local_conn_s *conn,
* slot for the poll structure reference
*/
for (i = 0; i < LOCAL_ACCEPT_NPOLLWAITERS; i++)
for (i = 0; i < LOCAL_NPOLLWAITERS; i++)
{
/* Find an available slot */
@ -87,7 +86,7 @@ static int local_accept_pollsetup(FAR struct local_conn_s *conn,
}
}
if (i >= LOCAL_ACCEPT_NPOLLWAITERS)
if (i >= LOCAL_NPOLLWAITERS)
{
fds->priv = NULL;
ret = -EBUSY;
@ -143,7 +142,7 @@ void local_accept_pollnotify(FAR struct local_conn_s *conn,
#ifdef CONFIG_NET_LOCAL_STREAM
int i;
for (i = 0; i < LOCAL_ACCEPT_NPOLLWAITERS; i++)
for (i = 0; i < LOCAL_NPOLLWAITERS; i++)
{
struct pollfd *fds = conn->lc_accept_fds[i];
if (fds)
@ -215,22 +214,31 @@ int local_pollsetup(FAR struct socket *psock, FAR struct pollfd *fds)
goto pollerr;
}
/* Allocate shadow pollfds. */
/* Find shadow pollfds. */
shadowfds = kmm_zalloc(2 * sizeof(struct pollfd));
if (!shadowfds)
net_lock();
shadowfds = conn->lc_inout_fds;
while (shadowfds->fd != 0)
{
return -ENOMEM;
shadowfds += 2;
if (shadowfds >= &conn->lc_inout_fds[2*LOCAL_NPOLLWAITERS])
{
net_unlock();
return -ENOMEM;
}
}
shadowfds[0].fd = 0; /* Does not matter */
shadowfds[0].fd = 1; /* Does not matter */
shadowfds[0].sem = fds->sem;
shadowfds[0].events = fds->events & ~POLLOUT;
shadowfds[1].fd = 1; /* Does not matter */
shadowfds[1].fd = 0; /* Does not matter */
shadowfds[1].sem = fds->sem;
shadowfds[1].events = fds->events & ~POLLIN;
net_unlock();
/* Setup poll for both shadow pollfds. */
ret = file_poll(&conn->lc_infile, &shadowfds[0], true);
@ -245,7 +253,7 @@ int local_pollsetup(FAR struct socket *psock, FAR struct pollfd *fds)
if (ret < 0)
{
kmm_free(shadowfds);
shadowfds[0].fd = 0;
fds->priv = NULL;
goto pollerr;
}
@ -367,7 +375,7 @@ int local_pollteardown(FAR struct socket *psock, FAR struct pollfd *fds)
fds->revents |= shadowfds[0].revents | shadowfds[1].revents;
fds->priv = NULL;
kmm_free(shadowfds);
shadowfds[0].fd = 0;
}
break;

View File

@ -410,10 +410,6 @@ ssize_t pkt_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
}
#endif
/* Set the socket state to receiving */
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_RECV);
/* Set up the callback in the connection */
state.pr_cb = pkt_callback_alloc(dev, conn);
@ -441,10 +437,6 @@ ssize_t pkt_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
ret = -EBUSY;
}
/* Set the socket state to idle */
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE);
errout_with_state:
net_unlock();
pkt_recvfrom_uninitialize(&state);

View File

@ -191,10 +191,6 @@ ssize_t psock_pkt_send(FAR struct socket *psock, FAR const void *buf,
return -ENODEV;
}
/* Set the socket state to sending */
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_SEND);
/* Perform the send operation */
/* Initialize the state structure. This is done with the network locked
@ -249,10 +245,6 @@ ssize_t psock_pkt_send(FAR struct socket *psock, FAR const void *buf,
nxsem_destroy(&state.snd_sem);
net_unlock();
/* Set the socket state to idle */
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE);
/* Check for a errors, Errors are signalled by negative errno values
* for the send length
*/

View File

@ -854,10 +854,6 @@ ssize_t psock_6lowpan_tcp_send(FAR struct socket *psock, FAR const void *buf,
return (ssize_t)ret;
}
/* Set the socket state to sending */
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_SEND);
/* Send the TCP packets, breaking down the potential large user buffer
* into smaller packets that can be reassembled in the allocated MTU
* packet buffer.
@ -874,14 +870,9 @@ ssize_t psock_6lowpan_tcp_send(FAR struct socket *psock, FAR const void *buf,
if (ret < 0)
{
nerr("ERROR: sixlowpan_send_packet() failed: %d\n", ret);
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE);
return (ssize_t)ret;
}
/* Set the socket state to idle */
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE);
return (ssize_t)buflen;
}

View File

@ -302,10 +302,6 @@ ssize_t psock_6lowpan_udp_sendto(FAR struct socket *psock,
return (ssize_t)ret;
}
/* Set the socket state to sending */
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_SEND);
/* If routable, then call sixlowpan_send() to format and send the 6LoWPAN
* packet.
*/
@ -324,9 +320,6 @@ ssize_t psock_6lowpan_udp_sendto(FAR struct socket *psock,
nerr("ERROR: sixlowpan_send() failed: %d\n", ret);
}
/* Set the socket state to idle */
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE);
return (ssize_t)ret;
}

View File

@ -43,8 +43,8 @@ config NET_SOLINGER
bool "SO_LINGER socket option"
default n
depends on NET_TCP_WRITE_BUFFERS || NET_UDP_WRITE_BUFFERS
select TCP_NOTIFIER if NET_TCP
select UDP_NOTIFIER if NET_UDP
select NET_TCP_NOTIFIER if NET_TCP
select NET_UDP_NOTIFIER if NET_UDP
---help---
Enable or disable support for the SO_LINGER socket option. Requires
write buffer support.

View File

@ -88,8 +88,6 @@ ssize_t psock_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
int flags, FAR struct sockaddr *from,
FAR socklen_t *fromlen)
{
ssize_t ret;
/* Verify that non-NULL pointers were passed */
#ifdef CONFIG_DEBUG_FEATURES
@ -111,10 +109,6 @@ ssize_t psock_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
return -EBADF;
}
/* Set the socket state to receiving */
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_RECV);
/* Let logic specific to this address family handle the recvfrom()
* operation.
*/
@ -122,12 +116,7 @@ ssize_t psock_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
DEBUGASSERT(psock->s_sockif != NULL &&
psock->s_sockif->si_recvfrom != NULL);
ret = psock->s_sockif->si_recvfrom(psock, buf, len, flags, from, fromlen);
/* Set the socket state to idle */
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE);
return ret;
return psock->s_sockif->si_recvfrom(psock, buf, len, flags, from, fromlen);
}
/****************************************************************************

View File

@ -1,7 +1,8 @@
/****************************************************************************
* net/socket/socket.h
*
* Copyright (C) 2007-2009, 2011-2014, 2017 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2009, 2011-2014, 2017, 2019 Gregory Nutt. All rights
* reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -56,13 +57,6 @@
/* Definitions of 8-bit socket flags */
/* Bits 0-2: Socket state */
#define _SF_IDLE 0x00 /* - There is no socket activity */
#define _SF_ACCEPT 0x01 /* - Socket is waiting to accept a connection */
#define _SF_RECV 0x02 /* - Waiting for recv action to complete */
#define _SF_SEND 0x03 /* - Waiting for send action to complete */
#define _SF_MASK 0x03 /* - Mask to isolate the above actions */
#define _SF_NONBLOCK 0x08 /* Bit 3: Don't block if no data (TCP/READ only) */
#define _SF_LISTENING 0x10 /* Bit 4: SOCK_STREAM is listening */
#define _SF_BOUND 0x20 /* Bit 5: SOCK_STREAM is bound to an address */
@ -79,10 +73,6 @@
/* Macro to manage the socket state and flags */
#define _SS_SETSTATE(s,f) (((s) & ~_SF_MASK) | (f))
#define _SS_GETSTATE(s) ((s) & _SF_MASK)
#define _SS_ISBUSY(s) (_SS_GETSTATE(s) != _SF_IDLE)
#define _SS_ISNONBLOCK(s) (((s) & _SF_NONBLOCK) != 0)
#define _SS_ISLISTENING(s) (((s) & _SF_LISTENING) != 0)
#define _SS_ISBOUND(s) (((s) & _SF_BOUND) != 0)

View File

@ -55,6 +55,10 @@ config NET_TCP_CONNS
---help---
Maximum number of TCP/IP connections (all tasks)
config NET_TCP_NPOLLWAITERS
int "Number of TCP poll waiters"
default 1
config NET_TCP_RTO
int "RTO of TCP/IP connections"
default 3
@ -74,7 +78,7 @@ config NET_MAX_LISTENPORTS
---help---
Maximum number of listening TCP/IP ports (all tasks). Default: 20
config TCP_NOTIFIER
config NET_TCP_NOTIFIER
bool "Support TCP notifications"
default n
depends on SCHED_WORKQUEUE

View File

@ -52,15 +52,12 @@ ifeq ($(CONFIG_NET_SENDFILE),y)
SOCK_CSRCS += tcp_sendfile.c
endif
ifeq ($(CONFIG_NET_TCP_READAHEAD),y)
SOCK_CSRCS += tcp_netpoll.c
ifeq ($(CONFIG_TCP_NOTIFIER),y)
ifeq ($(CONFIG_NET_TCP_NOTIFIER),y)
SOCK_CSRCS += tcp_notifier.c
ifeq ($(CONFIG_NET_TCP_WRITE_BUFFERS),y)
SOCK_CSRCS += tcp_txdrain.c
endif
endif
endif
ifeq ($(CONFIG_NET_TCPPROTO_OPTIONS),y)
SOCK_CSRCS += tcp_setsockopt.c tcp_getsockopt.c
@ -71,7 +68,7 @@ endif
NET_CSRCS += tcp_conn.c tcp_seqno.c tcp_devpoll.c tcp_finddev.c tcp_timer.c
NET_CSRCS += tcp_send.c tcp_input.c tcp_appsend.c tcp_listen.c
NET_CSRCS += tcp_monitor.c tcp_callback.c tcp_backlog.c tcp_ipselect.c
NET_CSRCS += tcp_recvwindow.c
NET_CSRCS += tcp_recvwindow.c tcp_netpoll.c
# TCP write buffering

View File

@ -49,7 +49,7 @@
#include <nuttx/mm/iob.h>
#include <nuttx/net/ip.h>
#ifdef CONFIG_TCP_NOTIFIER
#ifdef CONFIG_NET_TCP_NOTIFIER
# include <nuttx/wqueue.h>
#endif
@ -61,12 +61,6 @@
#define NET_TCP_HAVE_STACK 1
/* Conditions for support TCP poll/select operations */
#ifdef CONFIG_NET_TCP_READAHEAD
# define HAVE_TCP_POLL
#endif
/* Allocate a new TCP data callback */
/* These macros allocate and free callback structures used for receiving
@ -110,6 +104,11 @@
* Public Type Definitions
****************************************************************************/
struct file; /* Forward reference */
struct sockaddr; /* Forward reference */
struct socket; /* Forward reference */
struct pollfd; /* Forward reference */
/* Representation of a TCP connection.
*
* The tcp_conn_s structure is used for identifying a connection. All
@ -124,6 +123,18 @@ struct devif_callback_s; /* Forward reference */
struct tcp_backlog_s; /* Forward reference */
struct tcp_hdr_s; /* Forward reference */
/* This is a container that holds the poll-related information */
struct tcp_poll_s
{
FAR struct socket *psock; /* Needed to handle loss of connection */
struct pollfd *fds; /* Needed to handle poll events */
FAR struct devif_callback_s *cb; /* Needed to teardown the poll */
#if defined(CONFIG_NET_TCP_WRITE_BUFFERS) && defined(CONFIG_IOB_NOTIFIER)
int16_t key; /* Needed to cancel pending notification */
#endif
};
struct tcp_conn_s
{
/* Common prologue of all connection structures. */
@ -274,6 +285,12 @@ struct tcp_conn_s
FAR void *accept_private;
int (*accept)(FAR struct tcp_conn_s *listener, FAR struct tcp_conn_s *conn);
/* The following is a list of poll structures of threads waiting for
* socket events.
*/
struct tcp_poll_s pollinfo[CONFIG_NET_TCP_NPOLLWAITERS];
};
/* This structure supports TCP write buffering */
@ -335,11 +352,6 @@ EXTERN struct net_driver_s *g_netdevices;
* Public Function Prototypes
****************************************************************************/
struct file; /* Forward reference */
struct sockaddr; /* Forward reference */
struct socket; /* Forward reference */
struct pollfd; /* Forward reference */
/****************************************************************************
* Name: tcp_initialize
*
@ -1535,9 +1547,7 @@ void tcp_wrbuffer_dump(FAR const char *msg, FAR struct tcp_wrbuffer_s *wrb,
*
****************************************************************************/
#ifdef HAVE_TCP_POLL
int tcp_pollsetup(FAR struct socket *psock, FAR struct pollfd *fds);
#endif
/****************************************************************************
* Name: tcp_pollteardown
@ -1555,9 +1565,7 @@ int tcp_pollsetup(FAR struct socket *psock, FAR struct pollfd *fds);
*
****************************************************************************/
#ifdef HAVE_TCP_POLL
int tcp_pollteardown(FAR struct socket *psock, FAR struct pollfd *fds);
#endif
/****************************************************************************
* Name: tcp_readahead_notifier_setup
@ -1586,7 +1594,7 @@ int tcp_pollteardown(FAR struct socket *psock, FAR struct pollfd *fds);
*
****************************************************************************/
#ifdef CONFIG_TCP_NOTIFIER
#ifdef CONFIG_NET_TCP_NOTIFIER
int tcp_readahead_notifier_setup(worker_t worker,
FAR struct tcp_conn_s *conn,
FAR void *arg);
@ -1619,7 +1627,7 @@ int tcp_readahead_notifier_setup(worker_t worker,
*
****************************************************************************/
#ifdef CONFIG_TCP_NOTIFIER
#ifdef CONFIG_NET_TCP_NOTIFIER
int tcp_writebuffer_notifier_setup(worker_t worker,
FAR struct tcp_conn_s *conn,
FAR void *arg);
@ -1650,7 +1658,7 @@ int tcp_writebuffer_notifier_setup(worker_t worker,
*
****************************************************************************/
#ifdef CONFIG_TCP_NOTIFIER
#ifdef CONFIG_NET_TCP_NOTIFIER
int tcp_disconnect_notifier_setup(worker_t worker,
FAR struct tcp_conn_s *conn,
FAR void *arg);
@ -1675,7 +1683,7 @@ int tcp_disconnect_notifier_setup(worker_t worker,
*
****************************************************************************/
#ifdef CONFIG_TCP_NOTIFIER
#ifdef CONFIG_NET_TCP_NOTIFIER
int tcp_notifier_teardown(int key);
#endif
@ -1700,7 +1708,7 @@ int tcp_notifier_teardown(int key);
*
****************************************************************************/
#if defined(CONFIG_NET_TCP_READAHEAD) && defined(CONFIG_TCP_NOTIFIER)
#if defined(CONFIG_NET_TCP_READAHEAD) && defined(CONFIG_NET_TCP_NOTIFIER)
void tcp_readahead_signal(FAR struct tcp_conn_s *conn);
#endif
@ -1725,7 +1733,7 @@ void tcp_readahead_signal(FAR struct tcp_conn_s *conn);
*
****************************************************************************/
#if defined(CONFIG_NET_TCP_WRITE_BUFFERS) && defined(CONFIG_TCP_NOTIFIER)
#if defined(CONFIG_NET_TCP_WRITE_BUFFERS) && defined(CONFIG_NET_TCP_NOTIFIER)
void tcp_writebuffer_signal(FAR struct tcp_conn_s *conn);
#endif
@ -1744,7 +1752,7 @@ void tcp_writebuffer_signal(FAR struct tcp_conn_s *conn);
*
****************************************************************************/
#ifdef CONFIG_TCP_NOTIFIER
#ifdef CONFIG_NET_TCP_NOTIFIER
void tcp_disconnect_signal(FAR struct tcp_conn_s *conn);
#endif
@ -1764,7 +1772,7 @@ void tcp_disconnect_signal(FAR struct tcp_conn_s *conn);
*
****************************************************************************/
#if defined(CONFIG_NET_TCP_WRITE_BUFFERS) && defined(CONFIG_TCP_NOTIFIER)
#if defined(CONFIG_NET_TCP_WRITE_BUFFERS) && defined(CONFIG_NET_TCP_NOTIFIER)
struct timespec;
int tcp_txdrain(FAR struct socket *psock,
FAR const struct timespec *abstime);

View File

@ -264,10 +264,6 @@ int psock_tcp_accept(FAR struct socket *psock, FAR struct sockaddr *addr,
else
#endif
{
/* Set the socket state to accepting */
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_ACCEPT);
/* Perform the TCP accept operation */
/* Initialize the state structure. This is done with the network
@ -306,10 +302,6 @@ int psock_tcp_accept(FAR struct socket *psock, FAR struct sockaddr *addr,
nxsem_destroy(&state. acpt_sem);
/* Set the socket state to idle */
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE);
/* Check for a errors. Errors are signalled by negative errno values
* for the send length.
*/

View File

@ -145,7 +145,7 @@ tcp_data_event(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
uint16_t tcp_callback(FAR struct net_driver_s *dev,
FAR struct tcp_conn_s *conn, uint16_t flags)
{
#ifdef CONFIG_TCP_NOTIFIER
#ifdef CONFIG_NET_TCP_NOTIFIER
uint16_t orig = flags;
#endif
@ -203,7 +203,7 @@ uint16_t tcp_callback(FAR struct net_driver_s *dev,
flags = devif_conn_event(dev, conn, flags, conn->connevents);
}
#ifdef CONFIG_TCP_NOTIFIER
#ifdef CONFIG_NET_TCP_NOTIFIER
/* Provide notification(s) if the TCP connection has been lost. */
if ((orig & TCP_DISCONN_EVENTS) != 0)
@ -287,7 +287,7 @@ uint16_t tcp_datahandler(FAR struct tcp_conn_s *conn, FAR uint8_t *buffer,
return 0;
}
#ifdef CONFIG_TCP_NOTIFIER
#ifdef CONFIG_NET_TCP_NOTIFIER
/* Provide notification(s) that additional TCP read-ahead data is
* available.
*/

View File

@ -41,13 +41,12 @@
#include <nuttx/config.h>
#include <stdint.h>
#include <assert.h>
#include <poll.h>
#include <debug.h>
#include <nuttx/kmalloc.h>
#include <nuttx/wqueue.h>
#include <nuttx/mm/iob.h>
#include <nuttx/net/net.h>
#include <nuttx/semaphore.h>
#include "devif/devif.h"
#include "netdev/netdev.h"
@ -55,24 +54,6 @@
#include "inet/inet.h"
#include "tcp/tcp.h"
#ifdef HAVE_TCP_POLL
/****************************************************************************
* Private Types
****************************************************************************/
/* This is an allocated container that holds the poll-related information */
struct tcp_poll_s
{
FAR struct socket *psock; /* Needed to handle loss of connection */
struct pollfd *fds; /* Needed to handle poll events */
FAR struct devif_callback_s *cb; /* Needed to teardown the poll */
#if defined(CONFIG_NET_TCP_WRITE_BUFFERS) && defined(CONFIG_IOB_NOTIFIER)
int16_t key; /* Needed to cancel pending notification */
#endif
};
/****************************************************************************
* Private Functions
****************************************************************************/
@ -172,19 +153,11 @@ static uint16_t tcp_poll_eventhandler(FAR struct net_driver_s *dev,
#if defined(CONFIG_NET_TCP_WRITE_BUFFERS) && defined(CONFIG_IOB_NOTIFIER)
static inline void tcp_iob_work(FAR void *arg)
{
FAR struct work_notifier_entry_s *entry;
FAR struct work_notifier_s *ninfo;
FAR struct tcp_poll_s *pinfo;
FAR struct socket *psock;
FAR struct pollfd *fds;
entry = (FAR struct work_notifier_entry_s *)arg;
DEBUGASSERT(entry != NULL);
ninfo = &entry->info;
DEBUGASSERT(ninfo->arg != NULL);
pinfo = (FAR struct tcp_poll_s *)ninfo->arg;
pinfo = (FAR struct tcp_poll_s *)arg;
DEBUGASSERT(pinfo->psock != NULL && pinfo->fds != NULL);
psock = pinfo->psock;
@ -231,12 +204,6 @@ static inline void tcp_iob_work(FAR void *arg)
pinfo->key = iob_notifier_setup(LPWORK, tcp_iob_work, pinfo);
}
}
/* Protocol for the use of the IOB notifier is that we free the argument
* after the notification has been processed.
*/
kmm_free(arg);
}
#endif
@ -276,18 +243,22 @@ int tcp_pollsetup(FAR struct socket *psock, FAR struct pollfd *fds)
}
#endif
/* Allocate a container to hold the poll information */
info = (FAR struct tcp_poll_s *)kmm_malloc(sizeof(struct tcp_poll_s));
if (!info)
{
return -ENOMEM;
}
/* Some of the following must be atomic */
net_lock();
/* Find a container to hold the poll information */
info = conn->pollinfo;
while (info->psock != NULL)
{
if (++info >= &conn->pollinfo[CONFIG_NET_TCP_NPOLLWAITERS])
{
ret = -ENOMEM;
goto errout_with_lock;
}
}
/* Allocate a TCP/IP callback structure */
cb = tcp_callback_alloc(conn);
@ -331,14 +302,14 @@ int tcp_pollsetup(FAR struct socket *psock, FAR struct pollfd *fds)
fds->priv = (FAR void *)info;
#ifdef CONFIG_NET_TCPBACKLOG
#ifdef CONFIG_NET_TCP_READAHEAD
/* Check for read data or backlogged connection availability now */
if (!IOB_QEMPTY(&conn->readahead) || tcp_backlogavailable(conn))
#else
/* Check for read data availability now */
/* Check for backlogged connection now */
if (!IOB_QEMPTY(&conn->readahead))
if (tcp_backlogavailable(conn))
#endif
{
/* Normal data may be read without blocking. */
@ -423,11 +394,7 @@ int tcp_pollsetup(FAR struct socket *psock, FAR struct pollfd *fds)
}
#endif
net_unlock();
return OK;
errout_with_lock:
kmm_free(info);
net_unlock();
return ret;
}
@ -481,9 +448,7 @@ int tcp_pollteardown(FAR struct socket *psock, FAR struct pollfd *fds)
/* Release the callback */
net_lock();
tcp_callback_free(conn, info->cb);
net_unlock();
/* Release the poll/select data slot */
@ -491,10 +456,8 @@ int tcp_pollteardown(FAR struct socket *psock, FAR struct pollfd *fds)
/* Then free the poll info container */
kmm_free(info);
info->psock = NULL;
}
return OK;
}
#endif /* HAVE_TCP_POLL */

View File

@ -49,7 +49,7 @@
#include "tcp/tcp.h"
#ifdef CONFIG_TCP_NOTIFIER
#ifdef CONFIG_NET_TCP_NOTIFIER
/****************************************************************************
* Public Functions
@ -330,4 +330,4 @@ void tcp_disconnect_signal(FAR struct tcp_conn_s *conn)
return work_notifier_signal(WORK_TCP_DISCONNECT, conn);
}
#endif /* CONFIG_TCP_NOTIFIER */
#endif /* CONFIG_NET_TCP_NOTIFIER */

View File

@ -1,7 +1,7 @@
/****************************************************************************
* net/tcp/tcp_send_buffered.c
*
* Copyright (C) 2007-2014, 2016-2018 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2014, 2016-2019 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
* Jason Jiang <jasonj@live.cn>
*
@ -84,6 +84,7 @@
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* If both IPv4 and IPv6 support are both enabled, then we will need to build
* in some additional domain selection support.
*/
@ -173,7 +174,7 @@ static void psock_insert_segment(FAR struct tcp_wrbuffer_s *wrb,
*
****************************************************************************/
#ifdef CONFIG_TCP_NOTIFIER
#ifdef CONFIG_NET_TCP_NOTIFIER
static void psock_writebuffer_notify(FAR struct tcp_conn_s *conn)
{
/* Check if all write buffers have been sent and ACKed */
@ -994,10 +995,6 @@ ssize_t psock_tcp_send(FAR struct socket *psock, FAR const void *buf,
BUF_DUMP("psock_tcp_send", buf, len);
/* Set the socket state to sending */
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_SEND);
if (len > 0)
{
/* Allocate a write buffer. Careful, the network will be momentarily
@ -1124,10 +1121,6 @@ ssize_t psock_tcp_send(FAR struct socket *psock, FAR const void *buf,
net_unlock();
}
/* Set the socket state to idle */
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE);
/* Check for errors. Errors are signaled by negative errno values
* for the send length
*/

View File

@ -1,7 +1,8 @@
/****************************************************************************
* net/tcp/tcp_send_unbuffered.c
*
* Copyright (C) 2007-2014, 2016-2017 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2014, 2016-2017, 2019 Gregory Nutt. All rights
* reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -73,6 +74,7 @@
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* If both IPv4 and IPv6 support are both enabled, then we will need to build
* in some additional domain selection support.
*/
@ -707,10 +709,6 @@ ssize_t psock_tcp_send(FAR struct socket *psock,
}
#endif /* CONFIG_NET_ARP_SEND || CONFIG_NET_ICMPv6_NEIGHBOR */
/* Set the socket state to sending */
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_SEND);
/* Perform the TCP send operation */
/* Initialize the state structure. This is done with the network
@ -780,10 +778,6 @@ ssize_t psock_tcp_send(FAR struct socket *psock,
nxsem_destroy(&state.snd_sem);
net_unlock();
/* Set the socket state to idle */
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE);
/* Check for a errors. Errors are signalled by negative errno values
* for the send length
*/

View File

@ -562,10 +562,6 @@ ssize_t tcp_sendfile(FAR struct socket *psock, FAR struct file *infile,
}
#endif /* CONFIG_NET_ARP_SEND || CONFIG_NET_ICMPv6_NEIGHBOR */
/* Set the socket state to sending */
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_SEND);
/* Initialize the state structure. This is done with the network
* locked because we don't want anything to happen until we are
* ready.
@ -643,10 +639,6 @@ ssize_t tcp_sendfile(FAR struct socket *psock, FAR struct file *infile,
}
while (state.snd_sent >= 0 && state.snd_acked < state.snd_flen);
/* Set the socket state to idle */
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE);
tcp_callback_free(conn, state.snd_ackcb);
errout_datacb:

View File

@ -46,13 +46,9 @@
#include <assert.h>
#include <errno.h>
#include <nuttx/kmalloc.h>
#include <nuttx/wqueue.h>
#include <nuttx/net/net.h>
#include "tcp/tcp.h"
#if defined(CONFIG_NET_TCP_WRITE_BUFFERS) && defined(CONFIG_TCP_NOTIFIER)
#if defined(CONFIG_NET_TCP_WRITE_BUFFERS) && defined(CONFIG_NET_TCP_NOTIFIER)
/****************************************************************************
* Private Functions
@ -74,25 +70,13 @@
static void txdrain_worker(FAR void *arg)
{
/* The entire notifier entry is passed to us. That is because we are
* responsible for disposing of the entry via kmm_free() when we are
* finished with it.
*/
FAR sem_t *waitsem = (FAR sem_t *)arg;
FAR struct work_notifier_entry_s *notifier =
(FAR struct work_notifier_entry_s *)arg;
FAR sem_t *waitsem;
DEBUGASSERT(notifier != NULL && notifier->info.arg != NULL);
waitsem = (FAR sem_t *)notifier->info.arg;
/* Free the notifier entry */
kmm_free(notifier);
DEBUGASSERT(waitsem != NULL);
/* Then just post the semaphore, waking up tcp_txdrain() */
sem_post(waitsem);
nxsem_post(waitsem);
}
/****************************************************************************
@ -130,6 +114,7 @@ int tcp_txdrain(FAR struct socket *psock,
/* Initialize the wait semaphore */
nxsem_init(&waitsem, 0, 0);
nxsem_setprotocol(&waitsem, SEM_PRIO_NONE);
/* The following needs to be done with the network stable */
@ -195,4 +180,4 @@ int tcp_txdrain(FAR struct socket *psock,
return ret;
}
#endif /* CONFIG_NET_TCP_WRITE_BUFFERS && CONFIG_TCP_NOTIFIER */
#endif /* CONFIG_NET_TCP_WRITE_BUFFERS && CONFIG_NET_TCP_NOTIFIER */

View File

@ -119,6 +119,7 @@ void tcp_wrbuffer_initialize(void)
}
nxsem_init(&g_wrbuffer.sem, 0, CONFIG_NET_TCP_NWRBCHAINS);
nxsem_setprotocol(&g_wrbuffer.sem, SEM_PRIO_NONE);
}
/****************************************************************************
@ -149,7 +150,7 @@ FAR struct tcp_wrbuffer_s *tcp_wrbuffer_alloc(void)
* buffer
*/
DEBUGVERIFY(net_lockedwait(&g_wrbuffer.sem)); /* TODO: Handle EINTR. */
while (net_lockedwait(&g_wrbuffer.sem) < 0);
/* Now, we are guaranteed to have a write buffer structure reserved
* for us in the free list.
@ -207,11 +208,7 @@ FAR struct tcp_wrbuffer_s *tcp_wrbuffer_tryalloc(void)
* buffer
*/
if (tcp_wrbuffer_test() == OK)
{
DEBUGVERIFY(net_lockedwait(&g_wrbuffer.sem));
}
else
if (nxsem_trywait(&g_wrbuffer.sem) != OK)
{
return NULL;
}

View File

@ -55,6 +55,10 @@ config NET_UDP_CONNS
---help---
The maximum amount of open concurrent UDP sockets
config NET_UDP_NPOLLWAITERS
int "Number of UDP poll waiters"
default 1
config NET_UDP_READAHEAD
bool "Enable UDP/IP read-ahead buffering"
default y
@ -109,15 +113,15 @@ config NET_UDP_WRBUFFER_DUMP
endif # NET_UDP_WRITE_BUFFERS
config UDP_NOTIFIER
config NET_UDP_NOTIFIER
bool "Support UDP read-ahead notifications"
default n
depends on SCHED_WORKQUEUE
select WQUEUE_NOTIFIER
---help---
Enable building of UDP read-ahead notifier logic that will execute a
worker function on the high priority work queue when read-ahead data
is available. This is is a general purpose notifier, but was
worker function on the low priority work queue when read-ahead data
is available. This is a general purpose notifier, but was
developed specifically to support poll() logic where the poll must
wait for read-ahead data to become available.

View File

@ -52,11 +52,8 @@ else
SOCK_CSRCS += udp_psock_sendto_unbuffered.c
endif
ifeq ($(CONFIG_NET_UDP_READAHEAD),y)
SOCK_CSRCS += udp_netpoll.c
ifeq ($(CONFIG_UDP_NOTIFIER),y)
ifeq ($(CONFIG_NET_UDP_NOTIFIER),y)
SOCK_CSRCS += udp_notifier.c
endif
ifeq ($(CONFIG_NET_UDP_WRITE_BUFFERS),y)
SOCK_CSRCS += udp_txdrain.c
endif
@ -65,7 +62,7 @@ endif
# Transport layer
NET_CSRCS += udp_conn.c udp_devpoll.c udp_send.c udp_input.c udp_finddev.c
NET_CSRCS += udp_callback.c udp_ipselect.c
NET_CSRCS += udp_callback.c udp_ipselect.c udp_netpoll.c
# UDP write buffering

View File

@ -53,7 +53,7 @@
# include <nuttx/mm/iob.h>
#endif
#ifdef CONFIG_UDP_NOTIFIER
#ifdef CONFIG_NET_UDP_NOTIFIER
# include <nuttx/wqueue.h>
#endif
@ -65,12 +65,6 @@
#define NET_UDP_HAVE_STACK 1
/* Conditions for support UDP poll/select operations */
#ifdef CONFIG_NET_UDP_READAHEAD
# define HAVE_UDP_POLL
#endif
#ifdef CONFIG_NET_UDP_WRITE_BUFFERS
/* UDP write buffer dump macros */
@ -99,11 +93,29 @@
* Public Type Definitions
****************************************************************************/
struct sockaddr; /* Forward reference */
struct socket; /* Forward reference */
struct net_driver_s; /* Forward reference */
struct pollfd; /* Forward reference */
/* Representation of a UDP connection */
struct devif_callback_s; /* Forward reference */
struct udp_hdr_s; /* Forward reference */
/* This is a container that holds the poll-related information */
struct udp_poll_s
{
FAR struct socket *psock; /* Needed to handle loss of connection */
FAR struct net_driver_s *dev; /* Needed to free the callback structure */
struct pollfd *fds; /* Needed to handle poll events */
FAR struct devif_callback_s *cb; /* Needed to teardown the poll */
#if defined(CONFIG_NET_UDP_WRITE_BUFFERS) && defined(CONFIG_IOB_NOTIFIER)
int16_t key; /* Needed to cancel pending notification */
#endif
};
struct udp_conn_s
{
/* Common prologue of all connection structures. */
@ -151,6 +163,12 @@ struct udp_conn_s
sq_queue_t write_q; /* Write buffering for UDP packets */
FAR struct net_driver_s *dev; /* Last device */
#endif
/* The following is a list of poll structures of threads waiting for
* socket events.
*/
struct udp_poll_s pollinfo[CONFIG_NET_UDP_NPOLLWAITERS];
};
/* This structure supports UDP write buffering. It is simply a container
@ -185,11 +203,6 @@ extern "C"
* Public Function Prototypes
****************************************************************************/
struct sockaddr; /* Forward reference */
struct socket; /* Forward reference */
struct net_driver_s; /* Forward reference */
struct pollfd; /* Forward reference */
/****************************************************************************
* Name: udp_initialize
*
@ -653,9 +666,7 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf,
*
****************************************************************************/
#ifdef HAVE_UDP_POLL
int udp_pollsetup(FAR struct socket *psock, FAR struct pollfd *fds);
#endif
/****************************************************************************
* Name: udp_pollteardown
@ -673,9 +684,7 @@ int udp_pollsetup(FAR struct socket *psock, FAR struct pollfd *fds);
*
****************************************************************************/
#ifdef HAVE_UDP_POLL
int udp_pollteardown(FAR struct socket *psock, FAR struct pollfd *fds);
#endif
/****************************************************************************
* Name: udp_readahead_notifier_setup
@ -703,7 +712,7 @@ int udp_pollteardown(FAR struct socket *psock, FAR struct pollfd *fds);
*
****************************************************************************/
#ifdef CONFIG_UDP_NOTIFIER
#ifdef CONFIG_NET_UDP_NOTIFIER
int udp_readahead_notifier_setup(worker_t worker,
FAR struct udp_conn_s *conn,
FAR void *arg);
@ -735,7 +744,7 @@ int udp_readahead_notifier_setup(worker_t worker,
*
****************************************************************************/
#ifdef CONFIG_UDP_NOTIFIER
#ifdef CONFIG_NET_UDP_NOTIFIER
int udp_writebuffer_notifier_setup(worker_t worker,
FAR struct udp_conn_s *conn,
FAR void *arg);
@ -760,7 +769,7 @@ int udp_writebuffer_notifier_setup(worker_t worker,
*
****************************************************************************/
#ifdef CONFIG_UDP_NOTIFIER
#ifdef CONFIG_NET_UDP_NOTIFIER
int udp_notifier_teardown(int key);
#endif
@ -784,7 +793,7 @@ int udp_notifier_teardown(int key);
*
****************************************************************************/
#if defined(CONFIG_NET_UDP_READAHEAD) && defined(CONFIG_UDP_NOTIFIER)
#if defined(CONFIG_NET_UDP_READAHEAD) && defined(CONFIG_NET_UDP_NOTIFIER)
void udp_readahead_signal(FAR struct udp_conn_s *conn);
#endif
@ -809,7 +818,7 @@ void udp_readahead_signal(FAR struct udp_conn_s *conn);
*
****************************************************************************/
#if defined(CONFIG_NET_UDP_WRITE_BUFFERS) && defined(CONFIG_UDP_NOTIFIER)
#if defined(CONFIG_NET_UDP_WRITE_BUFFERS) && defined(CONFIG_NET_UDP_NOTIFIER)
void udp_writebuffer_signal(FAR struct udp_conn_s *conn);
#endif
@ -829,7 +838,7 @@ void udp_writebuffer_signal(FAR struct udp_conn_s *conn);
*
****************************************************************************/
#if defined(CONFIG_NET_UDP_WRITE_BUFFERS) && defined(CONFIG_UDP_NOTIFIER)
#if defined(CONFIG_NET_UDP_WRITE_BUFFERS) && defined(CONFIG_NET_UDP_NOTIFIER)
struct timespec;
int udp_txdrain(FAR struct socket *psock,
FAR const struct timespec *abstime);

View File

@ -234,7 +234,7 @@ static uint16_t udp_datahandler(FAR struct net_driver_s *dev,
return 0;
}
#ifdef CONFIG_UDP_NOTIFIER
#ifdef CONFIG_NET_UDP_NOTIFIER
/* Provided notification(s) that additional UDP read-ahead data is
* available.
*/

View File

@ -41,38 +41,18 @@
#include <nuttx/config.h>
#include <stdint.h>
#include <assert.h>
#include <poll.h>
#include <debug.h>
#include <nuttx/kmalloc.h>
#include <nuttx/wqueue.h>
#include <nuttx/mm/iob.h>
#include <nuttx/net/net.h>
#include <nuttx/semaphore.h>
#include "devif/devif.h"
#include "netdev/netdev.h"
#include "socket/socket.h"
#include "udp/udp.h"
#ifdef HAVE_UDP_POLL
/****************************************************************************
* Private Types
****************************************************************************/
/* This is an allocated container that holds the poll-related information */
struct udp_poll_s
{
FAR struct socket *psock; /* Needed to handle loss of connection */
FAR struct net_driver_s *dev; /* Needed to free the callback structure */
struct pollfd *fds; /* Needed to handle poll events */
FAR struct devif_callback_s *cb; /* Needed to teardown the poll */
#if defined(CONFIG_NET_UDP_WRITE_BUFFERS) && defined(CONFIG_IOB_NOTIFIER)
int16_t key; /* Needed to cancel pending notification */
#endif
};
/****************************************************************************
* Private Functions
****************************************************************************/
@ -163,19 +143,11 @@ static uint16_t udp_poll_eventhandler(FAR struct net_driver_s *dev,
#if defined(CONFIG_NET_UDP_WRITE_BUFFERS) && defined(CONFIG_IOB_NOTIFIER)
static inline void udp_iob_work(FAR void *arg)
{
FAR struct work_notifier_entry_s *entry;
FAR struct work_notifier_s *ninfo;
FAR struct udp_poll_s *pinfo;
FAR struct socket *psock;
FAR struct pollfd *fds;
entry = (FAR struct work_notifier_entry_s *)arg;
DEBUGASSERT(entry != NULL);
ninfo = &entry->info;
DEBUGASSERT(ninfo->arg != NULL);
pinfo = (FAR struct udp_poll_s *)ninfo->arg;
pinfo = (FAR struct udp_poll_s *)arg;
DEBUGASSERT(pinfo->psock != NULL && pinfo->fds != NULL);
psock = pinfo->psock;
@ -204,12 +176,6 @@ static inline void udp_iob_work(FAR void *arg)
pinfo->key = iob_notifier_setup(LPWORK, udp_iob_work, pinfo);
}
}
/* Protocol for the use of the IOB notifier is that we free the argument
* after the notification has been processed.
*/
kmm_free(arg);
}
#endif
@ -249,18 +215,22 @@ int udp_pollsetup(FAR struct socket *psock, FAR struct pollfd *fds)
}
#endif
/* Allocate a container to hold the poll information */
info = (FAR struct udp_poll_s *)kmm_malloc(sizeof(struct udp_poll_s));
if (!info)
{
return -ENOMEM;
}
/* Some of the following must be atomic */
net_lock();
/* Find a container to hold the poll information */
info = conn->pollinfo;
while (info->psock != NULL)
{
if (++info >= &conn->pollinfo[CONFIG_NET_UDP_NPOLLWAITERS])
{
ret = -ENOMEM;
goto errout_with_lock;
}
}
/* Get the device that will provide the provide the NETDEV_DOWN event.
* NOTE: in the event that the local socket is bound to INADDR_ANY, the
* dev value will be zero and there will be no NETDEV_DOWN notifications.
@ -311,6 +281,7 @@ int udp_pollsetup(FAR struct socket *psock, FAR struct pollfd *fds)
fds->priv = (FAR void *)info;
#ifdef CONFIG_NET_UDP_READAHEAD
/* Check for read data availability now */
if (!IOB_QEMPTY(&conn->readahead))
@ -319,6 +290,7 @@ int udp_pollsetup(FAR struct socket *psock, FAR struct pollfd *fds)
fds->revents |= (POLLRDNORM & fds->events);
}
#endif
if (psock_udp_cansend(psock) >= 0)
{
@ -350,11 +322,7 @@ int udp_pollsetup(FAR struct socket *psock, FAR struct pollfd *fds)
}
#endif
net_unlock();
return OK;
errout_with_lock:
kmm_free(info);
net_unlock();
return ret;
}
@ -408,9 +376,7 @@ int udp_pollteardown(FAR struct socket *psock, FAR struct pollfd *fds)
/* Release the callback */
net_lock();
udp_callback_free(info->dev, conn, info->cb);
net_unlock();
/* Release the poll/select data slot */
@ -418,10 +384,8 @@ int udp_pollteardown(FAR struct socket *psock, FAR struct pollfd *fds)
/* Then free the poll info container */
kmm_free(info);
info->psock = NULL;
}
return OK;
}
#endif /* !HAVE_UDP_POLL */

View File

@ -47,7 +47,7 @@
#include "udp/udp.h"
#ifdef CONFIG_UDP_NOTIFIER
#ifdef CONFIG_NET_UDP_NOTIFIER
/****************************************************************************
* Public Functions
@ -254,4 +254,4 @@ void udp_writebuffer_signal(FAR struct udp_conn_s *conn)
}
#endif
#endif /* CONFIG_UDP_NOTIFIER */
#endif /* CONFIG_NET_UDP_NOTIFIER */

View File

@ -80,6 +80,7 @@
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* If both IPv4 and IPv6 support are both enabled, then we will need to build
* in some additional domain selection support.
*/
@ -162,7 +163,7 @@ static void sendto_writebuffer_release(FAR struct socket *psock,
psock->s_sndcb->event = NULL;
wrb = NULL;
#ifdef CONFIG_UDP_NOTIFIER
#ifdef CONFIG_NET_UDP_NOTIFIER
/* Notify any waiters that the write buffers have been drained. */
udp_writebuffer_signal(conn);
@ -694,10 +695,6 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf,
BUF_DUMP("psock_udp_send", buf, len);
/* Set the socket state to sending */
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_SEND);
if (len > 0)
{
/* Allocate a write buffer. Careful, the network will be momentarily
@ -825,10 +822,6 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf,
net_unlock();
}
/* Set the socket state to idle */
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE);
/* Return the number of bytes that will be sent */
return len;

View File

@ -63,6 +63,7 @@
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* If both IPv4 and IPv6 support are both enabled, then we will need to build
* in some additional domain selection support.
*/
@ -458,10 +459,6 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf,
}
#endif /* CONFIG_NET_ARP_SEND || CONFIG_NET_ICMPv6_NEIGHBOR */
/* Set the socket state to sending */
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_SEND);
/* Initialize the state structure. This is done with the network
* locked because we don't want anything to happen until we are
* ready.
@ -566,10 +563,6 @@ errout_with_lock:
nxsem_destroy(&state.st_sem);
/* Set the socket state back to idle */
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE);
/* Unlock the network and return the result of the sendto() operation */
net_unlock();

View File

@ -46,13 +46,9 @@
#include <assert.h>
#include <errno.h>
#include <nuttx/wqueue.h>
#include <nuttx/kmalloc.h>
#include <nuttx/net/net.h>
#include "udp/udp.h"
#if defined(CONFIG_NET_UDP_WRITE_BUFFERS) && defined(CONFIG_UDP_NOTIFIER)
#if defined(CONFIG_NET_UDP_WRITE_BUFFERS) && defined(CONFIG_NET_UDP_NOTIFIER)
/****************************************************************************
* Private Functions
@ -74,25 +70,13 @@
static void txdrain_worker(FAR void *arg)
{
/* The entire notifier entry is passed to us. That is because we are
* responsible for disposing of the entry via kmm_free() when we are
* finished with it.
*/
FAR sem_t *waitsem = (FAR sem_t *)arg;
FAR struct work_notifier_entry_s *notifier =
(FAR struct work_notifier_entry_s *)arg;
FAR sem_t *waitsem;
DEBUGASSERT(notifier != NULL && notifier->info.arg != NULL);
waitsem = (FAR sem_t *)notifier->info.arg;
/* Free the notifier entry */
kmm_free(notifier);
DEBUGASSERT(waitsem != NULL);
/* Then just post the semaphore, waking up tcp_txdrain() */
sem_post(waitsem);
nxsem_post(waitsem);
}
/****************************************************************************
@ -130,6 +114,7 @@ int udp_txdrain(FAR struct socket *psock,
/* Initialize the wait semaphore */
nxsem_init(&waitsem, 0, 0);
nxsem_setprotocol(&waitsem, SEM_PRIO_NONE);
/* The following needs to be done with the network stable */
@ -160,4 +145,4 @@ int udp_txdrain(FAR struct socket *psock,
return ret;
}
#endif /* CONFIG_NET_UDP_WRITE_BUFFERS && CONFIG_UDP_NOTIFIER */
#endif /* CONFIG_NET_UDP_WRITE_BUFFERS && CONFIG_NET_UDP_NOTIFIER */

View File

@ -116,6 +116,7 @@ void udp_wrbuffer_initialize(void)
}
nxsem_init(&g_wrbuffer.sem, 0, CONFIG_NET_UDP_NWRBCHAINS);
nxsem_setprotocol(&g_wrbuffer.sem, SEM_PRIO_NONE);
}
/****************************************************************************
@ -146,7 +147,7 @@ FAR struct udp_wrbuffer_s *udp_wrbuffer_alloc(void)
* buffer
*/
DEBUGVERIFY(net_lockedwait(&g_wrbuffer.sem)); /* TODO: Handle EINTR. */
while (net_lockedwait(&g_wrbuffer.sem) < 0);
/* Now, we are guaranteed to have a write buffer structure reserved
* for us in the free list.

View File

@ -23,6 +23,10 @@ config NET_USRSOCK_CONNS
Note: Usrsock daemon can impose additional restrictions for
maximum number of concurrent connections supported.
config NET_USRSOCK_NPOLLWAITERS
int "Number of usrsock poll waiters"
default 1
config NET_USRSOCK_NO_INET
bool "Disable PF_INET for usrsock"
default n

View File

@ -86,6 +86,13 @@ enum usrsock_conn_state_e
USRSOCK_CONN_STATE_CONNECTING,
};
struct usrsock_poll_s
{
FAR struct socket *psock; /* Needed to handle loss of connection */
struct pollfd *fds; /* Needed to handle poll events */
FAR struct devif_callback_s *cb; /* Needed to teardown the poll */
};
struct usrsock_conn_s
{
/* Common prologue of all connection structures. */
@ -126,6 +133,12 @@ struct usrsock_conn_s
size_t pos; /* Writer position on input buffer */
} datain;
} resp;
/* The following is a list of poll structures of threads waiting for
* socket events.
*/
struct usrsock_poll_s pollinfo[CONFIG_NET_USRSOCK_NPOLLWAITERS];
};
struct usrsock_reqstate_s

View File

@ -53,21 +53,9 @@
#include <nuttx/semaphore.h>
#include <nuttx/net/net.h>
#include <nuttx/net/usrsock.h>
#include <nuttx/kmalloc.h>
#include "usrsock/usrsock.h"
/****************************************************************************
* Private Data
****************************************************************************/
struct usrsock_poll_s
{
FAR struct socket *psock; /* Needed to handle loss of connection */
struct pollfd *fds; /* Needed to handle poll events */
FAR struct devif_callback_s *cb; /* Needed to teardown the poll */
};
/****************************************************************************
* Private Functions
****************************************************************************/
@ -182,24 +170,26 @@ static int usrsock_pollsetup(FAR struct socket *psock, FAR struct pollfd *fds)
}
#endif
/* Allocate a container to hold the poll information */
info = (FAR struct usrsock_poll_s *)
kmm_malloc(sizeof(struct usrsock_poll_s));
if (!info)
{
return -ENOMEM;
}
net_lock();
/* Find a container to hold the poll information */
info = conn->pollinfo;
while (info->psock != NULL)
{
if (++info >= &conn->pollinfo[CONFIG_NET_USRSOCK_NPOLLWAITERS])
{
ret = -ENOMEM;
goto errout_unlock;
}
}
/* Allocate a usrsock callback structure */
cb = devif_callback_alloc(NULL, &conn->list);
if (cb == NULL)
{
ret = -EBUSY;
kmm_free(info); /* fds->priv not set, so we need to free info here. */
goto errout_unlock;
}
@ -338,9 +328,7 @@ static int usrsock_pollteardown(FAR struct socket *psock,
{
/* Release the callback */
net_lock();
devif_conn_callback_free(NULL, info->cb, &conn->list);
net_unlock();
/* Release the poll/select data slot */
@ -348,7 +336,7 @@ static int usrsock_pollteardown(FAR struct socket *psock,
/* Then free the poll info container */
kmm_free(info);
info->psock = NULL;
}
return OK;

View File

@ -55,10 +55,42 @@
#ifdef CONFIG_WQUEUE_NOTIFIER
/****************************************************************************
* Private Types
****************************************************************************/
/* This structure describes one notification list entry. It is cast-
* compatible with struct work_notifier_s. This structure is an allocated
* container for the user notification data. It is allocated because it
* must persist until the work is executed.
*/
struct work_notifier_entry_s
{
/* This must appear at the beginning of the structure. A reference to
* the struct work_notifier_entry_s instance must be cast-compatible with
* struct dq_entry_s.
*/
struct work_s work; /* Used for scheduling the work */
/* User notification information */
struct work_notifier_s info; /* The notification info */
/* Additional payload needed to manage the notification */
int16_t key; /* Unique ID for the notification */
};
/****************************************************************************
* Private Data
****************************************************************************/
/* This is a doubly linked list of free notifications. */
static dq_queue_t g_notifier_free;
/* This is a doubly linked list of pending notifications. When an event
* occurs available, *all* of the waiters for that event in this list will
* be notified and the entry will be freed. If there are multiple waiters
@ -146,6 +178,30 @@ static int16_t work_notifier_key(void)
return key;
}
/****************************************************************************
* Name: work_notifier_worker
*
* Description:
* Forward to the real worker and free the notification.
*
****************************************************************************/
static void work_notifier_worker(FAR void *arg)
{
FAR struct work_notifier_entry_s *notifier =
(FAR struct work_notifier_entry_s *)arg;
/* Forward to the real worker */
notifier->info.worker(notifier->info.arg);
/* Put the notification to the free list */
while (nxsem_wait(&g_notifier_sem) < 0);
dq_addlast((FAR dq_entry_t *)notifier, &g_notifier_free);
nxsem_post(&g_notifier_sem);
}
/****************************************************************************
* Public Functions
****************************************************************************/
@ -185,9 +241,16 @@ int work_notifier_setup(FAR struct work_notifier_s *info)
return ret;
}
/* Allocate a new notification entry */
/* Try to get the entry from the free list */
notifier = (FAR struct work_notifier_entry_s *)dq_remfirst(&g_notifier_free);
if (notifier == NULL)
{
/* Allocate a new notification entry */
notifier = kmm_malloc(sizeof(struct work_notifier_entry_s));
}
notifier = kmm_malloc(sizeof(struct work_notifier_entry_s));
if (notifier == NULL)
{
ret = -ENOMEM;
@ -269,9 +332,9 @@ int work_notifier_teardown(int key)
dq_rem((FAR dq_entry_t *)notifier, &g_notifier_pending);
/* Free the notification */
/* Put the notification to the free list */
kmm_free(notifier);
dq_addlast((FAR dq_entry_t *)notifier, &g_notifier_free);
ret = OK;
}
@ -359,8 +422,8 @@ void work_notifier_signal(enum work_evtype_e evtype,
* responsible for freeing the allocated memory.
*/
(void)work_queue(info->qid, &notifier->work, info->worker,
entry, 0);
(void)work_queue(info->qid, &notifier->work,
work_notifier_worker, entry, 0);
}
}