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();
