This is an automated email from the ASF dual-hosted git repository.

xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 7e5d05f4fdc481c068fc0d1f4c070897812cab28
Author: DuoYuWang <[email protected]>
AuthorDate: Mon Aug 31 13:13:03 2026 +0800

    sched/wqueue: consolidate queue submission paths
    
    Factor the common queueing logic used by work_queue_wq() and
    work_queue_next_wq() into a private helper.
    
    Preserve existing timing semantics: regular work calculates its absolute
    expiration before taking the queue lock, while periodic work advances the
    previous expiration under the lock.
    
    This is a code deduplication change with no public API or behavior changes.
    
    Assisted-by: Codex:GPT-5
    Signed-off-by: DuoYuWang <[email protected]>
---
 sched/wqueue/kwork_queue.c | 153 ++++++++++++++++++++-------------------------
 1 file changed, 69 insertions(+), 84 deletions(-)

diff --git a/sched/wqueue/kwork_queue.c b/sched/wqueue/kwork_queue.c
index 4e36159a66b..6e9b4ac1a07 100644
--- a/sched/wqueue/kwork_queue.c
+++ b/sched/wqueue/kwork_queue.c
@@ -41,18 +41,18 @@
 #ifdef CONFIG_SCHED_WORKQUEUE
 
 /****************************************************************************
- * Public Functions
+ * Private Functions
  ****************************************************************************/
 
 /****************************************************************************
- * Name: work_queue_next/work_queue_next_wq
+ * Name: work_qqueue
  *
  * Description:
- *   Queue work to be performed at a later time based on the last expiration
- *   time. This function must be called in the workqueue callback.
+ *   Queue work on a kernel-mode work queue.  Regular work uses an absolute
+ *   expiration calculated before taking the queue lock.  Periodic work
+ *   advances the previous expiration while holding the lock.
  *
  * Input Parameters:
- *   qid    - The work queue ID (must be HPWORK or LPWORK)
  *   wqueue - The work queue handle
  *   work   - The work structure to queue
  *   worker - The worker callback to be invoked.  The callback will be
@@ -61,19 +61,20 @@
  *            it is invoked.
  *   delay  - Delay (in clock ticks) from the time queue until the worker
  *            is invoked. Zero means to perform the work immediately.
+ *   period - Use the previous expiration as the scheduling reference
  *
  * Returned Value:
  *   Zero on success, a negated errno on failure
  *
  ****************************************************************************/
 
-int work_queue_next_wq(FAR struct kwork_wqueue_s *wqueue,
+static int work_qqueue(FAR struct kwork_wqueue_s *wqueue,
                        FAR struct work_s *work, worker_t worker,
-                       FAR void *arg, clock_t delay)
+                       FAR void *arg, clock_t delay, bool period)
 {
   irqstate_t flags;
+  clock_t expected = 0;
   bool retimer;
-  int ret = OK;
 
   if (wqueue == NULL || work == NULL || worker == NULL ||
       delay < 0 || delay > WDOG_MAX_DELAY)
@@ -81,12 +82,23 @@ int work_queue_next_wq(FAR struct kwork_wqueue_s *wqueue,
       return -EINVAL;
     }
 
+  /* Preserve regular queue timing across lock contention. */
+
+  if (!period)
+    {
+      expected = clock_delay2abstick(delay);
+    }
+
+  /* Interrupts are disabled so that this logic can be called from task
+   * logic or interrupt handling logic.
+   */
+
   flags = spin_lock_irqsave(&wqueue->lock);
 
   if (wqueue->exit)
     {
-      ret = -ESHUTDOWN;
-      goto out;
+      spin_unlock_irqrestore(&wqueue->lock, flags);
+      return -ESHUTDOWN;
     }
 
   /* Remove a previous pending instance before requeueing it. */
@@ -97,9 +109,17 @@ int work_queue_next_wq(FAR struct kwork_wqueue_s *wqueue,
 
   work->worker = worker; /* Work callback. non-NULL means queued */
   work->arg    = arg;    /* Callback argument */
-  work->qtime += delay;  /* Expected time based on last expiration time */
 
-  if (delay)
+  if (period)
+    {
+      work->qtime += delay;
+    }
+  else
+    {
+      work->qtime = expected;
+    }
+
+  if (delay > 0)
     {
       /* Insert to the pending list of the wqueue. */
 
@@ -124,17 +144,50 @@ int work_queue_next_wq(FAR struct kwork_wqueue_s *wqueue,
       work_timer_reset(wqueue);
     }
 
-out:
   spin_unlock_irqrestore(&wqueue->lock, flags);
 
-  if (ret == OK && !delay)
+  if (delay == 0)
     {
       /* Immediately wake up the worker thread. */
 
       nxsem_post(&wqueue->sem);
     }
 
-  return ret;
+  return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: work_queue_next/work_queue_next_wq
+ *
+ * Description:
+ *   Queue work to be performed at a later time based on the last expiration
+ *   time. This function must be called in the workqueue callback.
+ *
+ * Input Parameters:
+ *   qid    - The work queue ID (must be HPWORK or LPWORK)
+ *   wqueue - The work queue handle
+ *   work   - The work structure to queue
+ *   worker - The worker callback to be invoked.  The callback will be
+ *            invoked on the worker thread of execution.
+ *   arg    - The argument that will be passed to the worker callback when
+ *            it is invoked.
+ *   delay  - Delay (in clock ticks) from the time queue until the worker
+ *            is invoked. Zero means to perform the work immediately.
+ *
+ * Returned Value:
+ *   Zero on success, a negated errno on failure
+ *
+ ****************************************************************************/
+
+int work_queue_next_wq(FAR struct kwork_wqueue_s *wqueue,
+                       FAR struct work_s *work, worker_t worker,
+                       FAR void *arg, clock_t delay)
+{
+  return work_qqueue(wqueue, work, worker, arg, delay, true);
 }
 
 int work_queue_next(int qid, FAR struct work_s *work, worker_t worker,
@@ -177,75 +230,7 @@ int work_queue_wq(FAR struct kwork_wqueue_s *wqueue,
                   FAR struct work_s *work, worker_t worker,
                   FAR void *arg, clock_t delay)
 {
-  irqstate_t flags;
-  clock_t expected;
-  bool retimer;
-
-  if (wqueue == NULL || work == NULL || worker == NULL ||
-      delay < 0 || delay > WDOG_MAX_DELAY)
-    {
-      return -EINVAL;
-    }
-
-  expected = clock_delay2abstick(delay);
-
-  /* Interrupts are disabled so that this logic can be called from with
-   * task logic or from interrupt handling logic.
-   */
-
-  flags = spin_lock_irqsave(&wqueue->lock);
-
-  if (wqueue->exit)
-    {
-      spin_unlock_irqrestore(&wqueue->lock, flags);
-      return -ESHUTDOWN;
-    }
-
-  /* Ensure the work has been removed. */
-
-  retimer = work_available(work) ? false : work_remove(wqueue, work);
-
-  /* Initialize the work structure. */
-
-  work->worker = worker;   /* Work callback. non-NULL means queued */
-  work->arg    = arg;      /* Callback argument */
-  work->qtime  = expected; /* Expected time */
-
-  if (delay)
-    {
-      /* Insert to the pending list of the wqueue. */
-
-      if (work_insert_pending(wqueue, work))
-        {
-          /* Start the timer if the work is the earliest expired work. */
-
-          retimer = false;
-          wd_start_abstick(&wqueue->timer, work->qtime,
-                           work_timer_expired, (wdparm_t)wqueue);
-        }
-    }
-  else
-    {
-      /* Insert to the expired list of the wqueue. */
-
-      list_add_tail(&wqueue->expired, &work->node);
-    }
-
-  if (retimer)
-    {
-      work_timer_reset(wqueue);
-    }
-
-  spin_unlock_irqrestore(&wqueue->lock, flags);
-
-  if (!delay)
-    {
-      /* Immediately wake up the worker thread. */
-
-      nxsem_post(&wqueue->sem);
-    }
-
-  return 0;
+  return work_qqueue(wqueue, work, worker, arg, delay, false);
 }
 
 int work_queue(int qid, FAR struct work_s *work, worker_t worker,

Reply via email to