Skip to content

Commit eab7228

Browse files
PoC to improve pipelines startup latency
Signed-off-by: Serhiy Katsyuba <serhiy.katsyuba@intel.com>
1 parent efbc17b commit eab7228

2 files changed

Lines changed: 105 additions & 0 deletions

File tree

src/ipc/ipc4/handler-user.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,7 @@ static int ipc4_set_pipeline_state(struct ipc4_message_request *ipc4)
543543
ipc_compound_pre_start(state.primary.r.type);
544544
ret = ipc4_pipeline_trigger(ppl_icd, cmd, &delayed);
545545
ipc_compound_post_start(state.primary.r.type, ret, delayed);
546+
delayed = false; ///!!!
546547
if (delayed) {
547548
/* To maintain pipeline order for triggers, we must
548549
* do a blocking wait until trigger is processed.

src/schedule/zephyr_ll.c

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ DECLARE_TR_CTX(ll_tr, SOF_UUID(zll_sched_uuid), LOG_LEVEL_INFO);
2626

2727
/* per-scheduler data */
2828
struct zephyr_ll {
29+
struct list_item startup_tasks;
2930
struct list_item tasks; /* list of ll tasks */
3031
unsigned int n_tasks; /* task counter */
3132
struct ll_schedule_domain *ll_domain; /* scheduling domain */
@@ -109,6 +110,9 @@ static void zephyr_ll_task_insert_unlocked(struct zephyr_ll *sch, struct task *t
109110

110111
task->state = SOF_TASK_STATE_QUEUED;
111112

113+
list_item_append(&task->list, &sch->startup_tasks);
114+
115+
#if 0
112116
/*
113117
* Tasks are added into the list in priority order. List order
114118
* defines schedule order. Priority 0 indicates highest
@@ -129,6 +133,7 @@ static void zephyr_ll_task_insert_unlocked(struct zephyr_ll *sch, struct task *t
129133
*/
130134
if (list == &sch->tasks)
131135
list_item_append(&task->list, &sch->tasks);
136+
#endif // 0
132137
}
133138

134139
static void zephyr_ll_task_insert_before_unlocked(struct task *task, struct task *before)
@@ -187,12 +192,67 @@ static void zephyr_ll_run(void *data)
187192
struct zephyr_ll *sch = data;
188193
struct task *task;
189194
struct list_item *list, *tmp, task_head = LIST_INIT(task_head);
195+
struct list_item *list2, removed_startup_task_head = LIST_INIT(removed_startup_task_head);
190196
uint32_t flags;
191197

192198
tr_dbg(&ll_tr, "entry");
193199

194200
zephyr_ll_lock(sch, &flags);
195201

202+
for (list = sch->startup_tasks.next; !list_is_empty(&sch->startup_tasks); list = sch->startup_tasks.next) {
203+
enum task_state state;
204+
struct zephyr_ll_pdata *pdata;
205+
206+
task = container_of(list, struct task, list);
207+
pdata = task->priv_data;
208+
209+
if (task->state == SOF_TASK_STATE_CANCEL) {
210+
list = list->next; ///!!! A BUG IS HEHE???!!!
211+
zephyr_ll_task_done(sch, task);
212+
continue;
213+
}
214+
215+
pdata->run = true;
216+
task->state = SOF_TASK_STATE_RUNNING;
217+
218+
/* Move the task to a temporary list */
219+
list_item_del(list);
220+
list_item_append(list, &removed_startup_task_head);
221+
222+
zephyr_ll_unlock(sch, &flags);
223+
224+
/*
225+
* task's .run() should only return either
226+
* SOF_TASK_STATE_COMPLETED or SOF_TASK_STATE_RESCHEDULE
227+
*/
228+
state = do_task_run(task);
229+
if (state != SOF_TASK_STATE_COMPLETED &&
230+
state != SOF_TASK_STATE_RESCHEDULE) {
231+
tr_err(&ll_tr,
232+
"invalid return state %u",
233+
state);
234+
state = SOF_TASK_STATE_RESCHEDULE;
235+
}
236+
237+
zephyr_ll_lock(sch, &flags);
238+
239+
if (pdata->freeing || state == SOF_TASK_STATE_COMPLETED) {
240+
zephyr_ll_task_done(sch, task);
241+
} else {
242+
/*
243+
* task->state could've been changed to
244+
* SOF_TASK_STATE_CANCEL
245+
*/
246+
switch (task->state) {
247+
case SOF_TASK_STATE_CANCEL:
248+
zephyr_ll_task_done(sch, task);
249+
break;
250+
default:
251+
break;
252+
}
253+
}
254+
}
255+
196256
/*
197257
* We drop the lock while executing tasks, at that time tasks can be
198258
* removed from or added to the list, including the task that was
@@ -261,6 +321,28 @@ static void zephyr_ll_run(void *data)
261321
list_item_append(list, &sch->tasks);
262322
}
263323

324+
/* Move startup tasks back but respecting priorities */
325+
list_for_item_safe(list, tmp, &removed_startup_task_head) {
326+
list_item_del(list);
327+
328+
struct task *task_iter = container_of(list, struct task, list);
329+
330+
list_for_item(list2, &sch->tasks) {
331+
struct task *task_iter2 = container_of(list2, struct task, list);
332+
if (task_iter->priority < task_iter2->priority) {
333+
list_item_append(list, &task_iter2->list);
334+
break;
335+
}
336+
}
337+
338+
/*
339+
* If the task has not been added, it means that it has the lowest
340+
* priority and should be added at the end of the list
341+
*/
342+
if (list_is_empty(list))
343+
list_item_append(list, &sch->tasks);
344+
}
345+
264346
zephyr_ll_unlock(sch, &flags);
265347

266348
#ifndef CONFIG_SOF_USERSPACE_LL
@@ -320,6 +402,26 @@ static int zephyr_ll_task_schedule_common(struct zephyr_ll *sch, struct task *ta
320402
return -EDEADLK;
321403
}
322404

405+
/* check if the task is already scheduled */
406+
list_for_item(list, &sch->startup_tasks) {
407+
task_iter = container_of(list, struct task, list);
408+
409+
if (task_iter == task) {
410+
/* if cancelled, reschedule the task */
411+
if (task->state == SOF_TASK_STATE_CANCEL)
412+
break;
413+
414+
/*
415+
* keep original start. TODO: this shouldn't be happening.
416+
* Remove after verification
417+
*/
418+
zephyr_ll_unlock(sch, &flags);
419+
tr_warn(&ll_tr, "task %p (%pU) already scheduled",
420+
task, task->uid);
421+
return 0;
422+
}
423+
}
424+
323425
/* check if the task is already scheduled */
324426
list_for_item(list, &sch->tasks) {
325427
task_iter = container_of(list, struct task, list);
@@ -593,6 +695,7 @@ int zephyr_ll_scheduler_init(struct ll_schedule_domain *domain)
593695
memset(sch, 0, sizeof(*sch));
594696

595697
list_init(&sch->tasks);
698+
list_init(&sch->startup_tasks);
596699
sch->ll_domain = domain;
597700
sch->core = core;
598701
sch->n_tasks = 0;
@@ -625,6 +728,7 @@ void scheduler_get_task_info_ll(struct scheduler_props *scheduler_props,
625728
struct zephyr_ll *ll_sch = (struct zephyr_ll *)scheduler_get_data(SOF_SCHEDULE_LL_TIMER);
626729

627730
zephyr_ll_lock(ll_sch, &flags);
731+
///TODO: !!! CONCATENATE LISTS, MAYBE???!!!
628732
scheduler_get_task_info(scheduler_props, data_off_size, &ll_sch->tasks);
629733
zephyr_ll_unlock(ll_sch, &flags);
630734
}

0 commit comments

Comments
 (0)