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;
 }


Reply via email to