From a32be944ac98e91630d46a25927b4b9d670b683a Mon Sep 17 00:00:00 2001 From: Bartosz Kokoszko Date: Tue, 19 Mar 2019 10:46:07 +0100 Subject: [PATCH] schedule: ll: refinement low latency queue I've removed queue per priority in low latency scheduler. Now there is only one queue for all priorities. Scheduler adds tasks to queue in descending order based on ther priority. Signed-off-by: Bartosz Kokoszko --- src/include/sof/ll_schedule.h | 3 - src/lib/ll_schedule.c | 138 +++++++++++++++++----------------- 2 files changed, 71 insertions(+), 70 deletions(-) diff --git a/src/include/sof/ll_schedule.h b/src/include/sof/ll_schedule.h index d8d3b478b6f5..40ee9edc3e19 100644 --- a/src/include/sof/ll_schedule.h +++ b/src/include/sof/ll_schedule.h @@ -43,9 +43,6 @@ struct work_queue; -/* range of priorities (0 - SOF_TASK_PRI_COUNT) */ -#define LL_PRIORITIES SOF_TASK_PRI_COUNT - #define ll_sch_set_pdata(task, data) \ task->private = data diff --git a/src/lib/ll_schedule.c b/src/lib/ll_schedule.c index 18e53c987386..f5f46e1c02f0 100644 --- a/src/lib/ll_schedule.c +++ b/src/lib/ll_schedule.c @@ -63,7 +63,7 @@ */ struct ll_schedule_data { - struct list_item work[LL_PRIORITIES]; /* list of ll per priority */ + struct list_item tasks; /* list of ll tasks */ uint64_t timeout; /* timeout for next queue run */ uint32_t window_size; /* window size for pending ll */ spinlock_t lock; @@ -141,40 +141,36 @@ static int is_ll_pending(struct ll_schedule_data *queue) uint64_t win_end; uint64_t win_start; int pending_count = 0; - int i; /* get the current valid window of work */ win_end = ll_get_timer(queue); win_start = win_end - queue->window_size; - /* check every priority level */ - for (i = (LL_PRIORITIES - 1); i >= 0; i--) { - /* mark each valid work item in this time period as pending */ - list_for_item(wlist, &queue->work[i]) { - ll_task = container_of(wlist, struct task, list); - - /* correct the pending flag window for overflow */ - if (win_end > win_start) { - /* mark pending work */ - if (ll_task->start >= win_start && - ll_task->start <= win_end) { - ll_task->state = - SOF_TASK_STATE_PENDING; - pending_count++; - } else { - ll_task->state = 0; - } + /* mark each valid work item in this time period as pending */ + list_for_item(wlist, &queue->tasks) { + ll_task = container_of(wlist, struct task, list); + + /* correct the pending flag window for overflow */ + if (win_end > win_start) { + /* mark pending work */ + if (ll_task->start >= win_start && + ll_task->start <= win_end) { + ll_task->state = + SOF_TASK_STATE_PENDING; + pending_count++; } else { - /* mark pending work */ - if ((ll_task->start <= win_end || - (ll_task->start >= win_start && - ll_task->start < ULONG_LONG_MAX))) { - ll_task->state = - SOF_TASK_STATE_PENDING; - pending_count++; - } else { - ll_task->state = 0; - } + ll_task->state = 0; + } + } else { + /* mark pending work */ + if ((ll_task->start <= win_end || + (ll_task->start >= win_start && + ll_task->start < ULONG_LONG_MAX))) { + ll_task->state = + SOF_TASK_STATE_PENDING; + pending_count++; + } else { + ll_task->state = 0; } } } @@ -203,8 +199,7 @@ static inline void ll_next_timeout(struct ll_schedule_data *queue, } /* run all pending work */ -static void run_ll(struct ll_schedule_data *queue, uint32_t *flags, - uint32_t priority) +static void run_ll(struct ll_schedule_data *queue, uint32_t *flags) { struct list_item *wlist; struct list_item *tlist; @@ -213,7 +208,7 @@ static void run_ll(struct ll_schedule_data *queue, uint32_t *flags, int cpu = cpu_get_id(); /* check each work item in queue for pending */ - list_for_item_safe(wlist, tlist, &queue->work[priority]) { + list_for_item_safe(wlist, tlist, &queue->tasks) { ll_task = container_of(wlist, struct task, list); /* run work if its pending and remove from the queue */ @@ -263,28 +258,24 @@ static void queue_recalc_timers(struct ll_schedule_data *queue, uint64_t delta_ticks; uint64_t delta_msecs; uint64_t current; - int i; /* get current time */ current = ll_get_timer(queue); - /* recalculate for each priority level */ - for (i = (LL_PRIORITIES - 1); i >= 0; i--) { - /* recalculate timers for each work item */ - list_for_item(wlist, &queue->work[i]) { - ll_task = container_of(wlist, struct task, list); - delta_ticks = calc_delta_ticks(current, ll_task->start); - delta_msecs = delta_ticks / - clk_data->old_ticks_per_msec; - - /* is work within next msec, then schedule it now */ - if (delta_msecs > 0) - ll_task->start = current + - queue->ticks_per_msec * delta_msecs; - else - ll_task->start = current + - (queue->ticks_per_msec >> 3); - } + /* recalculate timers for each work item */ + list_for_item(wlist, &queue->tasks) { + ll_task = container_of(wlist, struct task, list); + delta_ticks = calc_delta_ticks(current, ll_task->start); + delta_msecs = delta_ticks / + clk_data->old_ticks_per_msec; + + /* is work within next msec, then schedule it now */ + if (delta_msecs > 0) + ll_task->start = current + + queue->ticks_per_msec * delta_msecs; + else + ll_task->start = current + + (queue->ticks_per_msec >> 3); } } @@ -330,7 +321,6 @@ static void queue_run(void *data) { struct ll_schedule_data *queue = (struct ll_schedule_data *)data; uint32_t flags; - int i; timer_disable(&queue->ts->timer); @@ -338,9 +328,7 @@ static void queue_run(void *data) /* run work if there is any pending */ if (is_ll_pending(queue)) { - /* run for each priority level */ - for (i = (LL_PRIORITIES - 1); i >= 0; i--) - run_ll(queue, &flags, i); + run_ll(queue, &flags); } /* re-calc timer and re-arm */ @@ -374,6 +362,28 @@ static void ll_notify(int message, void *data, void *event_data) spin_unlock_irq(&queue->lock, flags); } +static inline void insert_task_to_queue(struct task *w, + struct list_item *q_list) +{ + struct task *ll_task; + struct list_item *wlist; + + /* works are adding to queue in order */ + list_for_item(wlist, q_list) { + ll_task = container_of(wlist, struct task, list); + if (w->priority >= ll_task->priority) { + list_item_append(&w->list, &ll_task->list); + return; + } + } + + /* if task has not been added, means that it has the lowest + * priority in queue and it should be added at the end of the list + */ + list_item_append(&w->list, q_list); + return; +} + static void ll_schedule(struct ll_schedule_data *queue, struct task *w, uint64_t start) { @@ -385,7 +395,7 @@ static void ll_schedule(struct ll_schedule_data *queue, struct task *w, spin_lock_irq(&queue->lock, flags); /* check to see if we are already scheduled ? */ - list_for_item(wlist, &queue->work[w->priority]) { + list_for_item(wlist, &queue->tasks) { ll_task = container_of(wlist, struct task, list); /* keep original start */ @@ -403,7 +413,7 @@ static void ll_schedule(struct ll_schedule_data *queue, struct task *w, w->start += ll_shared_ctx->last_tick; /* insert work into list */ - list_item_prepend(&w->list, &queue->work[w->priority]); + insert_task_to_queue(w, &queue->tasks); ll_set_timer(queue); @@ -429,7 +439,7 @@ static void reschedule(struct ll_schedule_data *queue, struct task *w, spin_lock_irq(&queue->lock, flags); /* check to see if we are already scheduled */ - list_for_item(wlist, &queue->work[w->priority]) { + list_for_item(wlist, &queue->tasks) { ll_task = container_of(wlist, struct task, list); /* found it */ @@ -437,8 +447,7 @@ static void reschedule(struct ll_schedule_data *queue, struct task *w, goto found; } - /* not found insert work into list */ - list_item_prepend(&w->list, &queue->work[w->priority]); + insert_task_to_queue(w, &queue->tasks); ll_set_timer(queue); @@ -481,7 +490,7 @@ static int schedule_ll_task_cancel(struct task *w) spin_lock_irq(&queue->lock, flags); /* check to see if we are scheduled */ - list_for_item(wlist, &queue->work[w->priority]) { + list_for_item(wlist, &queue->tasks) { ll_task = container_of(wlist, struct task, list); /* found it */ @@ -521,13 +530,10 @@ static void schedule_ll_task_free(struct task *w) static struct ll_schedule_data *work_new_queue(struct timesource_data *ts) { struct ll_schedule_data *queue; - int i; /* init work queue */ queue = rmalloc(RZONE_SYS, SOF_MEM_CAPS_RAM, sizeof(*queue)); - - for (i = 0; i < LL_PRIORITIES; ++i) - list_init(&queue->work[i]); + list_init(&queue->tasks); spinlock_init(&queue->lock); atomic_init(&queue->num_ll, 0); @@ -602,7 +608,6 @@ static void ll_scheduler_free(void) struct ll_schedule_data *queue = (*arch_schedule_get_data())->ll_sch_data; uint32_t flags; - int i; spin_lock_irq(&queue->lock, flags); @@ -610,8 +615,7 @@ static void ll_scheduler_free(void) notifier_unregister(&queue->notifier); - for (i = 0; i < LL_PRIORITIES; ++i) - list_item_del(&queue->work[i]); + list_item_del(&queue->tasks); spin_unlock_irq(&queue->lock, flags); }