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 f8ecbd781cfd3d7ece9ee4667c1b019724057f39
Author: wangchen <[email protected]>
AuthorDate: Thu May 29 09:32:59 2025 +0800

    udp:Resolve UDP exit delay due to high CPU usage
    
    Optimize the processing logic of UDP TXDrain, reduce thread switching,
    and improve timeliness and CPU consumption.
    
    Signed-off-by: wangchen <[email protected]>
---
 net/udp/udp.h                 | 58 +---------------------------
 net/udp/udp_notifier.c        | 88 -------------------------------------------
 net/udp/udp_sendto_buffered.c | 11 ++++--
 net/udp/udp_txdrain.c         | 51 +++----------------------
 4 files changed, 13 insertions(+), 195 deletions(-)

diff --git a/net/udp/udp.h b/net/udp/udp.h
index e0268604584..78314bbbe07 100644
--- a/net/udp/udp.h
+++ b/net/udp/udp.h
@@ -162,6 +162,7 @@ struct udp_conn_s
 #ifdef CONFIG_NET_TIMESTAMP
   int timestamp; /* Nonzero when SO_TIMESTAMP is enabled */
 #endif
+  FAR sem_t *txdrain_sem;
 };
 
 /* This structure supports UDP write buffering.  It is simply a container
@@ -837,38 +838,6 @@ int udp_readahead_notifier_setup(worker_t worker,
                                  FAR void *arg);
 #endif
 
-/****************************************************************************
- * Name: udp_writebuffer_notifier_setup
- *
- * Description:
- *   Set up to perform a callback to the worker function when an UDP write
- *   buffer is emptied.  The worker function will execute on the high
- *   priority worker thread.
- *
- * Input Parameters:
- *   worker - The worker function to execute on the low priority work
- *            queue when data is available in the UDP read-ahead buffer.
- *   conn   - The UDP connection where read-ahead data is needed.
- *   arg    - A user-defined argument that will be available to the worker
- *            function when it runs.
- *
- * Returned Value:
- *   > 0   - The notification is in place.  The returned value is a key that
- *           may be used later in a call to udp_notifier_teardown().
- *   == 0  - There is already buffered read-ahead data.  No notification
- *           will be provided.
- *   < 0   - An unexpected error occurred and no notification will occur.
- *           The returned value is a negated errno value that indicates the
- *           nature of the failure.
- *
- ****************************************************************************/
-
-#ifdef CONFIG_NET_UDP_NOTIFIER
-int udp_writebuffer_notifier_setup(worker_t worker,
-                                   FAR struct udp_conn_s *conn,
-                                   FAR void *arg);
-#endif
-
 /****************************************************************************
  * Name: udp_notifier_teardown
  *
@@ -915,31 +884,6 @@ void udp_notifier_teardown(FAR void *key);
 void udp_readahead_signal(FAR struct udp_conn_s *conn);
 #endif
 
-/****************************************************************************
- * Name: udp_writebuffer_signal
- *
- * Description:
- *   All buffer Tx data has been sent.  Signal all threads waiting for the
- *   write buffers to become empty.
- *
- *   When write buffer becomes empty, *all* of the workers waiting
- *   for that event data will be executed.  If there are multiple workers
- *   waiting for read-ahead data then only the first to execute will get the
- *   data.  Others will need to call udp_writebuffer_notifier_setup() once
- *   again.
- *
- * Input Parameters:
- *   conn  - The UDP connection where read-ahead data was just buffered.
- *
- * Returned Value:
- *   None.
- *
- ****************************************************************************/
-
-#if defined(CONFIG_NET_UDP_WRITE_BUFFERS) && defined(CONFIG_NET_UDP_NOTIFIER)
-void udp_writebuffer_signal(FAR struct udp_conn_s *conn);
-#endif
-
 /****************************************************************************
  * Name: udp_txdrain
  *
diff --git a/net/udp/udp_notifier.c b/net/udp/udp_notifier.c
index bb9b07d255b..7ec20bd8cf4 100644
--- a/net/udp/udp_notifier.c
+++ b/net/udp/udp_notifier.c
@@ -94,64 +94,6 @@ int udp_readahead_notifier_setup(worker_t worker,
   return work_notifier_setup(&info);
 }
 
-/****************************************************************************
- * Name: udp_writebuffer_notifier_setup
- *
- * Description:
- *   Set up to perform a callback to the worker function when an UDP write
- *   buffer is emptied.  The worker function will execute on the high
- *   priority worker thread.
- *
- * Input Parameters:
- *   worker - The worker function to execute on the low priority work
- *            queue when data is available in the UDP read-ahead buffer.
- *   conn  - The UDP connection where read-ahead data is needed.
- *   arg    - A user-defined argument that will be available to the worker
- *            function when it runs.
- *
- * Returned Value:
- *   > 0   - The notification is in place.  The returned value is a key that
- *           may be used later in a call to udp_notifier_teardown().
- *   == 0  - There is already buffered read-ahead data.  No notification
- *           will be provided.
- *   < 0   - An unexpected error occurred and no notification will occur.
- *           The returned value is a negated errno value that indicates the
- *           nature of the failure.
- *
- ****************************************************************************/
-
-int udp_writebuffer_notifier_setup(worker_t worker,
-                                   FAR struct udp_conn_s *conn,
-                                   FAR void *arg)
-{
-#ifdef CONFIG_NET_UDP_WRITE_BUFFERS
-  struct work_notifier_s info;
-
-  DEBUGASSERT(worker != NULL);
-
-  /* If there is already buffered read-ahead data, then return zero without
-   * setting up the notification.
-   */
-
-  if (sq_empty(&conn->write_q))
-    {
-      return 0;
-    }
-
-  /* Otherwise, this is just a simple wrapper around work_notifer_setup(). */
-
-  info.evtype    = WORK_UDP_WRITEBUFFER;
-  info.qid       = LPWORK;
-  info.qualifier = conn;
-  info.arg       = arg;
-  info.worker    = worker;
-
-  return work_notifier_setup(&info);
-#else
-  return 0;
-#endif
-}
-
 /****************************************************************************
  * Name: udp_notifier_teardown
  *
@@ -205,34 +147,4 @@ void udp_readahead_signal(FAR struct udp_conn_s *conn)
   work_notifier_signal(WORK_UDP_READAHEAD, conn);
 }
 
-/****************************************************************************
- * Name: udp_writebuffer_signal
- *
- * Description:
- *   All buffer Tx data has been sent.  Signal all threads waiting for the
- *   write buffers to become empty.
- *
- *   When write buffer becomes empty, *all* of the workers waiting
- *   for that event data will be executed.  If there are multiple workers
- *   waiting for read-ahead data then only the first to execute will get the
- *   data.  Others will need to call tcp_writebuffer_notifier_setup() once
- *   again.
- *
- * Input Parameters:
- *   conn  - The UDP connection where read-ahead data was just buffered.
- *
- * Returned Value:
- *   None.
- *
- ****************************************************************************/
-
-#ifdef CONFIG_NET_UDP_WRITE_BUFFERS
-void udp_writebuffer_signal(FAR struct udp_conn_s *conn)
-{
-  /* This is just a simple wrapper around work_notifier_signal(). */
-
-  work_notifier_signal(WORK_UDP_WRITEBUFFER, conn);
-}
-#endif
-
 #endif /* CONFIG_NET_UDP_NOTIFIER */
diff --git a/net/udp/udp_sendto_buffered.c b/net/udp/udp_sendto_buffered.c
index e9c95038b5e..5dba74a504b 100644
--- a/net/udp/udp_sendto_buffered.c
+++ b/net/udp/udp_sendto_buffered.c
@@ -138,11 +138,14 @@ static void sendto_writebuffer_release(FAR struct 
udp_conn_s *conn)
           conn->sndcb->event = NULL;
           wrb = NULL;
 
-#ifdef CONFIG_NET_UDP_NOTIFIER
-          /* Notify any waiters that the write buffers have been drained. */
+          if (conn->txdrain_sem != NULL)
+            {
+              /* Notify the txdrain semaphore that the write buffer queue
+               * has been drained.
+               */
 
-          udp_writebuffer_signal(conn);
-#endif
+              nxsem_post(conn->txdrain_sem);
+            }
         }
       else
         {
diff --git a/net/udp/udp_txdrain.c b/net/udp/udp_txdrain.c
index 62a04d6157e..b98be298dd9 100644
--- a/net/udp/udp_txdrain.c
+++ b/net/udp/udp_txdrain.c
@@ -41,35 +41,6 @@
 
 #if defined(CONFIG_NET_UDP_WRITE_BUFFERS) && defined(CONFIG_NET_UDP_NOTIFIER)
 
-/****************************************************************************
- * Private Functions
- ****************************************************************************/
-
-/****************************************************************************
- * Name: txdrain_worker
- *
- * Description:
- *   Called with the write buffers have all been sent.
- *
- * Input Parameters:
- *   arg     - The notifier entry.
- *
- * Returned Value:
- *   None.
- *
- ****************************************************************************/
-
-static void txdrain_worker(FAR void *arg)
-{
-  FAR sem_t *waitsem = (FAR sem_t *)arg;
-
-  DEBUGASSERT(waitsem != NULL);
-
-  /* Then just post the semaphore, waking up tcp_txdrain() */
-
-  nxsem_post(waitsem);
-}
-
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
@@ -94,7 +65,7 @@ int udp_txdrain(FAR struct socket *psock, unsigned int 
timeout)
 {
   FAR struct udp_conn_s *conn;
   sem_t waitsem;
-  int ret;
+  int ret = OK;
 
   DEBUGASSERT(psock->s_type == SOCK_DGRAM);
 
@@ -111,24 +82,12 @@ int udp_txdrain(FAR struct socket *psock, unsigned int 
timeout)
   /* The following needs to be done with the network stable */
 
   net_lock();
-  ret = udp_writebuffer_notifier_setup(txdrain_worker, conn, &waitsem);
-  if (ret > 0)
-    {
-      int key = ret;
-
-      /* There is pending write data.. wait for it to drain. */
 
-      tls_cleanup_push(tls_get_info(), udp_notifier_teardown, &key);
+  if (!sq_empty(&conn->write_q))
+    {
+      conn->txdrain_sem = &waitsem;
       ret = net_sem_timedwait_uninterruptible(&waitsem, timeout);
-
-      /* Tear down the notifier (in case we timed out or were canceled) */
-
-      if (ret < 0)
-        {
-          udp_notifier_teardown(&key);
-        }
-
-      tls_cleanup_pop(tls_get_info(), 0);
+      conn->txdrain_sem = NULL;
     }
 
   net_unlock();

Reply via email to