mirror of
https://github.com/apache/nuttx.git
synced 2026-09-06 08:56:32 +00:00
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 <thirteenking.wang@gmail.com>
This commit is contained in:
parent
d2e01b9055
commit
7e5d05f4fd
1 changed files with 118 additions and 133 deletions
|
|
@ -40,6 +40,122 @@
|
|||
|
||||
#ifdef CONFIG_SCHED_WORKQUEUE
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: work_qqueue
|
||||
*
|
||||
* Description:
|
||||
* 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:
|
||||
* 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.
|
||||
* period - Use the previous expiration as the scheduling reference
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success, a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int work_qqueue(FAR struct kwork_wqueue_s *wqueue,
|
||||
FAR struct work_s *work, worker_t worker,
|
||||
FAR void *arg, clock_t delay, bool period)
|
||||
{
|
||||
irqstate_t flags;
|
||||
clock_t expected = 0;
|
||||
bool retimer;
|
||||
|
||||
if (wqueue == NULL || work == NULL || worker == NULL ||
|
||||
delay < 0 || delay > WDOG_MAX_DELAY)
|
||||
{
|
||||
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)
|
||||
{
|
||||
spin_unlock_irqrestore(&wqueue->lock, flags);
|
||||
return -ESHUTDOWN;
|
||||
}
|
||||
|
||||
/* Remove a previous pending instance before requeueing it. */
|
||||
|
||||
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 */
|
||||
|
||||
if (period)
|
||||
{
|
||||
work->qtime += delay;
|
||||
}
|
||||
else
|
||||
{
|
||||
work->qtime = expected;
|
||||
}
|
||||
|
||||
if (delay > 0)
|
||||
{
|
||||
/* 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 == 0)
|
||||
{
|
||||
/* Immediately wake up the worker thread. */
|
||||
|
||||
nxsem_post(&wqueue->sem);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
|
@ -71,70 +187,7 @@ 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;
|
||||
bool retimer;
|
||||
int ret = OK;
|
||||
|
||||
if (wqueue == NULL || work == NULL || worker == NULL ||
|
||||
delay < 0 || delay > WDOG_MAX_DELAY)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
flags = spin_lock_irqsave(&wqueue->lock);
|
||||
|
||||
if (wqueue->exit)
|
||||
{
|
||||
ret = -ESHUTDOWN;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Remove a previous pending instance before requeueing it. */
|
||||
|
||||
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 += delay; /* Expected time based on last expiration 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);
|
||||
}
|
||||
|
||||
out:
|
||||
spin_unlock_irqrestore(&wqueue->lock, flags);
|
||||
|
||||
if (ret == OK && !delay)
|
||||
{
|
||||
/* Immediately wake up the worker thread. */
|
||||
|
||||
nxsem_post(&wqueue->sem);
|
||||
}
|
||||
|
||||
return ret;
|
||||
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,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue