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,
