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 eb60667561f918b6b60471a3609b89ac087b13fb
Author: zhanghongyu <[email protected]>
AuthorDate: Fri Jul 4 16:51:08 2025 +0800

    net/utils/net_lock.c: add api to lock conn and netdev
    
    add new api to protect access and operation to conn and dev
    
    Signed-off-by: zhanghongyu <[email protected]>
---
 drivers/net/netdev_upperhalf.c | 12 ++++++---
 include/nuttx/net/net.h        | 27 +++++++++++++++++++
 include/nuttx/net/netdev.h     |  2 ++
 net/netdev/CMakeLists.txt      |  3 ++-
 net/netdev/Make.defs           |  2 +-
 net/netdev/netdev_ioctl.c      | 18 ++++++-------
 net/netdev/netdev_lock.c       | 59 ++++++++++++++++++++++++++++++++++++++++++
 net/netdev/netdev_register.c   |  2 ++
 net/netdev/netdev_unregister.c |  2 ++
 net/utils/net_lock.c           | 40 ++++++++++++++++++++++++++++
 net/utils/utils.h              | 17 ++++++++++++
 11 files changed, 168 insertions(+), 16 deletions(-)

diff --git a/drivers/net/netdev_upperhalf.c b/drivers/net/netdev_upperhalf.c
index 4a0ac06e3c2..04cac299730 100644
--- a/drivers/net/netdev_upperhalf.c
+++ b/drivers/net/netdev_upperhalf.c
@@ -382,7 +382,7 @@ static void netdev_upper_txavail_work(FAR struct 
netdev_upperhalf_s *upper)
 
   /* Ignore the notification if the interface is not yet up */
 
-  net_lock();
+  netdev_lock(dev);
   if (IFF_IS_UP(dev->d_flags) && !upper->txing)
     {
       DEBUGASSERT(dev->d_buf == NULL); /* Make sure: IOB only. */
@@ -392,7 +392,7 @@ static void netdev_upper_txavail_work(FAR struct 
netdev_upperhalf_s *upper)
       upper->txing = false;
     }
 
-  net_unlock();
+  netdev_unlock(dev);
 }
 
 /****************************************************************************
@@ -708,7 +708,7 @@ static void netdev_upper_rxpoll_work(FAR struct 
netdev_upperhalf_s *upper)
 
   /* Loop while receive() successfully retrieves valid Ethernet frames. */
 
-  net_lock();
+  netdev_lock(dev);
   while ((pkt = lower->ops->receive(lower)) != NULL)
     {
       if (!IFF_IS_UP(dev->d_flags))
@@ -763,7 +763,7 @@ static void netdev_upper_rxpoll_work(FAR struct 
netdev_upperhalf_s *upper)
         }
     }
 
-  net_unlock();
+  netdev_unlock(dev);
 }
 
 /****************************************************************************
@@ -1532,7 +1532,9 @@ void netdev_lower_carrier_on(FAR struct 
netdev_lowerhalf_s *dev)
   netdev_upper_vlan_foreach(upper, netdev_lower_carrier_on);
 #endif
 
+  netdev_lock(&dev->netdev);
   netdev_carrier_on(&dev->netdev);
+  netdev_unlock(&dev->netdev);
 }
 
 /****************************************************************************
@@ -1554,7 +1556,9 @@ void netdev_lower_carrier_off(FAR struct 
netdev_lowerhalf_s *dev)
   netdev_upper_vlan_foreach(upper, netdev_lower_carrier_off);
 #endif
 
+  netdev_lock(&dev->netdev);
   netdev_carrier_off(&dev->netdev);
+  netdev_unlock(&dev->netdev);
 }
 
 /****************************************************************************
diff --git a/include/nuttx/net/net.h b/include/nuttx/net/net.h
index af2af577b3e..c16c4c38f2e 100644
--- a/include/nuttx/net/net.h
+++ b/include/nuttx/net/net.h
@@ -206,6 +206,13 @@ struct socket_conn_s
   FAR struct devif_callback_s *list;
   FAR struct devif_callback_s *list_tail;
 
+  /* This lock protects the connection structure.  It is used to prevent
+   * re-entrance into the connection structure while it is being modified.
+   * This mutex is also used to protect the list of callbacks.
+   */
+
+  mutex_t       s_lock;      /* Protect the connection structure */
+
   /* Socket options */
 
 #ifdef CONFIG_NET_SOCKOPTS
@@ -1498,6 +1505,26 @@ int netdev_register(FAR struct net_driver_s *dev, enum 
net_lltype_e lltype);
 
 int netdev_unregister(FAR struct net_driver_s *dev);
 
+/****************************************************************************
+ * Name: netdev_lock
+ *
+ * Description:
+ *   Lock the network device.
+ *
+ ****************************************************************************/
+
+void netdev_lock(FAR struct net_driver_s *dev);
+
+/****************************************************************************
+ * Name: netdev_unlock
+ *
+ * Description:
+ *   Unlock the network device.
+ *
+ ****************************************************************************/
+
+void netdev_unlock(FAR struct net_driver_s *dev);
+
 #undef EXTERN
 #ifdef __cplusplus
 }
diff --git a/include/nuttx/net/netdev.h b/include/nuttx/net/netdev.h
index c69e670d3fb..291aa853a0f 100644
--- a/include/nuttx/net/netdev.h
+++ b/include/nuttx/net/netdev.h
@@ -335,6 +335,8 @@ struct net_driver_s
   char d_ifname[IFNAMSIZ];
 #endif
 
+  rmutex_t d_lock;
+
   /* Drivers interface flags.  See IFF_* definitions in include/net/if.h */
 
   uint32_t d_flags;
diff --git a/net/netdev/CMakeLists.txt b/net/netdev/CMakeLists.txt
index 1ecdc0b9249..ac4e60ebf17 100644
--- a/net/netdev/CMakeLists.txt
+++ b/net/netdev/CMakeLists.txt
@@ -34,7 +34,8 @@ set(SRCS
     netdev_carrier.c
     netdev_default.c
     netdev_verify.c
-    netdev_lladdrsize.c)
+    netdev_lladdrsize.c
+    netdev_lock.c)
 
 if(CONFIG_MM_IOB)
   list(APPEND SRCS netdev_input.c netdev_iob.c)
diff --git a/net/netdev/Make.defs b/net/netdev/Make.defs
index 44a8c26533a..14bbe04fe97 100644
--- a/net/netdev/Make.defs
+++ b/net/netdev/Make.defs
@@ -26,7 +26,7 @@ NETDEV_CSRCS += netdev_register.c netdev_ioctl.c 
netdev_txnotify.c
 NETDEV_CSRCS += netdev_findbyname.c netdev_findbyaddr.c netdev_findbyindex.c
 NETDEV_CSRCS += netdev_count.c netdev_ifconf.c netdev_foreach.c
 NETDEV_CSRCS += netdev_unregister.c netdev_carrier.c netdev_default.c
-NETDEV_CSRCS += netdev_verify.c netdev_lladdrsize.c
+NETDEV_CSRCS += netdev_verify.c netdev_lladdrsize.c netdev_lock.c
 
 ifeq ($(CONFIG_MM_IOB),y)
 NETDEV_CSRCS += netdev_input.c netdev_iob.c
diff --git a/net/netdev/netdev_ioctl.c b/net/netdev/netdev_ioctl.c
index 2945744e06d..61efcac5f0f 100644
--- a/net/netdev/netdev_ioctl.c
+++ b/net/netdev/netdev_ioctl.c
@@ -581,18 +581,18 @@ static int netdev_cell_ioctl(FAR struct socket *psock, 
int cmd,
   int ret = -ENOTTY;
 
   ninfo("cmd: %d\n", cmd);
-  net_lock();
 
   if (_CELLIOCVALID(cmd))
     {
       dev = netdev_findbyname(req->ifr_name);
       if (dev && dev->d_ioctl)
         {
+          netdev_lock(dev);
           ret = dev->d_ioctl(dev, cmd, (unsigned long)(uintptr_t)req);
+          netdev_unlock(dev);
         }
     }
 
-  net_unlock();
   return ret;
 }
 #endif
@@ -830,8 +830,6 @@ static int netdev_ifr_ioctl(FAR struct socket *psock, int 
cmd,
 
   ninfo("cmd: %d\n", cmd);
 
-  net_lock();
-
   /* Execute commands that do not need ifr_name or lifr_name */
 
   switch (cmd)
@@ -886,7 +884,6 @@ static int netdev_ifr_ioctl(FAR struct socket *psock, int 
cmd,
       default:
         if (req == NULL)
           {
-            net_unlock();
             return -ENOTTY;
           }
 
@@ -913,10 +910,11 @@ static int netdev_ifr_ioctl(FAR struct socket *psock, int 
cmd,
 
   if (dev == NULL)
     {
-      net_unlock();
       return ret;
     }
 
+  netdev_lock(dev);
+
   /* Execute commands that need ifr_name or lifr_name */
 
   switch (cmd)
@@ -1322,7 +1320,7 @@ static int netdev_ifr_ioctl(FAR struct socket *psock, int 
cmd,
         break;
     }
 
-  net_unlock();
+  netdev_unlock(dev);
   return ret;
 }
 
@@ -1383,8 +1381,6 @@ static int netdev_imsf_ioctl(FAR struct socket *psock, 
int cmd,
 
   ninfo("cmd: %d\n", cmd);
 
-  net_lock();
-
   /* Execute the command */
 
   switch (cmd)
@@ -1394,6 +1390,7 @@ static int netdev_imsf_ioctl(FAR struct socket *psock, 
int cmd,
           dev = netdev_imsfdev(imsf);
           if (dev)
             {
+              netdev_lock(dev);
               if (imsf->imsf_fmode == MCAST_INCLUDE)
                 {
                   ret = igmp_joingroup(dev, &imsf->imsf_multiaddr);
@@ -1403,6 +1400,8 @@ static int netdev_imsf_ioctl(FAR struct socket *psock, 
int cmd,
                   DEBUGASSERT(imsf->imsf_fmode == MCAST_EXCLUDE);
                   ret = igmp_leavegroup(dev, &imsf->imsf_multiaddr);
                 }
+
+              netdev_unlock(dev);
             }
         }
         break;
@@ -1413,7 +1412,6 @@ static int netdev_imsf_ioctl(FAR struct socket *psock, 
int cmd,
         break;
     }
 
-  net_unlock();
   return ret;
 }
 #endif
diff --git a/net/netdev/netdev_lock.c b/net/netdev/netdev_lock.c
new file mode 100644
index 00000000000..69b80918719
--- /dev/null
+++ b/net/netdev/netdev_lock.c
@@ -0,0 +1,59 @@
+/****************************************************************************
+ * net/netdev/netdev_lock.c
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <nuttx/net/netdev.h>
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: netdev_lock
+ *
+ * Description:
+ *   Lock the network device.
+ *
+ ****************************************************************************/
+
+void netdev_lock(FAR struct net_driver_s *dev)
+{
+  nxrmutex_lock(&dev->d_lock);
+}
+
+/****************************************************************************
+ * Name: netdev_unlock
+ *
+ * Description:
+ *   Unlock the network device.
+ *
+ ****************************************************************************/
+
+void netdev_unlock(FAR struct net_driver_s *dev)
+{
+  nxrmutex_unlock(&dev->d_lock);
+}
diff --git a/net/netdev/netdev_register.c b/net/netdev/netdev_register.c
index 07d388ecca5..e23daa44082 100644
--- a/net/netdev/netdev_register.c
+++ b/net/netdev/netdev_register.c
@@ -425,6 +425,8 @@ int netdev_register(FAR struct net_driver_s *dev, enum 
net_lltype_e lltype)
       dev->d_conncb_tail = NULL;
       dev->d_devcb = NULL;
 
+      nxrmutex_init(&dev->d_lock);
+
       /* We need exclusive access for the following operations */
 
       netdev_list_lock();
diff --git a/net/netdev/netdev_unregister.c b/net/netdev/netdev_unregister.c
index 1ef46c95a0e..c07d8070559 100644
--- a/net/netdev/netdev_unregister.c
+++ b/net/netdev/netdev_unregister.c
@@ -163,6 +163,8 @@ int netdev_unregister(FAR struct net_driver_s *dev)
 
       netdev_list_unlock();
 
+      nxrmutex_destroy(&dev->d_lock);
+
 #if CONFIG_NETDEV_STATISTICS_LOG_PERIOD > 0
       work_cancel_sync(NETDEV_STATISTICS_WORK, &dev->d_statistics.logwork);
 #endif
diff --git a/net/utils/net_lock.c b/net/utils/net_lock.c
index de27e3bc44d..0a2037ca431 100644
--- a/net/utils/net_lock.c
+++ b/net/utils/net_lock.c
@@ -465,3 +465,43 @@ FAR struct iob_s *net_ioballoc(bool throttled)
   return net_iobtimedalloc(throttled, UINT_MAX);
 }
 #endif
+
+/****************************************************************************
+ * Name: conn_lock, conn_unlock, conn_dev_lock, conn_dev_unlock
+ *
+ * Description:
+ *   Lock and unlock the connection and device.
+ *
+ ****************************************************************************/
+
+void conn_lock(FAR struct socket_conn_s *sconn)
+{
+  nxmutex_lock(&sconn->s_lock);
+}
+
+void conn_unlock(FAR struct socket_conn_s *sconn)
+{
+  nxmutex_unlock(&sconn->s_lock);
+}
+
+void conn_dev_lock(FAR struct socket_conn_s *sconn,
+                   FAR struct net_driver_s *dev)
+{
+  if (dev != NULL)
+    {
+      netdev_lock(dev);
+    }
+
+  nxmutex_lock(&sconn->s_lock);
+}
+
+void conn_dev_unlock(FAR struct socket_conn_s *sconn,
+                     FAR struct net_driver_s *dev)
+{
+  nxmutex_unlock(&sconn->s_lock);
+
+  if (dev != NULL)
+    {
+      netdev_unlock(dev);
+    }
+}
diff --git a/net/utils/utils.h b/net/utils/utils.h
index 2aec120b1ed..0eacf0a59b7 100644
--- a/net/utils/utils.h
+++ b/net/utils/utils.h
@@ -606,6 +606,23 @@ uint16_t icmpv6_chksum(FAR struct net_driver_s *dev, 
unsigned int iplen);
 FAR void *cmsg_append(FAR struct msghdr *msg, int level, int type,
                       FAR void *value, int value_len);
 
+/****************************************************************************
+ * Name: conn_lock, conn_unlock, conn_dev_lock, conn_dev_unlock
+ *
+ * Description:
+ *   Lock and unlock the connection and device.
+ *
+ ****************************************************************************/
+
+void conn_lock(FAR struct socket_conn_s *sconn);
+void conn_unlock(FAR struct socket_conn_s *sconn);
+
+void conn_dev_lock(FAR struct socket_conn_s *sconn,
+                   FAR struct net_driver_s *dev);
+
+void conn_dev_unlock(FAR struct socket_conn_s *sconn,
+                     FAR struct net_driver_s *dev);
+
 #undef EXTERN
 #ifdef __cplusplus
 }

Reply via email to