This is an automated email from the ASF dual-hosted git repository. acassis pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit df183b668272dafb7e3e236fcbdf6d87ede6f3b9 Author: ouyangxiangzhen <ouyangxiangz...@xiaomi.com> AuthorDate: Wed Jun 4 17:11:49 2025 +0800 sched/wqueue: Remove the work_queue_period. For simplicity, better performance and lower memory-overhead, this commit replaced the periodical workqueue APIs with the more expressive work_queue_next. The work_queue_next restarts work based on the last expiration time. Signed-off-by: ouyangxiangzhen <ouyangxiangz...@xiaomi.com> --- include/nuttx/wqueue.h | 25 +++------- sched/wqueue/kwork_queue.c | 118 ++++++++++++++++++++++++++++---------------- sched/wqueue/kwork_thread.c | 25 +--------- 3 files changed, 86 insertions(+), 82 deletions(-) diff --git a/include/nuttx/wqueue.h b/include/nuttx/wqueue.h index 6eaefff597..f9b3470efe 100644 --- a/include/nuttx/wqueue.h +++ b/include/nuttx/wqueue.h @@ -251,7 +251,6 @@ struct work_s { struct list_node node; /* Implements a double linked list */ clock_t qtime; /* Time work queued */ - clock_t period; /* Periodical delay ticks */ worker_t worker; /* Work callback */ FAR void *arg; /* Callback argument */ }; @@ -411,18 +410,11 @@ int work_queue_wq(FAR struct kwork_wqueue_s *wqueue, FAR void *arg, clock_t delay); /**************************************************************************** - * Name: work_queue_period/work_queue_period_wq + * Name: work_queue_next/work_queue_next_wq * * Description: - * Queue work to be performed periodically. All queued work will be - * performed on the worker thread of execution (not the caller's). - * - * The work structure is allocated and must be initialized to all zero by - * the caller. Otherwise, the work structure is completely managed by the - * work queue logic. The caller should never modify the contents of the - * work queue structure directly. If work_queue() is called before the - * previous work has been performed and removed from the queue, then any - * pending work will be canceled and lost. + * 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) @@ -434,18 +426,17 @@ int work_queue_wq(FAR struct kwork_wqueue_s *wqueue, * 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 - Period (in clock ticks). * * Returned Value: * Zero on success, a negated errno on failure * ****************************************************************************/ -int work_queue_period(int qid, FAR struct work_s *work, worker_t worker, - FAR void *arg, clock_t delay, clock_t period); -int work_queue_period_wq(FAR struct kwork_wqueue_s *wqueue, - FAR struct work_s *work, worker_t worker, - FAR void *arg, clock_t delay, clock_t period); +int work_queue_next(int qid, FAR struct work_s *work, worker_t worker, + FAR void *arg, clock_t delay); +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); /**************************************************************************** * Name: work_queue_pri diff --git a/sched/wqueue/kwork_queue.c b/sched/wqueue/kwork_queue.c index ede28bb65c..75b5a7f5fd 100644 --- a/sched/wqueue/kwork_queue.c +++ b/sched/wqueue/kwork_queue.c @@ -45,18 +45,11 @@ ****************************************************************************/ /**************************************************************************** - * Name: work_queue_period/work_queue_period_wq + * Name: work_queue_next/work_queue_next_wq * * Description: - * Queue work to be performed periodically. All queued work will be - * performed on the worker thread of execution (not the caller's). - * - * The work structure is allocated and must be initialized to all zero by - * the caller. Otherwise, the work structure is completely managed by the - * work queue logic. The caller should never modify the contents of the - * work queue structure directly. If work_queue() is called before the - * previous work has been performed and removed from the queue, then any - * pending work will be canceled and lost. + * 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) @@ -68,20 +61,17 @@ * 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 - Period (in clock ticks). * * Returned Value: * Zero on success, a negated errno on failure * ****************************************************************************/ -int work_queue_period_wq(FAR struct kwork_wqueue_s *wqueue, - FAR struct work_s *work, worker_t worker, - FAR void *arg, clock_t delay, clock_t period) +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) { irqstate_t flags; - clock_t expected; - bool retimer; if (wqueue == NULL || work == NULL || worker == NULL || delay > WDOG_MAX_DELAY) @@ -89,25 +79,14 @@ int work_queue_period_wq(FAR struct kwork_wqueue_s *wqueue, return -EINVAL; } - expected = clock_delay2abstick(delay); + /* Initialize the work structure. */ - /* Interrupts are disabled so that this logic can be called from with - * task logic or from interrupt handling logic. - */ + work->worker = worker; /* Work callback. non-NULL means queued */ + work->arg = arg; /* Callback argument */ + work->qtime += delay; /* Expected time based on last expiration time */ flags = spin_lock_irqsave(&wqueue->lock); - /* 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 */ - work->period = period; /* Periodical delay */ - if (delay) { /* Insert to the pending list of the wqueue. */ @@ -116,7 +95,6 @@ int work_queue_period_wq(FAR struct kwork_wqueue_s *wqueue, { /* 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); } @@ -128,11 +106,6 @@ int work_queue_period_wq(FAR struct kwork_wqueue_s *wqueue, list_add_tail(&wqueue->expired, &work->node); } - if (retimer) - { - work_timer_reset(wqueue); - } - spin_unlock_irqrestore(&wqueue->lock, flags); if (!delay) @@ -145,11 +118,10 @@ int work_queue_period_wq(FAR struct kwork_wqueue_s *wqueue, return 0; } -int work_queue_period(int qid, FAR struct work_s *work, worker_t worker, - FAR void *arg, clock_t delay, clock_t period) +int work_queue_next(int qid, FAR struct work_s *work, worker_t worker, + FAR void *arg, clock_t delay) { - return work_queue_period_wq(work_qid2wq(qid), work, worker, - arg, delay, period); + return work_queue_next_wq(work_qid2wq(qid), work, worker, arg, delay); } /**************************************************************************** @@ -186,7 +158,69 @@ int work_queue_wq(FAR struct kwork_wqueue_s *wqueue, FAR struct work_s *work, worker_t worker, FAR void *arg, clock_t delay) { - return work_queue_period_wq(wqueue, work, worker, arg, delay, 0); + irqstate_t flags; + clock_t expected; + bool retimer; + + if (wqueue == NULL || work == NULL || worker == NULL || + 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); + + /* 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; } int work_queue(int qid, FAR struct work_s *work, worker_t worker, diff --git a/sched/wqueue/kwork_thread.c b/sched/wqueue/kwork_thread.c index be1a77185e..a46c050528 100644 --- a/sched/wqueue/kwork_thread.c +++ b/sched/wqueue/kwork_thread.c @@ -239,30 +239,9 @@ static int work_thread(int argc, FAR char *argv[]) arg = work->arg; - /* Check whether the work is periodic. */ + /* Return the work structure ownership to the work owner. */ - if (work->period != 0) - { - /* Calculate next expiration qtime. */ - - work->qtime += work->period; - - /* Enqueue to the waiting queue */ - - if (work_insert_pending(wqueue, work)) - { - /* We should reset timer if the work is the earliest. */ - - wd_start_abstick(&wqueue->timer, work->qtime, - work_timer_expired, (wdparm_t)wqueue); - } - } - else - { - /* Return the work structure ownership to the work owner. */ - - work->worker = NULL; - } + work->worker = NULL; /* Mark the thread busy */