Add support for rescheduling work with a new deadline and for scheduling on a specific clock tick value.
Signed-off-by: Liam Girdwood liam.r.girdwood@linux.intel.com --- src/include/reef/work.h | 3 ++ src/lib/work.c | 74 ++++++++++++++++++++++++++++++------------------- 2 files changed, 49 insertions(+), 28 deletions(-)
diff --git a/src/include/reef/work.h b/src/include/reef/work.h index 199e46c..516f98f 100644 --- a/src/include/reef/work.h +++ b/src/include/reef/work.h @@ -70,10 +70,13 @@ struct work_queue_timesource {
/* schedule/cancel work on work queue */ void work_schedule(struct work_queue *queue, struct work *w, uint64_t timeout); +void work_reschedule(struct work_queue *queue, struct work *w, uint64_t timeout); void work_cancel(struct work_queue *queue, struct work *work);
/* schedule/cancel work on default system work queue */ void work_schedule_default(struct work *work, uint64_t timeout); +void work_reschedule_default(struct work *work, uint64_t timeout); +void work_reschedule_default_at(struct work *w, uint64_t time); void work_cancel_default(struct work *work);
/* create new work queue */ diff --git a/src/lib/work.c b/src/lib/work.c index cac3deb..c53f029 100644 --- a/src/lib/work.c +++ b/src/lib/work.c @@ -351,64 +351,82 @@ out: spin_unlock_irq(&queue->lock, flags); }
-void work_cancel(struct work_queue *queue, struct work *w) +void work_schedule_default(struct work *w, uint64_t timeout) +{ + work_schedule(queue_, w, timeout); +} + +static void reschedule(struct work_queue *queue, struct work *w, uint64_t time) { + struct work *work; + struct list_item *wlist; uint32_t flags;
spin_lock_irq(&queue->lock, flags);
- /* remove work from list */ - list_item_del(&w->list); + /* check to see if we are already scheduled ? */ + list_for_item(wlist, &queue->work) { + work = container_of(wlist, struct work, list);
+ /* found it */ + if (work == w) + goto found; + } + + /* not found insert work into list */ + list_item_prepend(&w->list, &queue->work); + +found: /* re-calc timer and re-arm */ + w->timeout = time; queue_reschedule(queue);
spin_unlock_irq(&queue->lock, flags); }
-void work_schedule_default(struct work *w, uint64_t timeout) +void work_reschedule(struct work_queue *queue, struct work *w, uint64_t timeout) { - struct work *work; - struct list_item *wlist; - uint32_t flags; + uint64_t time;
- spin_lock_irq(&queue_->lock, flags); - - /* check to see if we are already scheduled ? */ - list_for_item(wlist, &queue_->work) { - work = container_of(wlist, struct work, list); + /* convert timeout micro seconds to CPU clock ticks */ + time = queue->ticks_per_usec * timeout + work_get_timer(queue);
- /* keep original timeout */ - if (work == w) - goto out; - } + reschedule(queue, w, time); +}
- /* convert timeout microsecs to CPU clock ticks */ - w->timeout = queue_->ticks_per_usec * timeout + work_get_timer(queue_); +void work_reschedule_default(struct work *w, uint64_t timeout) +{ + uint64_t time;
- /* insert work into list */ - list_item_prepend(&w->list, &queue_->work); + /* convert timeout micro seconds to CPU clock ticks */ + time = queue_->ticks_per_usec * timeout + work_get_timer(queue_);
- /* re-calc timer and re-arm */ - queue_reschedule(queue_); + reschedule(queue_, w, time); +}
-out: - spin_unlock_irq(&queue_->lock, flags); +void work_reschedule_default_at(struct work *w, uint64_t time) +{ + reschedule(queue_, w, time); }
-void work_cancel_default(struct work *w) +void work_cancel(struct work_queue *queue, struct work *w) { uint32_t flags;
- spin_lock_irq(&queue_->lock, flags); + spin_lock_irq(&queue->lock, flags);
/* remove work from list */ list_item_del(&w->list);
/* re-calc timer and re-arm */ - queue_reschedule(queue_); + queue_reschedule(queue);
- spin_unlock_irq(&queue_->lock, flags); + spin_unlock_irq(&queue->lock, flags); +} + +void work_cancel_default(struct work *w) +{ + work_cancel(queue_, w); }
struct work_queue *work_new_queue(struct work_queue_timesource *ts)