This is an automated email from the ASF dual-hosted git repository. xiaoxiang pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 5032377c3467977cc1ad6202f84f88d829029859 Author: zhanghongyu <[email protected]> AuthorDate: Wed Jul 16 20:56:46 2025 +0800 net/tcp: replace net_lock with conn_lock and conn_lock_dev Protect tcp resources through netdev_lock, conn_lock, and tcp_list_lock Signed-off-by: zhanghongyu <[email protected]> --- net/procfs/net_tcp.c | 8 +--- net/tcp/tcp.h | 20 +++++++++ net/tcp/tcp_accept.c | 19 ++++++--- net/tcp/tcp_backlog.c | 5 ++- net/tcp/tcp_callback.c | 5 ++- net/tcp/tcp_close.c | 14 +++---- net/tcp/tcp_conn.c | 95 +++++++++++++++++++++++++------------------ net/tcp/tcp_connect.c | 9 ++-- net/tcp/tcp_devpoll.c | 3 ++ net/tcp/tcp_ioctl.c | 5 ++- net/tcp/tcp_listen.c | 12 ++++-- net/tcp/tcp_monitor.c | 12 ++---- net/tcp/tcp_netpoll.c | 17 ++++---- net/tcp/tcp_recvfrom.c | 12 ++++-- net/tcp/tcp_send_buffered.c | 12 ++++-- net/tcp/tcp_send_unbuffered.c | 9 ++-- net/tcp/tcp_sendfile.c | 7 +++- net/tcp/tcp_shutdown.c | 10 +++-- net/tcp/tcp_timer.c | 12 ++++-- net/tcp/tcp_txdrain.c | 6 ++- 20 files changed, 182 insertions(+), 110 deletions(-) diff --git a/net/procfs/net_tcp.c b/net/procfs/net_tcp.c index 95b9e417754..8b840caeebc 100644 --- a/net/procfs/net_tcp.c +++ b/net/procfs/net_tcp.c @@ -68,8 +68,6 @@ static ssize_t netprocfs_tcpstats(FAR struct netprocfs_file_s *priv, FAR void *laddr; FAR void *raddr; - net_lock(); - while ((conn = tcp_nextconn(conn)) != NULL) { #if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6) @@ -125,8 +123,6 @@ static ssize_t netprocfs_tcpstats(FAR struct netprocfs_file_s *priv, ntohs(conn->rport)); } - net_unlock(); - return len; } @@ -158,7 +154,7 @@ ssize_t netprocfs_read_tcpstats(FAR struct netprocfs_file_s *priv, int skip = 1; int len = 0; - net_lock(); + tcp_conn_list_lock(); if (tcp_nextconn(NULL) != NULL) { @@ -192,7 +188,7 @@ ssize_t netprocfs_read_tcpstats(FAR struct netprocfs_file_s *priv, #endif /* CONFIG_NET_IPv6 */ } - net_unlock(); + tcp_conn_list_unlock(); return len; } diff --git a/net/tcp/tcp.h b/net/tcp/tcp.h index e8ba598612a..a23b9a2c734 100644 --- a/net/tcp/tcp.h +++ b/net/tcp/tcp.h @@ -696,6 +696,26 @@ int tcp_connect(FAR struct tcp_conn_s *conn, void tcp_removeconn(FAR struct tcp_conn_s *conn); +/**************************************************************************** + * Name: tcp_conn_list_lock + * + * Description: + * Lock the TCP connection list. + * + ****************************************************************************/ + +void tcp_conn_list_lock(void); + +/**************************************************************************** + * Name: tcp_conn_list_unlock + * + * Description: + * Unlock the TCP connection list. + * + ****************************************************************************/ + +void tcp_conn_list_unlock(void); + /**************************************************************************** * Name: psock_tcp_connect * diff --git a/net/tcp/tcp_accept.c b/net/tcp/tcp_accept.c index dd5beb97d89..a2fb6135b35 100644 --- a/net/tcp/tcp_accept.c +++ b/net/tcp/tcp_accept.c @@ -39,6 +39,7 @@ #include <nuttx/net/net.h> #include "socket/socket.h" +#include "utils/utils.h" #include "tcp/tcp.h" /**************************************************************************** @@ -217,7 +218,7 @@ int psock_tcp_accept(FAR struct socket *psock, FAR struct sockaddr *addr, { FAR struct tcp_conn_s *conn; struct accept_s state; - int ret; + int ret = OK; /* Check the backlog to see if there is a connection already pending for * this listener. @@ -225,6 +226,8 @@ int psock_tcp_accept(FAR struct socket *psock, FAR struct sockaddr *addr, conn = psock->s_conn; + conn_lock(&conn->sconn); + #ifdef CONFIG_NET_TCPBACKLOG state.acpt_newconn = tcp_backlogremove(conn); if (state.acpt_newconn) @@ -243,7 +246,8 @@ int psock_tcp_accept(FAR struct socket *psock, FAR struct sockaddr *addr, else if (_SS_ISNONBLOCK(conn->sconn.s_flags)) { - return -EAGAIN; + ret = -EAGAIN; + goto out; } else #endif @@ -271,7 +275,9 @@ int psock_tcp_accept(FAR struct socket *psock, FAR struct sockaddr *addr, * net_sem_wait will also terminate if a signal is received. */ + conn_unlock(&conn->sconn); ret = net_sem_wait(&state.acpt_sem); + conn_lock(&conn->sconn); /* Make sure that no further events are processed */ @@ -287,7 +293,7 @@ int psock_tcp_accept(FAR struct socket *psock, FAR struct sockaddr *addr, if (state.acpt_result != 0) { DEBUGASSERT(state.acpt_result > 0); - return -state.acpt_result; + ret = -state.acpt_result; } /* If net_sem_wait failed, then we were probably reawakened by a @@ -297,12 +303,15 @@ int psock_tcp_accept(FAR struct socket *psock, FAR struct sockaddr *addr, if (ret < 0) { - return ret; + goto out; } } *newconn = (FAR void *)state.acpt_newconn; - return OK; + +out: + conn_unlock(&conn->sconn); + return ret; } #endif /* CONFIG_NET_TCP */ diff --git a/net/tcp/tcp_backlog.c b/net/tcp/tcp_backlog.c index da73323b0dc..2d1864d6f1b 100644 --- a/net/tcp/tcp_backlog.c +++ b/net/tcp/tcp_backlog.c @@ -37,6 +37,7 @@ #include <nuttx/net/net.h> #include "devif/devif.h" +#include "utils/utils.h" #include "tcp/tcp.h" /**************************************************************************** @@ -118,7 +119,7 @@ int tcp_backlogcreate(FAR struct tcp_conn_s *conn, int nblg) /* Destroy any existing backlog (shouldn't be any) */ - net_lock(); + conn_lock(&conn->sconn); tcp_backlogdestroy(conn); /* Now install the backlog tear-off in the connection. NOTE that bls may @@ -128,7 +129,7 @@ int tcp_backlogcreate(FAR struct tcp_conn_s *conn, int nblg) */ conn->backlog = bls; - net_unlock(); + conn_unlock(&conn->sconn); return OK; } diff --git a/net/tcp/tcp_callback.c b/net/tcp/tcp_callback.c index 8632d6fcc5b..9910151cfca 100644 --- a/net/tcp/tcp_callback.c +++ b/net/tcp/tcp_callback.c @@ -436,11 +436,12 @@ uint16_t tcp_datahandler(FAR struct net_driver_s *dev, void tcp_callback_cleanup(FAR void *arg) { FAR struct tcp_callback_s *cb = (FAR struct tcp_callback_s *)arg; + FAR struct tcp_conn_s *conn = cb->tc_conn; - net_lock(); + conn_dev_lock(&conn->sconn, conn->dev); nerr("ERROR: pthread is being canceled, need to cleanup cb\n"); tcp_callback_free(cb->tc_conn, *(cb->tc_cb)); nxsem_destroy(cb->tc_sem); - net_unlock(); + conn_dev_unlock(&conn->sconn, conn->dev); } #endif /* NET_TCP_HAVE_STACK */ diff --git a/net/tcp/tcp_close.c b/net/tcp/tcp_close.c index d91e2b1227c..8df0cb76198 100644 --- a/net/tcp/tcp_close.c +++ b/net/tcp/tcp_close.c @@ -40,6 +40,7 @@ #include "devif/devif.h" #include "tcp/tcp.h" #include "socket/socket.h" +#include "utils/utils.h" /**************************************************************************** * Private Functions @@ -53,18 +54,16 @@ static void tcp_close_work(FAR void *param) { FAR struct tcp_conn_s *conn = (FAR struct tcp_conn_s *)param; - net_lock(); - conn->flags &= ~TCP_CLOSE_ARRANGED; if (conn->crefs == 0) { /* Stop the network monitor for all sockets */ + conn_dev_lock(&conn->sconn, conn->dev); tcp_stop_monitor(conn, TCP_CLOSE); + conn_dev_unlock(&conn->sconn, conn->dev); tcp_free(conn); } - - net_unlock(); } /**************************************************************************** @@ -220,10 +219,10 @@ static inline int tcp_close_disconnect(FAR struct socket *psock) /* Interrupts are disabled here to avoid race conditions */ - net_lock(); - conn = psock->s_conn; + conn_dev_lock(&conn->sconn, conn->dev); + /* Discard our reference to the connection */ conn->crefs = 0; @@ -279,12 +278,14 @@ static inline int tcp_close_disconnect(FAR struct socket *psock) /* Notify the device driver of the availability of TX data */ tcp_send_txnotify(psock, conn); + conn_dev_unlock(&conn->sconn, conn->dev); } else { /* Stop the network monitor for all sockets */ tcp_stop_monitor(conn, TCP_CLOSE); + conn_dev_unlock(&conn->sconn, conn->dev); /* Free network resources */ @@ -293,7 +294,6 @@ static inline int tcp_close_disconnect(FAR struct socket *psock) psock->s_conn = NULL; - net_unlock(); return ret; } diff --git a/net/tcp/tcp_conn.c b/net/tcp/tcp_conn.c index e8fdb5bb427..0a2dc61f687 100644 --- a/net/tcp/tcp_conn.c +++ b/net/tcp/tcp_conn.c @@ -343,11 +343,8 @@ static inline int tcp_ipv4_bind(FAR struct tcp_conn_s *conn, /* Verify or select a local port and address */ - net_lock(); - if (conn->lport != 0) { - net_unlock(); return -EINVAL; } @@ -372,7 +369,6 @@ static inline int tcp_ipv4_bind(FAR struct tcp_conn_s *conn, if (ret == -EADDRNOTAVAIL) { - net_unlock(); return ret; } } @@ -385,7 +381,6 @@ static inline int tcp_ipv4_bind(FAR struct tcp_conn_s *conn, if (port < 0) { nerr("ERROR: tcp_selectport failed: %d\n", port); - net_unlock(); return port; } @@ -411,7 +406,6 @@ static inline int tcp_ipv4_bind(FAR struct tcp_conn_s *conn, net_ipv4addr_copy(conn->u.ipv4.laddr, INADDR_ANY); } - net_unlock(); return ret; } #endif /* CONFIG_NET_IPv4 */ @@ -441,11 +435,8 @@ static inline int tcp_ipv6_bind(FAR struct tcp_conn_s *conn, /* Verify or select a local port and address */ - net_lock(); - if (conn->lport != 0) { - net_unlock(); return -EINVAL; } @@ -472,7 +463,6 @@ static inline int tcp_ipv6_bind(FAR struct tcp_conn_s *conn, netdev_list_unlock(); if (ret == -EADDRNOTAVAIL) { - net_unlock(); return ret; } } @@ -487,7 +477,6 @@ static inline int tcp_ipv6_bind(FAR struct tcp_conn_s *conn, if (port < 0) { nerr("ERROR: tcp_selectport failed: %d\n", port); - net_unlock(); return port; } @@ -513,7 +502,6 @@ static inline int tcp_ipv6_bind(FAR struct tcp_conn_s *conn, net_ipv6addr_copy(conn->u.ipv6.laddr, g_ipv6_unspecaddr); } - net_unlock(); return ret; } #endif /* CONFIG_NET_IPv6 */ @@ -561,6 +549,7 @@ int tcp_selectport(uint8_t domain, NET_PORT_RANDOM_INIT(g_last_tcp_port); } + tcp_conn_list_lock(); if (portno == 0) { uint16_t loop_start = g_last_tcp_port; @@ -609,6 +598,7 @@ int tcp_selectport(uint8_t domain, /* Return the selected or verified port number (host byte order) */ + tcp_conn_list_unlock(); return portno; } @@ -632,7 +622,7 @@ FAR struct tcp_conn_s *tcp_alloc(uint8_t domain) * locked in any cased while accessing g_free_tcp_connections[]; */ - net_lock(); + tcp_conn_list_lock(); /* Return the entry from the head of the free list */ @@ -714,7 +704,7 @@ FAR struct tcp_conn_s *tcp_alloc(uint8_t domain) } #endif - net_unlock(); + tcp_conn_list_unlock(); /* Mark the connection allocated */ @@ -739,6 +729,7 @@ FAR struct tcp_conn_s *tcp_alloc(uint8_t domain) nxsem_init(&conn->snd_sem, 0, 0); #endif + nxmutex_init(&conn->sconn.s_lock); /* Set the default value of mss to max, this field will changed when * receive SYN. @@ -815,13 +806,6 @@ void tcp_free(FAR struct tcp_conn_s *conn) FAR struct tcp_wrbuffer_s *wrbuffer; #endif - /* Because g_free_tcp_connections is accessed from user level and event - * processing logic, it is necessary to keep the network locked during this - * operation. - */ - - net_lock(); - DEBUGASSERT(conn->crefs == 0); /* Cancel close work */ @@ -831,7 +815,6 @@ void tcp_free(FAR struct tcp_conn_s *conn) { /* Close work is already running, tcp_free will be called again. */ - net_unlock(); return; } @@ -841,6 +824,7 @@ void tcp_free(FAR struct tcp_conn_s *conn) /* Make sure monitor is stopped. */ + conn_dev_lock(&conn->sconn, conn->dev); tcp_stop_monitor(conn, TCP_CLOSE); /* Free remaining callbacks, actually there should be only the send @@ -853,6 +837,8 @@ void tcp_free(FAR struct tcp_conn_s *conn) tcp_callback_free(conn, cb); } + conn_dev_unlock(&conn->sconn, conn->dev); + /* TCP_ALLOCATED means that that the connection is not in the active list * yet. */ @@ -861,9 +847,12 @@ void tcp_free(FAR struct tcp_conn_s *conn) { /* Remove the connection from the active list */ + tcp_conn_list_lock(); dq_rem(&conn->sconn.node, &g_active_tcp_connections); + tcp_conn_list_unlock(); } + nxmutex_destroy(&conn->sconn.s_lock); tcp_free_rx_buffers(conn); #ifdef CONFIG_NET_TCP_WRITE_BUFFERS @@ -918,8 +907,6 @@ void tcp_free(FAR struct tcp_conn_s *conn) /* Free the connection structure */ NET_BUFPOOL_FREE(g_tcp_connections, conn); - - net_unlock(); } /**************************************************************************** @@ -937,12 +924,15 @@ void tcp_free(FAR struct tcp_conn_s *conn) FAR struct tcp_conn_s *tcp_active(FAR struct net_driver_s *dev, FAR struct tcp_hdr_s *tcp) { + FAR struct tcp_conn_s *conn = NULL; + + tcp_conn_list_lock(); #ifdef CONFIG_NET_IPv6 #ifdef CONFIG_NET_IPv4 if (IFF_IS_IPv6(dev->d_flags)) #endif { - return tcp_ipv6_active(dev, tcp); + conn = tcp_ipv6_active(dev, tcp); } #endif /* CONFIG_NET_IPv6 */ @@ -951,9 +941,12 @@ FAR struct tcp_conn_s *tcp_active(FAR struct net_driver_s *dev, else #endif { - return tcp_ipv4_active(dev, tcp); + conn = tcp_ipv4_active(dev, tcp); } #endif /* CONFIG_NET_IPv4 */ + + tcp_conn_list_unlock(); + return conn; } /**************************************************************************** @@ -1162,7 +1155,10 @@ FAR struct tcp_conn_s *tcp_alloc_accept(FAR struct net_driver_s *dev, * Interrupts should already be disabled in this context. */ + tcp_conn_list_lock(); dq_addlast(&conn->sconn.node, &g_active_tcp_connections); + tcp_conn_list_unlock(); + tcp_update_retrantimer(conn, TCP_RTO); } @@ -1243,7 +1239,7 @@ int tcp_bind(FAR struct tcp_conn_s *conn, FAR const struct sockaddr *addr) int tcp_connect(FAR struct tcp_conn_s *conn, FAR const struct sockaddr *addr) { int port; - int ret = OK; + int ret; /* The connection is expected to be in the TCP_ALLOCATED state.. i.e., * allocated via up_tcpalloc(), but not yet put into the active connections @@ -1260,8 +1256,6 @@ int tcp_connect(FAR struct tcp_conn_s *conn, FAR const struct sockaddr *addr) * but the port may still be INPORT_ANY. */ - net_lock(); - /* Check if the local port has been bind() */ port = conn->lport; @@ -1302,8 +1296,7 @@ int tcp_connect(FAR struct tcp_conn_s *conn, FAR const struct sockaddr *addr) if (port < 0) { - ret = port; - goto errout_with_lock; + return port; } } @@ -1387,7 +1380,7 @@ int tcp_connect(FAR struct tcp_conn_s *conn, FAR const struct sockaddr *addr) */ nerr("ERROR: Failed to find network device: %d\n", ret); - goto errout_with_lock; + return ret; } #if defined(CONFIG_NET_ARP_SEND) || defined(CONFIG_NET_ICMPv6_NEIGHBOR) @@ -1417,8 +1410,7 @@ int tcp_connect(FAR struct tcp_conn_s *conn, FAR const struct sockaddr *addr) if (ret < 0) { - ret = -ENETUNREACH; - goto errout_with_lock; + return -ENETUNREACH; } #endif /* CONFIG_NET_ARP_SEND || CONFIG_NET_ICMPv6_NEIGHBOR */ @@ -1473,12 +1465,37 @@ int tcp_connect(FAR struct tcp_conn_s *conn, FAR const struct sockaddr *addr) /* And, finally, put the connection structure into the active list. */ + tcp_conn_list_lock(); dq_addlast(&conn->sconn.node, &g_active_tcp_connections); - ret = OK; + tcp_conn_list_unlock(); -errout_with_lock: - net_unlock(); - return ret; + return OK; +} + +/**************************************************************************** + * Name: tcp_conn_list_lock + * + * Description: + * Lock the TCP connection list. + * + ****************************************************************************/ + +void tcp_conn_list_lock(void) +{ + NET_BUFPOOL_LOCK(g_tcp_connections); +} + +/**************************************************************************** + * Name: tcp_conn_list_unlock + * + * Description: + * Unlock the TCP connection list. + * + ****************************************************************************/ + +void tcp_conn_list_unlock(void) +{ + NET_BUFPOOL_UNLOCK(g_tcp_connections); } /**************************************************************************** @@ -1494,9 +1511,7 @@ errout_with_lock: void tcp_removeconn(FAR struct tcp_conn_s *conn) { - net_lock(); dq_rem(&conn->sconn.node, &g_active_tcp_connections); - net_unlock(); } #endif /* CONFIG_NET && CONFIG_NET_TCP */ diff --git a/net/tcp/tcp_connect.c b/net/tcp/tcp_connect.c index 888636b7349..79142e8e734 100644 --- a/net/tcp/tcp_connect.c +++ b/net/tcp/tcp_connect.c @@ -47,6 +47,7 @@ #include "netdev/netdev.h" #include "socket/socket.h" #include "inet/inet.h" +#include "utils/utils.h" #include "tcp/tcp.h" #ifdef NET_TCP_HAVE_STACK @@ -304,8 +305,6 @@ int psock_tcp_connect(FAR struct socket *psock, * setup. */ - net_lock(); - conn = psock->s_conn; /* Get the connection reference from the socket */ @@ -367,6 +366,7 @@ int psock_tcp_connect(FAR struct socket *psock, { /* Set up the callbacks in the connection */ + conn_dev_lock(&conn->sconn, conn->dev); ret = psock_setup_callbacks(psock, &state); if (ret >= 0) { @@ -377,6 +377,7 @@ int psock_tcp_connect(FAR struct socket *psock, info.tc_conn = conn; info.tc_cb = &state.tc_cb; info.tc_sem = &state.tc_sem; + conn_dev_unlock(&conn->sconn, conn->dev); tls_cleanup_push(tls_get_info(), tcp_callback_cleanup, &info); /* Notify the device driver that new connection is available. */ @@ -392,6 +393,7 @@ int psock_tcp_connect(FAR struct socket *psock, ret = net_sem_wait(&state.tc_sem); tls_cleanup_pop(tls_get_info(), 0); + conn_dev_lock(&conn->sconn, conn->dev); /* Uninitialize the state structure */ @@ -412,6 +414,8 @@ int psock_tcp_connect(FAR struct socket *psock, psock_teardown_callbacks(&state, ret); } + + conn_dev_unlock(&conn->sconn, conn->dev); } /* Check if the socket was successfully connected. */ @@ -443,7 +447,6 @@ int psock_tcp_connect(FAR struct socket *psock, } } - net_unlock(); return ret; } diff --git a/net/tcp/tcp_devpoll.c b/net/tcp/tcp_devpoll.c index b3e37dd4b5c..b5e3531a1bf 100644 --- a/net/tcp/tcp_devpoll.c +++ b/net/tcp/tcp_devpoll.c @@ -55,6 +55,7 @@ #include <nuttx/net/tcp.h> #include "devif/devif.h" +#include "utils/utils.h" #include "tcp/tcp.h" /**************************************************************************** @@ -117,6 +118,7 @@ void tcp_poll(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn) * setup may not actually be used. */ + conn_lock(&conn->sconn); tcp_ip_select(conn); /* Perform the callback */ @@ -126,6 +128,7 @@ void tcp_poll(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn) /* Handle the callback response */ tcp_appsend(dev, conn, result); + conn_unlock(&conn->sconn); } } diff --git a/net/tcp/tcp_ioctl.c b/net/tcp/tcp_ioctl.c index 7e95eea4c7a..52c2808be32 100644 --- a/net/tcp/tcp_ioctl.c +++ b/net/tcp/tcp_ioctl.c @@ -38,6 +38,7 @@ #include <nuttx/mm/iob.h> #include <nuttx/net/net.h> +#include "utils/utils.h" #include "tcp/tcp.h" /**************************************************************************** @@ -121,7 +122,7 @@ int tcp_ioctl(FAR struct tcp_conn_s *conn, int cmd, unsigned long arg) { int ret = OK; - net_lock(); + conn_lock(&conn->sconn); switch (cmd) { @@ -156,7 +157,7 @@ int tcp_ioctl(FAR struct tcp_conn_s *conn, int cmd, unsigned long arg) break; } - net_unlock(); + conn_unlock(&conn->sconn); return ret; } diff --git a/net/tcp/tcp_listen.c b/net/tcp/tcp_listen.c index d6e9a064aba..52eb8bb69ae 100644 --- a/net/tcp/tcp_listen.c +++ b/net/tcp/tcp_listen.c @@ -93,6 +93,7 @@ FAR struct tcp_conn_s *tcp_findlistener(FAR union ip_binding_u *uaddr, /* Examine each connection structure in each slot of the listener list */ + tcp_conn_list_lock(); for (ndx = 0; ndx < CONFIG_NET_MAX_LISTENPORTS; ndx++) { /* Is this slot assigned? If so, does the connection have the same @@ -117,6 +118,7 @@ FAR struct tcp_conn_s *tcp_findlistener(FAR union ip_binding_u *uaddr, { /* Yes.. we found a listener on this port */ + tcp_conn_list_unlock(); return conn; } } @@ -133,6 +135,7 @@ FAR struct tcp_conn_s *tcp_findlistener(FAR union ip_binding_u *uaddr, { /* Yes.. we found a listener on this port */ + tcp_conn_list_unlock(); return conn; } } @@ -142,6 +145,7 @@ FAR struct tcp_conn_s *tcp_findlistener(FAR union ip_binding_u *uaddr, /* No listener for this port */ + tcp_conn_list_unlock(); return NULL; } @@ -165,7 +169,7 @@ int tcp_unlisten(FAR struct tcp_conn_s *conn) int ndx; int ret = -EINVAL; - net_lock(); + tcp_conn_list_lock(); for (ndx = 0; ndx < CONFIG_NET_MAX_LISTENPORTS; ndx++) { if (tcp_listenports[ndx] == conn) @@ -176,7 +180,7 @@ int tcp_unlisten(FAR struct tcp_conn_s *conn) } } - net_unlock(); + tcp_conn_list_unlock(); return ret; } @@ -200,7 +204,7 @@ int tcp_listen(FAR struct tcp_conn_s *conn) * is accessed from event processing logic as well. */ - net_lock(); + tcp_conn_list_lock(); /* First, check if there is already a socket listening on this port */ @@ -239,7 +243,7 @@ int tcp_listen(FAR struct tcp_conn_s *conn) } } - net_unlock(); + tcp_conn_list_unlock(); return ret; } diff --git a/net/tcp/tcp_monitor.c b/net/tcp/tcp_monitor.c index bccd87349c2..540607aa3ca 100644 --- a/net/tcp/tcp_monitor.c +++ b/net/tcp/tcp_monitor.c @@ -34,6 +34,7 @@ #include "devif/devif.h" #include "socket/socket.h" +#include "utils/utils.h" #include "tcp/tcp.h" #ifdef NET_TCP_HAVE_STACK @@ -203,8 +204,6 @@ static void tcp_shutdown_monitor(FAR struct tcp_conn_s *conn, uint16_t flags) * are informed of the loss of connection event. */ - net_lock(); - /* Free all allocated connection event callback structures */ while (conn->connevents != NULL) @@ -213,8 +212,6 @@ static void tcp_shutdown_monitor(FAR struct tcp_conn_s *conn, uint16_t flags) &conn->connevents, &conn->connevents_tail); } - - net_unlock(); } /**************************************************************************** @@ -250,8 +247,6 @@ int tcp_start_monitor(FAR struct socket *psock) conn = psock->s_conn; - net_lock(); - /* Non-blocking connection ? */ nonblock_conn = (conn->tcpstateflags == TCP_SYN_SENT && @@ -277,7 +272,6 @@ int tcp_start_monitor(FAR struct socket *psock) if (conn->tcpstateflags == TCP_CLOSED || conn->tcpstateflags == TCP_LAST_ACK) { - net_unlock(); return OK; } @@ -285,7 +279,6 @@ int tcp_start_monitor(FAR struct socket *psock) * because the socket was already disconnected. */ - net_unlock(); return -ENOTCONN; } @@ -293,6 +286,7 @@ int tcp_start_monitor(FAR struct socket *psock) * the network goes down. */ + conn_dev_lock(&conn->sconn, conn->dev); cb = devif_callback_alloc(conn->dev, &conn->connevents, &conn->connevents_tail); @@ -310,7 +304,7 @@ int tcp_start_monitor(FAR struct socket *psock) } } - net_unlock(); + conn_dev_unlock(&conn->sconn, conn->dev); return OK; } diff --git a/net/tcp/tcp_netpoll.c b/net/tcp/tcp_netpoll.c index 75ecb86649f..0c71ec8d976 100644 --- a/net/tcp/tcp_netpoll.c +++ b/net/tcp/tcp_netpoll.c @@ -39,6 +39,7 @@ #include "netdev/netdev.h" #include "socket/socket.h" #include "inet/inet.h" +#include "utils/utils.h" #include "tcp/tcp.h" /**************************************************************************** @@ -207,18 +208,17 @@ int tcp_pollsetup(FAR struct socket *psock, FAR struct pollfd *fds) /* Some of the following must be atomic */ - net_lock(); - conn = psock->s_conn; /* Sanity check */ if (!conn || !fds) { - ret = -EINVAL; - goto errout_with_lock; + return -EINVAL; } + conn_dev_lock(&conn->sconn, conn->dev); + /* Non-blocking connection ? */ nonblock_conn = ((conn->tcpstateflags == TCP_ALLOCATED || @@ -388,7 +388,7 @@ notify: poll_notify(&fds, 1, eventset); errout_with_lock: - net_unlock(); + conn_dev_unlock(&conn->sconn, conn->dev); return ret; } @@ -415,18 +415,17 @@ int tcp_pollteardown(FAR struct socket *psock, FAR struct pollfd *fds) /* Some of the following must be atomic */ - net_lock(); - conn = psock->s_conn; /* Sanity check */ if (!conn || !fds->priv) { - net_unlock(); return -EINVAL; } + conn_dev_lock(&conn->sconn, conn->dev); + /* Recover the socket descriptor poll state info from the poll structure */ info = (FAR struct tcp_poll_s *)fds->priv; @@ -446,7 +445,7 @@ int tcp_pollteardown(FAR struct socket *psock, FAR struct pollfd *fds) info->conn = NULL; } - net_unlock(); + conn_dev_unlock(&conn->sconn, conn->dev); return OK; } diff --git a/net/tcp/tcp_recvfrom.c b/net/tcp/tcp_recvfrom.c index ab2a51fa5e6..271bcaa83e9 100644 --- a/net/tcp/tcp_recvfrom.c +++ b/net/tcp/tcp_recvfrom.c @@ -42,8 +42,9 @@ #include "netdev/netdev.h" #include "devif/devif.h" -#include "tcp/tcp.h" #include "socket/socket.h" +#include "utils/utils.h" +#include "tcp/tcp.h" /**************************************************************************** * Private Types @@ -805,6 +806,7 @@ static ssize_t tcp_recvfrom_one(FAR struct tcp_conn_s *conn, FAR void *buf, info.tc_conn = conn; info.tc_cb = &state.ir_cb; info.tc_sem = &state.ir_sem; + conn_dev_unlock(&conn->sconn, conn->dev); tls_cleanup_push(tls_get_info(), tcp_callback_cleanup, &info); /* Wait for either the receive to complete or for an @@ -815,6 +817,7 @@ static ssize_t tcp_recvfrom_one(FAR struct tcp_conn_s *conn, FAR void *buf, ret = net_sem_timedwait(&state.ir_sem, _SO_TIMEOUT(conn->sconn.s_rcvtimeo)); tls_cleanup_pop(tls_get_info(), 0); + conn_dev_lock(&conn->sconn, conn->dev); if (ret == -ETIMEDOUT) { ret = -EAGAIN; @@ -839,7 +842,9 @@ static ssize_t tcp_recvfrom_one(FAR struct tcp_conn_s *conn, FAR void *buf, if (tcp_should_send_recvwindow(conn)) { + conn_unlock(&conn->sconn); netdev_txnotify_dev(conn->dev); + conn_lock(&conn->sconn); } tcp_notify_recvcpu(conn); @@ -880,9 +885,8 @@ ssize_t psock_tcp_recvfrom(FAR struct socket *psock, FAR struct msghdr *msg, ssize_t ret = 0; int i; - net_lock(); - conn = psock->s_conn; + conn_dev_lock(&conn->sconn, conn->dev); for (i = 0; i < msg->msg_iovlen; i++) { FAR void *buf = msg->msg_iov[i].iov_base; @@ -909,7 +913,7 @@ ssize_t psock_tcp_recvfrom(FAR struct socket *psock, FAR struct msghdr *msg, } } - net_unlock(); + conn_dev_unlock(&conn->sconn, conn->dev); return nrecv ? nrecv : ret; } diff --git a/net/tcp/tcp_send_buffered.c b/net/tcp/tcp_send_buffered.c index 49bc42a186d..8060698ee9d 100644 --- a/net/tcp/tcp_send_buffered.c +++ b/net/tcp/tcp_send_buffered.c @@ -1409,7 +1409,7 @@ ssize_t psock_tcp_send(FAR struct socket *psock, FAR const void *buf, size_t chunk_len = len; ssize_t chunk_result; - net_lock(); + conn_dev_lock(&conn->sconn, conn->dev); /* Now that we have the network locked, we need to check the connection * state again to ensure the connection is still valid. @@ -1469,11 +1469,13 @@ ssize_t psock_tcp_send(FAR struct socket *psock, FAR const void *buf, info.tc_conn = conn; info.tc_cb = &conn->sndcb; info.tc_sem = &conn->snd_sem; + conn_dev_unlock(&conn->sconn, conn->dev); tls_cleanup_push(tls_get_info(), tcp_callback_cleanup, &info); ret = net_sem_timedwait_uninterruptible(&conn->snd_sem, tcp_send_gettimeout(start, timeout)); tls_cleanup_pop(tls_get_info(), 0); + conn_dev_lock(&conn->sconn, conn->dev); if (ret < 0) { if (ret == -ETIMEDOUT) @@ -1523,8 +1525,10 @@ ssize_t psock_tcp_send(FAR struct socket *psock, FAR const void *buf, } else { + conn_dev_unlock(&conn->sconn, conn->dev); wrb = tcp_wrbuffer_timedalloc(tcp_send_gettimeout(start, timeout)); + conn_dev_lock(&conn->sconn, conn->dev); ninfo("new wrb %p\n", wrb); } @@ -1630,7 +1634,9 @@ ssize_t psock_tcp_send(FAR struct socket *psock, FAR const void *buf, * we risk a deadlock with other threads competing on IOBs. */ + conn_dev_unlock(&conn->sconn, conn->dev); iob = net_iobtimedalloc(true, tcp_send_gettimeout(start, timeout)); + conn_dev_lock(&conn->sconn, conn->dev); if (iob != NULL) { iob_free_chain(iob); @@ -1652,8 +1658,8 @@ ssize_t psock_tcp_send(FAR struct socket *psock, FAR const void *buf, /* Notify the device driver of the availability of TX data */ + conn_dev_unlock(&conn->sconn, conn->dev); tcp_send_txnotify(psock, conn); - net_unlock(); if (chunk_result == 0) { @@ -1699,7 +1705,7 @@ ssize_t psock_tcp_send(FAR struct socket *psock, FAR const void *buf, return result; errout_with_lock: - net_unlock(); + conn_dev_unlock(&conn->sconn, conn->dev); errout: if (result > 0) diff --git a/net/tcp/tcp_send_unbuffered.c b/net/tcp/tcp_send_unbuffered.c index 7d3078c9a71..3fcd5b92d69 100644 --- a/net/tcp/tcp_send_unbuffered.c +++ b/net/tcp/tcp_send_unbuffered.c @@ -55,6 +55,7 @@ #include "icmpv6/icmpv6.h" #include "neighbor/neighbor.h" #include "route/route.h" +#include "utils/utils.h" #include "tcp/tcp.h" /**************************************************************************** @@ -548,7 +549,7 @@ ssize_t psock_tcp_send(FAR struct socket *psock, * ready. */ - net_lock(); + conn_dev_lock(&conn->sconn, conn->dev); /* Now that we have the network locked, we need to check the connection * state again to ensure the connection is still valid. @@ -557,7 +558,7 @@ ssize_t psock_tcp_send(FAR struct socket *psock, if (!_SS_ISCONNECTED(conn->sconn.s_flags)) { nerr("ERROR: No longer connected\n"); - net_unlock(); + conn_dev_unlock(&conn->sconn, conn->dev); ret = -ENOTCONN; goto errout; } @@ -613,11 +614,13 @@ ssize_t psock_tcp_send(FAR struct socket *psock, info.tc_conn = conn; info.tc_cb = &state.snd_cb; info.tc_sem = &state.snd_sem; + conn_dev_unlock(&conn->sconn, conn->dev); tls_cleanup_push(tls_get_info(), tcp_callback_cleanup, &info); ret = net_sem_timedwait(&state.snd_sem, _SO_TIMEOUT(conn->sconn.s_sndtimeo)); tls_cleanup_pop(tls_get_info(), 0); + conn_dev_lock(&conn->sconn, conn->dev); if (ret != -ETIMEDOUT || acked == state.snd_acked) { if (ret == -ETIMEDOUT) @@ -636,7 +639,7 @@ ssize_t psock_tcp_send(FAR struct socket *psock, } nxsem_destroy(&state.snd_sem); - net_unlock(); + conn_dev_unlock(&conn->sconn, conn->dev); /* Check for a errors. Errors are signalled by negative errno values * for the send length diff --git a/net/tcp/tcp_sendfile.c b/net/tcp/tcp_sendfile.c index 0268c16e89c..5c1ff7ee7d9 100644 --- a/net/tcp/tcp_sendfile.c +++ b/net/tcp/tcp_sendfile.c @@ -55,6 +55,7 @@ #include "icmpv6/icmpv6.h" #include "neighbor/neighbor.h" #include "socket/socket.h" +#include "utils/utils.h" #include "tcp/tcp.h" #if defined(CONFIG_NET_SENDFILE) && defined(CONFIG_NET_TCP) && \ @@ -475,7 +476,7 @@ ssize_t tcp_sendfile(FAR struct socket *psock, FAR struct file *infile, * ready. */ - net_lock(); + conn_dev_lock(&conn->sconn, conn->dev); #ifdef CONFIG_NET_TCP_WRITE_BUFFERS conn->sendfile = true; #endif @@ -514,6 +515,7 @@ ssize_t tcp_sendfile(FAR struct socket *psock, FAR struct file *infile, TCP_DISCONN_EVENTS); state.snd_cb->priv = (FAR void *)&state; state.snd_cb->event = sendfile_eventhandler; + conn_dev_unlock(&conn->sconn, conn->dev); /* Notify the device driver of the availability of TX data */ @@ -536,6 +538,7 @@ ssize_t tcp_sendfile(FAR struct socket *psock, FAR struct file *infile, } } + conn_dev_lock(&conn->sconn, conn->dev); tcp_callback_free(conn, state.snd_cb); errout_locked: @@ -543,7 +546,7 @@ errout_locked: #ifdef CONFIG_NET_TCP_WRITE_BUFFERS conn->sendfile = false; #endif - net_unlock(); + conn_dev_unlock(&conn->sconn, conn->dev); /* Return the current file position */ diff --git a/net/tcp/tcp_shutdown.c b/net/tcp/tcp_shutdown.c index 840a2160eef..90cf11b5ab9 100644 --- a/net/tcp/tcp_shutdown.c +++ b/net/tcp/tcp_shutdown.c @@ -37,8 +37,9 @@ #include "netdev/netdev.h" #include "devif/devif.h" -#include "tcp/tcp.h" #include "socket/socket.h" +#include "utils/utils.h" +#include "tcp/tcp.h" /**************************************************************************** * Private Functions @@ -105,11 +106,10 @@ static inline int tcp_send_fin(FAR struct socket *psock) /* Interrupts are disabled here to avoid race conditions */ - net_lock(); - conn = psock->s_conn; DEBUGASSERT(conn != NULL); + conn_dev_lock(&conn->sconn, conn->dev); if ((conn->tcpstateflags == TCP_ESTABLISHED || conn->tcpstateflags == TCP_SYN_SENT || conn->tcpstateflags == TCP_SYN_RCVD || @@ -129,11 +129,13 @@ static inline int tcp_send_fin(FAR struct socket *psock) /* Notify the device driver of the availability of TX data */ + conn_dev_unlock(&conn->sconn, conn->dev); tcp_send_txnotify(psock, conn); + return ret; } out: - net_unlock(); + conn_dev_unlock(&conn->sconn, conn->dev); return ret; } diff --git a/net/tcp/tcp_timer.c b/net/tcp/tcp_timer.c index 5e0fefc1b51..3d175cff33e 100644 --- a/net/tcp/tcp_timer.c +++ b/net/tcp/tcp_timer.c @@ -62,6 +62,7 @@ #include "netdev/netdev.h" #include "devif/devif.h" #include "socket/socket.h" +#include "utils/utils.h" #include "tcp/tcp.h" /**************************************************************************** @@ -145,19 +146,20 @@ static void tcp_timer_expiry(FAR void *arg) { FAR struct tcp_conn_s *conn = NULL; - net_lock(); + tcp_conn_list_lock(); while ((conn = tcp_nextconn(conn)) != NULL) { if (conn == arg) { + tcp_conn_list_unlock(); conn->timeout = true; netdev_txnotify_dev(conn->dev); - break; + return; } } - net_unlock(); + tcp_conn_list_unlock(); } /**************************************************************************** @@ -418,6 +420,7 @@ void tcp_timer(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn) * the connection. */ + conn_lock(&conn->sconn); tcp_ip_select(conn); hdrlen = tcpip_hdrsize(conn); @@ -435,6 +438,7 @@ void tcp_timer(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn) { /* Nothing to be done */ + conn_unlock(&conn->sconn); return; } @@ -537,6 +541,7 @@ void tcp_timer(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn) /* Finally, we must free this TCP connection structure */ conn->crefs = 0; + conn_unlock(&conn->sconn); tcp_free(conn); return; } @@ -824,6 +829,7 @@ void tcp_timer(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn) done: tcp_update_timer(conn); + conn_unlock(&conn->sconn); } #endif /* CONFIG_NET && CONFIG_NET_TCP */ diff --git a/net/tcp/tcp_txdrain.c b/net/tcp/tcp_txdrain.c index 3339ec0233b..2ae4760d876 100644 --- a/net/tcp/tcp_txdrain.c +++ b/net/tcp/tcp_txdrain.c @@ -104,7 +104,7 @@ int tcp_txdrain(FAR struct socket *psock, unsigned int timeout) /* The following needs to be done with the network stable */ - net_lock(); + conn_lock(&conn->sconn); /* Get a notification when the write buffers are drained */ @@ -145,7 +145,9 @@ int tcp_txdrain(FAR struct socket *psock, unsigned int timeout) * wait for it to drain or be be disconnected. */ + conn_dev_unlock(&conn->sconn, conn->dev); ret = net_sem_timedwait_uninterruptible(&waitsem, timeout); + conn_dev_lock(&conn->sconn, conn->dev); /* Tear down the disconnect notifier */ @@ -157,7 +159,7 @@ int tcp_txdrain(FAR struct socket *psock, unsigned int timeout) tcp_notifier_teardown(drain_key); } - net_unlock(); + conn_unlock(&conn->sconn); nxsem_destroy(&waitsem); return ret; }
