mirror of
https://github.com/apache/nuttx.git
synced 2026-05-22 05:42:05 +08:00
net/udp: remove net_lock
protect UDP resources through netdev_lock, conn_lock, and udp_list_lock. Signed-off-by: zhanghongyu <zhanghongyu@xiaomi.com>
This commit is contained in:
@@ -93,11 +93,10 @@ static void devif_callback_free(FAR struct net_driver_s *dev,
|
||||
|
||||
if (cb)
|
||||
{
|
||||
net_lock();
|
||||
|
||||
#ifdef CONFIG_DEBUG_FEATURES
|
||||
/* Check for double freed callbacks */
|
||||
|
||||
NET_BUFPOOL_LOCK(g_cbprealloc);
|
||||
curr = (FAR struct devif_callback_s *)g_cbprealloc.freebuffers.head;
|
||||
|
||||
while (curr != NULL)
|
||||
@@ -105,6 +104,8 @@ static void devif_callback_free(FAR struct net_driver_s *dev,
|
||||
DEBUGASSERT(cb != curr);
|
||||
curr = curr->nxtconn;
|
||||
}
|
||||
|
||||
NET_BUFPOOL_UNLOCK(g_cbprealloc);
|
||||
#endif
|
||||
|
||||
/* Remove the callback structure from the data notification list if
|
||||
@@ -164,7 +165,6 @@ static void devif_callback_free(FAR struct net_driver_s *dev,
|
||||
if (cb->free_flags & DEVIF_CB_DONT_FREE)
|
||||
{
|
||||
cb->free_flags |= DEVIF_CB_PEND_FREE;
|
||||
net_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -200,8 +200,6 @@ static void devif_callback_free(FAR struct net_driver_s *dev,
|
||||
/* Free the callback structure */
|
||||
|
||||
NET_BUFPOOL_FREE(g_cbprealloc, cb);
|
||||
|
||||
net_unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -265,14 +263,12 @@ static bool devif_event_trigger(uint16_t events, uint16_t triggers)
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct devif_callback_s *
|
||||
devif_callback_alloc(FAR struct net_driver_s *dev,
|
||||
FAR struct devif_callback_s **list_head,
|
||||
FAR struct devif_callback_s **list_tail)
|
||||
devif_callback_alloc(FAR struct net_driver_s *dev,
|
||||
FAR struct devif_callback_s **list_head,
|
||||
FAR struct devif_callback_s **list_tail)
|
||||
{
|
||||
FAR struct devif_callback_s *ret;
|
||||
|
||||
net_lock();
|
||||
|
||||
/* Verify that the device pointer is valid, i.e., that it still
|
||||
* points to a registered network device and also that the network
|
||||
* device in the UP state.
|
||||
@@ -288,7 +284,6 @@ FAR struct devif_callback_s *
|
||||
|
||||
if (dev && !(netdev_verify(dev) && (dev->d_flags & IFF_UP) != 0))
|
||||
{
|
||||
net_unlock();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -339,7 +334,6 @@ FAR struct devif_callback_s *
|
||||
}
|
||||
#endif
|
||||
|
||||
net_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -466,7 +460,6 @@ uint16_t devif_conn_event(FAR struct net_driver_s *dev, uint16_t flags,
|
||||
* set in the flags set.
|
||||
*/
|
||||
|
||||
net_lock();
|
||||
while (list && flags)
|
||||
{
|
||||
/* Save the pointer to the next callback in the lists. This is done
|
||||
@@ -493,7 +486,6 @@ uint16_t devif_conn_event(FAR struct net_driver_s *dev, uint16_t flags,
|
||||
list = next;
|
||||
}
|
||||
|
||||
net_unlock();
|
||||
return flags;
|
||||
}
|
||||
|
||||
@@ -525,7 +517,6 @@ uint16_t devif_dev_event(FAR struct net_driver_s *dev, uint16_t flags)
|
||||
* set in the flags set.
|
||||
*/
|
||||
|
||||
net_lock();
|
||||
for (cb = dev->d_devcb; cb != NULL && flags != 0; cb = next)
|
||||
{
|
||||
/* Save the pointer to the next callback in the lists. This is done
|
||||
@@ -562,7 +553,6 @@ uint16_t devif_dev_event(FAR struct net_driver_s *dev, uint16_t flags)
|
||||
}
|
||||
}
|
||||
|
||||
net_unlock();
|
||||
return flags;
|
||||
}
|
||||
|
||||
|
||||
@@ -592,6 +592,7 @@ static int devif_poll_udp_connections(FAR struct net_driver_s *dev,
|
||||
* action.
|
||||
*/
|
||||
|
||||
udp_conn_list_lock();
|
||||
while (!bstop && (conn = udp_nextconn(conn)))
|
||||
{
|
||||
#ifdef CONFIG_NET_UDP_WRITE_BUFFERS
|
||||
@@ -614,6 +615,7 @@ static int devif_poll_udp_connections(FAR struct net_driver_s *dev,
|
||||
}
|
||||
}
|
||||
|
||||
udp_conn_list_unlock();
|
||||
return bstop;
|
||||
}
|
||||
#endif /* NET_UDP_HAVE_STACK */
|
||||
|
||||
@@ -68,8 +68,6 @@ static ssize_t netprocfs_udpstats(FAR struct netprocfs_file_s *priv,
|
||||
FAR void *laddr;
|
||||
FAR void *raddr;
|
||||
|
||||
net_lock();
|
||||
|
||||
while ((conn = udp_nextconn(conn)) != NULL)
|
||||
{
|
||||
#if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6)
|
||||
@@ -116,8 +114,6 @@ static ssize_t netprocfs_udpstats(FAR struct netprocfs_file_s *priv,
|
||||
ntohs(conn->rport));
|
||||
}
|
||||
|
||||
net_unlock();
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
@@ -149,8 +145,7 @@ ssize_t netprocfs_read_udpstats(FAR struct netprocfs_file_s *priv,
|
||||
int skip = 1;
|
||||
int len = 0;
|
||||
|
||||
net_lock();
|
||||
|
||||
udp_conn_list_lock();
|
||||
if (udp_nextconn(NULL) != NULL)
|
||||
{
|
||||
if (priv->offset == 0)
|
||||
@@ -183,8 +178,7 @@ ssize_t netprocfs_read_udpstats(FAR struct netprocfs_file_s *priv,
|
||||
#endif /* CONFIG_NET_IPv6 */
|
||||
}
|
||||
|
||||
net_unlock();
|
||||
|
||||
udp_conn_list_unlock();
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
@@ -253,6 +253,32 @@ FAR struct udp_conn_s *udp_active(FAR struct net_driver_s *dev,
|
||||
|
||||
FAR struct udp_conn_s *udp_nextconn(FAR struct udp_conn_s *conn);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: udp_conn_list_lock
|
||||
*
|
||||
* Description:
|
||||
* Lock the UDP connection list
|
||||
*
|
||||
* Assumptions:
|
||||
* This function must be called by driver thread.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void udp_conn_list_lock(void);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: udp_conn_list_unlock
|
||||
*
|
||||
* Description:
|
||||
* Unlock the UDP connection list
|
||||
*
|
||||
* Assumptions:
|
||||
* This function must be called by driver thread.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void udp_conn_list_unlock(void);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: udp_select_port
|
||||
*
|
||||
|
||||
@@ -78,9 +78,11 @@ static uint16_t udp_datahandler(FAR struct net_driver_s *dev,
|
||||
FAR void *src_addr;
|
||||
int offset;
|
||||
|
||||
conn_lock(&conn->sconn);
|
||||
#if CONFIG_NET_RECV_BUFSIZE > 0
|
||||
if (conn->readahead && conn->readahead->io_pktlen > conn->rcvbufs)
|
||||
{
|
||||
conn_unlock(&conn->sconn);
|
||||
netdev_iob_release(dev);
|
||||
return 0;
|
||||
}
|
||||
@@ -214,6 +216,7 @@ static uint16_t udp_datahandler(FAR struct net_driver_s *dev,
|
||||
/* Concat the iob to readahead */
|
||||
|
||||
net_iob_concat(&conn->readahead, &iob);
|
||||
conn_unlock(&conn->sconn);
|
||||
|
||||
#ifdef CONFIG_NET_UDP_NOTIFIER
|
||||
ninfo("Buffered %d bytes\n", buflen);
|
||||
@@ -230,6 +233,7 @@ static uint16_t udp_datahandler(FAR struct net_driver_s *dev,
|
||||
|
||||
errout:
|
||||
nerr("ERROR: Failed to queue the I/O buffer chain: %d\n", ret);
|
||||
conn_unlock(&conn->sconn);
|
||||
|
||||
netdev_iob_release(dev);
|
||||
return 0;
|
||||
@@ -313,7 +317,9 @@ uint16_t udp_callback(FAR struct net_driver_s *dev,
|
||||
{
|
||||
/* Perform the callback */
|
||||
|
||||
conn_lock(&conn->sconn);
|
||||
flags = devif_conn_event(dev, flags, conn->sconn.list);
|
||||
conn_unlock(&conn->sconn);
|
||||
|
||||
if ((flags & UDP_NEWDATA) != 0)
|
||||
{
|
||||
@@ -343,11 +349,13 @@ void udp_callback_cleanup(FAR void *arg)
|
||||
|
||||
nerr("ERROR: pthread is being canceled, need to cleanup cb\n");
|
||||
|
||||
udp_callback_free(cb->dev, cb->conn, cb->udp_cb);
|
||||
conn_dev_lock(&cb->conn->sconn, cb->dev);
|
||||
if (cb->sem)
|
||||
{
|
||||
nxsem_destroy(cb->sem);
|
||||
}
|
||||
|
||||
conn_dev_unlock(&cb->conn->sconn, cb->dev);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NET && CONFIG_NET_UDP */
|
||||
|
||||
+5
-4
@@ -35,8 +35,9 @@
|
||||
#include <nuttx/net/udp.h>
|
||||
|
||||
#include "devif/devif.h"
|
||||
#include "udp/udp.h"
|
||||
#include "socket/socket.h"
|
||||
#include "utils/utils.h"
|
||||
#include "udp/udp.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
@@ -67,8 +68,6 @@ int udp_close(FAR struct socket *psock)
|
||||
|
||||
/* Lock the network to avoid race conditions */
|
||||
|
||||
net_lock();
|
||||
|
||||
conn = psock->s_conn;
|
||||
DEBUGASSERT(conn != NULL);
|
||||
|
||||
@@ -112,8 +111,10 @@ int udp_close(FAR struct socket *psock)
|
||||
|
||||
if (conn->sndcb != NULL)
|
||||
{
|
||||
conn_dev_lock(&conn->sconn, conn->dev);
|
||||
udp_callback_free(conn->dev, conn, conn->sndcb);
|
||||
conn->sndcb = NULL;
|
||||
conn_dev_unlock(&conn->sconn, conn->dev);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -121,7 +122,7 @@ int udp_close(FAR struct socket *psock)
|
||||
|
||||
conn->crefs = 0;
|
||||
udp_free(psock->s_conn);
|
||||
net_unlock();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
+47
-17
@@ -129,6 +129,7 @@ static FAR struct udp_conn_s *udp_find_conn(uint8_t domain,
|
||||
|
||||
/* Now search each connection structure. */
|
||||
|
||||
udp_conn_list_lock();
|
||||
while ((conn = udp_nextconn(conn)) != NULL)
|
||||
{
|
||||
/* With SO_REUSEADDR set for both sockets, we do not need to check its
|
||||
@@ -157,7 +158,7 @@ static FAR struct udp_conn_s *udp_find_conn(uint8_t domain,
|
||||
(net_ipv4addr_cmp(conn->u.ipv4.laddr, ipaddr->ipv4.laddr) ||
|
||||
net_ipv4addr_cmp(conn->u.ipv4.laddr, INADDR_ANY)))
|
||||
{
|
||||
return conn;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_NET_IPv4 */
|
||||
@@ -171,13 +172,14 @@ static FAR struct udp_conn_s *udp_find_conn(uint8_t domain,
|
||||
(net_ipv6addr_cmp(conn->u.ipv6.laddr, ipaddr->ipv6.laddr) ||
|
||||
net_ipv6addr_cmp(conn->u.ipv6.laddr, g_ipv6_unspecaddr)))
|
||||
{
|
||||
return conn;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_NET_IPv6 */
|
||||
}
|
||||
|
||||
return NULL;
|
||||
udp_conn_list_unlock();
|
||||
return conn;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -316,7 +318,7 @@ udp_ipv4_active(FAR struct net_driver_s *dev, FAR struct udp_conn_s *conn,
|
||||
|
||||
/* Look at the next active connection */
|
||||
|
||||
conn = (FAR struct udp_conn_s *)conn->sconn.node.flink;
|
||||
conn = udp_nextconn(conn);
|
||||
}
|
||||
|
||||
return conn;
|
||||
@@ -456,7 +458,7 @@ udp_ipv6_active(FAR struct net_driver_s *dev, FAR struct udp_conn_s *conn,
|
||||
|
||||
/* Look at the next active connection */
|
||||
|
||||
conn = (FAR struct udp_conn_s *)conn->sconn.node.flink;
|
||||
conn = udp_nextconn(conn);
|
||||
}
|
||||
|
||||
return conn;
|
||||
@@ -492,8 +494,6 @@ uint16_t udp_select_port(uint8_t domain, FAR union ip_binding_u *u)
|
||||
static uint16_t g_last_udp_port;
|
||||
uint16_t portno;
|
||||
|
||||
net_lock();
|
||||
|
||||
/* Generate port base dynamically */
|
||||
|
||||
if (g_last_udp_port == 0)
|
||||
@@ -514,8 +514,7 @@ uint16_t udp_select_port(uint8_t domain, FAR union ip_binding_u *u)
|
||||
{
|
||||
/* We have looped back, failed. */
|
||||
|
||||
portno = 0;
|
||||
goto errout;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
while (udp_find_conn(domain, u, HTONS(g_last_udp_port), 0) != NULL
|
||||
@@ -531,9 +530,6 @@ uint16_t udp_select_port(uint8_t domain, FAR union ip_binding_u *u)
|
||||
|
||||
portno = g_last_udp_port;
|
||||
|
||||
errout:
|
||||
net_unlock();
|
||||
|
||||
return portno;
|
||||
}
|
||||
|
||||
@@ -575,6 +571,7 @@ FAR struct udp_conn_s *udp_alloc(uint8_t domain)
|
||||
nxsem_init(&conn->sndsem, 0, 0);
|
||||
#endif
|
||||
|
||||
nxmutex_init(&conn->sconn.s_lock);
|
||||
#ifdef CONFIG_NET_UDP_WRITE_BUFFERS
|
||||
/* Initialize the write buffer lists */
|
||||
|
||||
@@ -614,6 +611,7 @@ void udp_free(FAR struct udp_conn_s *conn)
|
||||
/* Remove the connection from the active list */
|
||||
|
||||
dq_rem(&conn->sconn.node, &g_active_udp_connections);
|
||||
nxmutex_destroy(&conn->sconn.s_lock);
|
||||
|
||||
/* Release any read-ahead buffers attached to the connection, NULL is ok */
|
||||
|
||||
@@ -682,6 +680,38 @@ FAR struct udp_conn_s *udp_active(FAR struct net_driver_s *dev,
|
||||
#endif /* CONFIG_NET_IPv4 */
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: udp_conn_list_lock
|
||||
*
|
||||
* Description:
|
||||
* Lock the UDP connection list
|
||||
*
|
||||
* Assumptions:
|
||||
* This function must be called by driver thread.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void udp_conn_list_lock(void)
|
||||
{
|
||||
NET_BUFPOOL_LOCK(g_udp_connections);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: udp_conn_list_unlock
|
||||
*
|
||||
* Description:
|
||||
* Unlock the UDP connection list
|
||||
*
|
||||
* Assumptions:
|
||||
* This function must be called by driver thread.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void udp_conn_list_unlock(void)
|
||||
{
|
||||
NET_BUFPOOL_UNLOCK(g_udp_connections);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: udp_nextconn
|
||||
*
|
||||
@@ -689,7 +719,7 @@ FAR struct udp_conn_s *udp_active(FAR struct net_driver_s *dev,
|
||||
* Traverse the list of allocated UDP connections
|
||||
*
|
||||
* Assumptions:
|
||||
* This function must be called with the network locked.
|
||||
* This function must be called with the udp_conn_list_lock.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@@ -734,7 +764,7 @@ int udp_bind(FAR struct udp_conn_s *conn, FAR const struct sockaddr *addr)
|
||||
|
||||
/* Interrupts must be disabled while access the UDP connection list */
|
||||
|
||||
net_lock();
|
||||
conn_lock(&conn->sconn);
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
@@ -764,7 +794,7 @@ int udp_bind(FAR struct udp_conn_s *conn, FAR const struct sockaddr *addr)
|
||||
netdev_list_unlock();
|
||||
if (ret == -EADDRNOTAVAIL)
|
||||
{
|
||||
net_unlock();
|
||||
conn_unlock(&conn->sconn);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -814,7 +844,7 @@ int udp_bind(FAR struct udp_conn_s *conn, FAR const struct sockaddr *addr)
|
||||
netdev_list_unlock();
|
||||
if (ret == -EADDRNOTAVAIL)
|
||||
{
|
||||
net_unlock();
|
||||
conn_unlock(&conn->sconn);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -880,7 +910,7 @@ int udp_bind(FAR struct udp_conn_s *conn, FAR const struct sockaddr *addr)
|
||||
}
|
||||
}
|
||||
|
||||
net_unlock();
|
||||
conn_unlock(&conn->sconn);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -297,6 +297,7 @@ static int udp_input(FAR struct net_driver_s *dev, unsigned int iplen)
|
||||
* that, however.
|
||||
*/
|
||||
|
||||
udp_conn_list_lock();
|
||||
conn = udp_active(dev, NULL, udp);
|
||||
if (conn)
|
||||
{
|
||||
@@ -389,6 +390,8 @@ static int udp_input(FAR struct net_driver_s *dev, unsigned int iplen)
|
||||
# endif /* CONFIG_NET_IPv6*/
|
||||
#endif
|
||||
}
|
||||
|
||||
udp_conn_list_unlock();
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
+3
-2
@@ -38,6 +38,7 @@
|
||||
#include <nuttx/mm/iob.h>
|
||||
#include <nuttx/net/net.h>
|
||||
|
||||
#include "utils/utils.h"
|
||||
#include "udp/udp.h"
|
||||
|
||||
/****************************************************************************
|
||||
@@ -117,7 +118,7 @@ int udp_ioctl(FAR struct udp_conn_s *conn, int cmd, unsigned long arg)
|
||||
FAR struct iob_s *iob;
|
||||
int ret = OK;
|
||||
|
||||
net_lock();
|
||||
conn_lock(&conn->sconn);
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
@@ -155,7 +156,7 @@ int udp_ioctl(FAR struct udp_conn_s *conn, int cmd, unsigned long arg)
|
||||
break;
|
||||
}
|
||||
|
||||
net_unlock();
|
||||
conn_unlock(&conn->sconn);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
+14
-12
@@ -37,6 +37,7 @@
|
||||
#include "devif/devif.h"
|
||||
#include "netdev/netdev.h"
|
||||
#include "socket/socket.h"
|
||||
#include "utils/utils.h"
|
||||
#include "udp/udp.h"
|
||||
|
||||
/****************************************************************************
|
||||
@@ -132,23 +133,25 @@ int udp_pollsetup(FAR struct socket *psock, FAR struct pollfd *fds)
|
||||
FAR struct udp_conn_s *conn;
|
||||
FAR struct udp_poll_s *info;
|
||||
FAR struct devif_callback_s *cb;
|
||||
FAR struct net_driver_s *dev;
|
||||
pollevent_t eventset = 0;
|
||||
int ret = OK;
|
||||
|
||||
/* Some of the following must be atomic */
|
||||
|
||||
net_lock();
|
||||
|
||||
conn = psock->s_conn;
|
||||
|
||||
/* Sanity check */
|
||||
|
||||
if (conn == NULL || fds == NULL)
|
||||
{
|
||||
ret = -EINVAL;
|
||||
goto errout_with_lock;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev = udp_find_laddr_device(conn);
|
||||
|
||||
conn_dev_lock(&conn->sconn, dev);
|
||||
|
||||
/* Find a container to hold the poll information */
|
||||
|
||||
info = conn->pollinfo;
|
||||
@@ -166,7 +169,7 @@ int udp_pollsetup(FAR struct socket *psock, FAR struct pollfd *fds)
|
||||
* dev value will be zero and there will be no NETDEV_DOWN notifications.
|
||||
*/
|
||||
|
||||
info->dev = udp_find_laddr_device(conn);
|
||||
info->dev = dev;
|
||||
|
||||
/* Allocate a UDP callback structure */
|
||||
|
||||
@@ -229,7 +232,8 @@ int udp_pollsetup(FAR struct socket *psock, FAR struct pollfd *fds)
|
||||
poll_notify(&fds, 1, eventset);
|
||||
|
||||
errout_with_lock:
|
||||
net_unlock();
|
||||
conn_dev_unlock(&conn->sconn, dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -254,9 +258,7 @@ int udp_pollteardown(FAR struct socket *psock, FAR struct pollfd *fds)
|
||||
FAR struct udp_conn_s *conn;
|
||||
FAR struct udp_poll_s *info;
|
||||
|
||||
/* Some of the following must be atomic */
|
||||
|
||||
net_lock();
|
||||
/* Some of the following must be atomic? */
|
||||
|
||||
conn = psock->s_conn;
|
||||
|
||||
@@ -264,7 +266,6 @@ int udp_pollteardown(FAR struct socket *psock, FAR struct pollfd *fds)
|
||||
|
||||
if (!conn || !fds->priv)
|
||||
{
|
||||
net_unlock();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -274,6 +275,8 @@ int udp_pollteardown(FAR struct socket *psock, FAR struct pollfd *fds)
|
||||
DEBUGASSERT(info->fds != NULL && info->cb != NULL);
|
||||
if (info != NULL)
|
||||
{
|
||||
conn_dev_lock(&conn->sconn, info->dev);
|
||||
|
||||
/* Release the callback */
|
||||
|
||||
udp_callback_free(info->dev, conn, info->cb);
|
||||
@@ -285,9 +288,8 @@ int udp_pollteardown(FAR struct socket *psock, FAR struct pollfd *fds)
|
||||
/* Then free the poll info container */
|
||||
|
||||
info->conn = NULL;
|
||||
conn_dev_unlock(&conn->sconn, info->dev);
|
||||
}
|
||||
|
||||
net_unlock();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
+12
-9
@@ -694,9 +694,17 @@ ssize_t psock_udp_recvfrom(FAR struct socket *psock, FAR struct msghdr *msg,
|
||||
* because we don't want anything to happen until we are ready.
|
||||
*/
|
||||
|
||||
net_lock();
|
||||
udp_recvfrom_initialize(conn, msg, &state, flags);
|
||||
|
||||
/* Get the device that will handle the packet transfers. This may be
|
||||
* NULL if the UDP socket is bound to INADDR_ANY. In that case, no
|
||||
* NETDEV_DOWN notifications will be received.
|
||||
*/
|
||||
|
||||
dev = udp_find_laddr_device(conn);
|
||||
|
||||
conn_dev_lock(&conn->sconn, dev);
|
||||
|
||||
/* Copy the read-ahead data from the packet */
|
||||
|
||||
udp_readahead(&state);
|
||||
@@ -735,13 +743,6 @@ ssize_t psock_udp_recvfrom(FAR struct socket *psock, FAR struct msghdr *msg,
|
||||
|
||||
else if (state.ir_recvlen <= 0)
|
||||
{
|
||||
/* Get the device that will handle the packet transfers. This may be
|
||||
* NULL if the UDP socket is bound to INADDR_ANY. In that case, no
|
||||
* NETDEV_DOWN notifications will be received.
|
||||
*/
|
||||
|
||||
dev = udp_find_laddr_device(conn);
|
||||
|
||||
/* Set up the callback in the connection */
|
||||
|
||||
state.ir_cb = udp_callback_alloc(dev, conn);
|
||||
@@ -768,8 +769,10 @@ ssize_t psock_udp_recvfrom(FAR struct socket *psock, FAR struct msghdr *msg,
|
||||
* received.
|
||||
*/
|
||||
|
||||
conn_dev_unlock(&conn->sconn, dev);
|
||||
ret = net_sem_timedwait(&state.ir_sem,
|
||||
_SO_TIMEOUT(conn->sconn.s_rcvtimeo));
|
||||
conn_dev_lock(&conn->sconn, dev);
|
||||
tls_cleanup_pop(tls_get_info(), 0);
|
||||
if (ret == -ETIMEDOUT)
|
||||
{
|
||||
@@ -787,9 +790,9 @@ ssize_t psock_udp_recvfrom(FAR struct socket *psock, FAR struct msghdr *msg,
|
||||
}
|
||||
}
|
||||
|
||||
conn_dev_unlock(&conn->sconn, dev);
|
||||
udp_notify_recvcpu(conn);
|
||||
|
||||
net_unlock();
|
||||
udp_recvfrom_uninitialize(&state);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -118,16 +118,16 @@ static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev,
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void sendto_writebuffer_release(FAR struct udp_conn_s *conn)
|
||||
static void sendto_writebuffer_release(FAR struct udp_conn_s *conn,
|
||||
FAR struct udp_wrbuffer_s *wrb)
|
||||
{
|
||||
FAR struct udp_wrbuffer_s *wrb;
|
||||
int ret = OK;
|
||||
|
||||
do
|
||||
{
|
||||
/* Check if the write queue became empty */
|
||||
|
||||
if (sq_empty(&conn->write_q))
|
||||
if (wrb == NULL && sq_empty(&conn->write_q))
|
||||
{
|
||||
/* Yes.. stifle any further callbacks until more write data is
|
||||
* enqueued.
|
||||
@@ -136,7 +136,7 @@ static void sendto_writebuffer_release(FAR struct udp_conn_s *conn)
|
||||
conn->sndcb->flags = 0;
|
||||
conn->sndcb->priv = NULL;
|
||||
conn->sndcb->event = NULL;
|
||||
wrb = NULL;
|
||||
ret = OK;
|
||||
|
||||
if (conn->txdrain_sem != NULL)
|
||||
{
|
||||
@@ -153,10 +153,17 @@ static void sendto_writebuffer_release(FAR struct udp_conn_s *conn)
|
||||
* and release it.
|
||||
*/
|
||||
|
||||
wrb = (FAR struct udp_wrbuffer_s *)sq_remfirst(&conn->write_q);
|
||||
if (wrb == NULL)
|
||||
{
|
||||
/* Get the write buffer at the head of the queue */
|
||||
|
||||
wrb = (FAR struct udp_wrbuffer_s *)sq_remfirst(&conn->write_q);
|
||||
}
|
||||
|
||||
DEBUGASSERT(wrb != NULL);
|
||||
|
||||
udp_wrbuffer_release(wrb);
|
||||
wrb = NULL;
|
||||
|
||||
/* Set up for the next packet transfer by setting the connection
|
||||
* address to the address of the next packet now at the header of
|
||||
@@ -166,7 +173,7 @@ static void sendto_writebuffer_release(FAR struct udp_conn_s *conn)
|
||||
ret = sendto_next_transfer(conn);
|
||||
}
|
||||
}
|
||||
while (wrb != NULL && ret < 0);
|
||||
while (ret < 0);
|
||||
|
||||
#if CONFIG_NET_SEND_BUFSIZE > 0
|
||||
/* Notify the send buffer available if wrbbuffer drained */
|
||||
@@ -303,6 +310,8 @@ static int sendto_next_transfer(FAR struct udp_conn_s *conn)
|
||||
}
|
||||
#endif
|
||||
|
||||
conn_unlock(&conn->sconn);
|
||||
|
||||
/* If this is not the same device that we used in the last call to
|
||||
* udp_callback_alloc(), then we need to release and reallocate the old
|
||||
* callback instance.
|
||||
@@ -310,8 +319,10 @@ static int sendto_next_transfer(FAR struct udp_conn_s *conn)
|
||||
|
||||
if (conn->sndcb != NULL && conn->dev != dev)
|
||||
{
|
||||
conn_dev_lock(&conn->sconn, conn->dev);
|
||||
udp_callback_free(conn->dev, conn, conn->sndcb);
|
||||
conn->sndcb = NULL;
|
||||
conn_dev_unlock(&conn->sconn, conn->dev);
|
||||
}
|
||||
|
||||
/* Allocate resources to receive a callback from this device if the
|
||||
@@ -320,7 +331,9 @@ static int sendto_next_transfer(FAR struct udp_conn_s *conn)
|
||||
|
||||
if (conn->sndcb == NULL)
|
||||
{
|
||||
conn_dev_lock(&conn->sconn, dev);
|
||||
conn->sndcb = udp_callback_alloc(dev, conn);
|
||||
conn_dev_unlock(&conn->sconn, dev);
|
||||
}
|
||||
|
||||
/* Test if the callback has been allocated */
|
||||
@@ -330,6 +343,7 @@ static int sendto_next_transfer(FAR struct udp_conn_s *conn)
|
||||
/* A buffer allocation error occurred */
|
||||
|
||||
nerr("ERROR: Failed to allocate callback\n");
|
||||
conn_lock(&conn->sconn);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@@ -344,6 +358,9 @@ static int sendto_next_transfer(FAR struct udp_conn_s *conn)
|
||||
/* Notify the device driver of the availability of TX data */
|
||||
|
||||
netdev_txnotify_dev(dev);
|
||||
|
||||
conn_lock(&conn->sconn);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
@@ -386,7 +403,7 @@ static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev,
|
||||
* the next transfer.
|
||||
*/
|
||||
|
||||
sendto_writebuffer_release(conn);
|
||||
sendto_writebuffer_release(conn, NULL);
|
||||
return flags;
|
||||
}
|
||||
|
||||
@@ -428,7 +445,7 @@ static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev,
|
||||
* the write_q is not empty.
|
||||
*/
|
||||
|
||||
wrb = (FAR struct udp_wrbuffer_s *)sq_peek(&conn->write_q);
|
||||
wrb = (FAR struct udp_wrbuffer_s *)sq_remfirst(&conn->write_q);
|
||||
DEBUGASSERT(wrb != NULL);
|
||||
|
||||
/* If the udp socket not connected, it is possible to have
|
||||
@@ -474,7 +491,7 @@ static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev,
|
||||
* setup the next transfer.
|
||||
*/
|
||||
|
||||
sendto_writebuffer_release(conn);
|
||||
sendto_writebuffer_release(conn, wrb);
|
||||
|
||||
/* Only one data can be sent by low level driver at once,
|
||||
* tell the caller stop polling the other connections.
|
||||
@@ -690,19 +707,18 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf,
|
||||
|
||||
BUF_DUMP("psock_udp_sendto", buf, len);
|
||||
|
||||
net_lock();
|
||||
|
||||
#if CONFIG_NET_SEND_BUFSIZE > 0
|
||||
/* If the send buffer size exceeds the send limit,
|
||||
* wait for the write buffer to be released
|
||||
*/
|
||||
|
||||
conn_lock(&conn->sconn);
|
||||
while (udp_wrbuffer_inqueue_size(conn) + len > conn->sndbufs)
|
||||
{
|
||||
conn_unlock(&conn->sconn);
|
||||
if (nonblock)
|
||||
{
|
||||
ret = -EAGAIN;
|
||||
goto errout_with_lock;
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
ret = net_sem_timedwait_uninterruptible(&conn->sndsem,
|
||||
@@ -714,9 +730,13 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf,
|
||||
ret = -EAGAIN;
|
||||
}
|
||||
|
||||
goto errout_with_lock;
|
||||
return ret;
|
||||
}
|
||||
|
||||
conn_lock(&conn->sconn);
|
||||
}
|
||||
|
||||
conn_unlock(&conn->sconn);
|
||||
#endif /* CONFIG_NET_SEND_BUFSIZE */
|
||||
|
||||
/* Allocate a write buffer. Careful, the network will be momentarily
|
||||
@@ -755,7 +775,7 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf,
|
||||
ret = -ENOMEM;
|
||||
}
|
||||
|
||||
goto errout_with_lock;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Initialize the write buffer
|
||||
@@ -825,21 +845,8 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf,
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int count;
|
||||
int blresult;
|
||||
|
||||
/* iob_copyin might wait for buffers to be freed, but if
|
||||
* network is locked this might never happen, since network
|
||||
* driver is also locked, therefore we need to break the lock
|
||||
*/
|
||||
|
||||
blresult = net_breaklock(&count);
|
||||
ret = iob_copyin(wrb->wb_iob, (FAR uint8_t *)buf,
|
||||
len, udpiplen, false);
|
||||
if (blresult >= 0)
|
||||
{
|
||||
net_restorelock(count);
|
||||
}
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
@@ -863,6 +870,7 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf,
|
||||
* not a very common use case, however.
|
||||
*/
|
||||
|
||||
conn_lock(&conn->sconn);
|
||||
empty = sq_empty(&conn->write_q);
|
||||
|
||||
sq_addlast(&wrb->wb_node, &conn->write_q);
|
||||
@@ -882,11 +890,12 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf,
|
||||
if (ret < 0)
|
||||
{
|
||||
sq_remlast(&conn->write_q);
|
||||
conn_unlock(&conn->sconn);
|
||||
goto errout_with_wrb;
|
||||
}
|
||||
}
|
||||
|
||||
net_unlock();
|
||||
conn_unlock(&conn->sconn);
|
||||
}
|
||||
|
||||
/* Return the number of bytes that will be sent */
|
||||
|
||||
@@ -895,8 +904,6 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf,
|
||||
errout_with_wrb:
|
||||
udp_wrbuffer_release(wrb);
|
||||
|
||||
errout_with_lock:
|
||||
net_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
#include "arp/arp.h"
|
||||
#include "icmpv6/icmpv6.h"
|
||||
#include "socket/socket.h"
|
||||
#include "utils/utils.h"
|
||||
#include "udp/udp.h"
|
||||
|
||||
/****************************************************************************
|
||||
@@ -415,7 +416,6 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf,
|
||||
* ready.
|
||||
*/
|
||||
|
||||
net_lock();
|
||||
memset(&state, 0, sizeof(struct sendto_s));
|
||||
nxsem_init(&state.st_sem, 0, 0);
|
||||
|
||||
@@ -440,7 +440,7 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf,
|
||||
if (ret < 0)
|
||||
{
|
||||
nerr("ERROR: udp_connect failed: %d\n", ret);
|
||||
goto errout_with_lock;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -452,8 +452,7 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf,
|
||||
if (state.st_dev == NULL)
|
||||
{
|
||||
nerr("ERROR: udp_find_raddr_device failed\n");
|
||||
ret = -ENETUNREACH;
|
||||
goto errout_with_lock;
|
||||
return -ENETUNREACH;
|
||||
}
|
||||
|
||||
/* Make sure that the device is in the UP state */
|
||||
@@ -461,10 +460,11 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf,
|
||||
if ((state.st_dev->d_flags & IFF_UP) == 0)
|
||||
{
|
||||
nwarn("WARNING: device is DOWN\n");
|
||||
ret = -EHOSTUNREACH;
|
||||
goto errout_with_lock;
|
||||
return -EHOSTUNREACH;
|
||||
}
|
||||
|
||||
conn_dev_lock(&conn->sconn, state.st_dev);
|
||||
|
||||
/* Set up the callback in the connection */
|
||||
|
||||
ret = -ENOMEM; /* Assume allocation failure */
|
||||
@@ -475,6 +475,8 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf,
|
||||
state.st_cb->priv = (FAR void *)&state;
|
||||
state.st_cb->event = sendto_eventhandler;
|
||||
|
||||
conn_dev_unlock(&conn->sconn, state.st_dev);
|
||||
|
||||
/* Notify the device driver of the availability of TX data */
|
||||
|
||||
netdev_txnotify_dev(state.st_dev);
|
||||
@@ -495,20 +497,20 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf,
|
||||
ret = state.st_sndlen;
|
||||
}
|
||||
|
||||
conn_dev_lock(&conn->sconn, state.st_dev);
|
||||
|
||||
/* Make sure that no further events are processed */
|
||||
|
||||
udp_callback_free(state.st_dev, conn, state.st_cb);
|
||||
}
|
||||
|
||||
errout_with_lock:
|
||||
|
||||
/* Release the semaphore */
|
||||
|
||||
nxsem_destroy(&state.st_sem);
|
||||
|
||||
/* Unlock the network and return the result of the sendto() operation */
|
||||
|
||||
net_unlock();
|
||||
conn_dev_unlock(&conn->sconn, state.st_dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -81,16 +81,17 @@ int udp_txdrain(FAR struct socket *psock, unsigned int timeout)
|
||||
|
||||
/* The following needs to be done with the network stable */
|
||||
|
||||
net_lock();
|
||||
|
||||
conn_lock(&conn->sconn);
|
||||
if (!sq_empty(&conn->write_q))
|
||||
{
|
||||
conn->txdrain_sem = &waitsem;
|
||||
conn_unlock(&conn->sconn);
|
||||
ret = net_sem_timedwait_uninterruptible(&waitsem, timeout);
|
||||
conn_lock(&conn->sconn);
|
||||
conn->txdrain_sem = NULL;
|
||||
}
|
||||
|
||||
net_unlock();
|
||||
conn_unlock(&conn->sconn);
|
||||
nxsem_destroy(&waitsem);
|
||||
leave_cancellation_point();
|
||||
return ret;
|
||||
|
||||
Reference in New Issue
Block a user