Skip to content

Commit

Permalink
schedule: cancel a task before freeing it
Browse files Browse the repository at this point in the history
When a chain DMA stream is the only one running, stopping it
currently takes 100ms. The reason is that the chain DMA driver is
trying to stop the task directly from the IPC context instead of
letting the task exit on its next scheduling event. The IPC thread is
indeed trying to wait on a semaphore for the task to exit, but that
doesn't work either, because zephyr_domain_unregister() terminates
the thread before it signals the semaphore. To fix this we swap the
order and signal the semaphore before terminating the thread.

Link: #8445
Signed-off-by: Guennadi Liakhovetski <[email protected]>
  • Loading branch information
lyakh committed Nov 9, 2023
1 parent f8a9591 commit ee7976b
Showing 1 changed file with 10 additions and 9 deletions.
19 changes: 10 additions & 9 deletions src/schedule/zephyr_ll.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ static void zephyr_ll_assert_core(const struct zephyr_ll *sch)
static void zephyr_ll_task_done(struct zephyr_ll *sch,
struct task *task)
{
struct zephyr_ll_pdata *pdata = task->priv_data;

list_item_del(&task->list);

if (!sch->n_tasks) {
Expand All @@ -66,6 +68,13 @@ static void zephyr_ll_task_done(struct zephyr_ll *sch,

task->state = SOF_TASK_STATE_FREE;

if (pdata->freeing)
/*
* zephyr_ll_task_free() is trying to free this task. Complete
* it and signal the semaphore to let the function proceed
*/
k_sem_give(&pdata->sem);

tr_info(&ll_tr, "task complete %p %pU", task, task->uid);
tr_info(&ll_tr, "num_tasks %d total_num_tasks %ld",
sch->n_tasks, atomic_read(&sch->ll_domain->total_num_tasks));
Expand Down Expand Up @@ -212,15 +221,7 @@ static void zephyr_ll_run(void *data)

zephyr_ll_lock(sch, &flags);

if (pdata->freeing) {
/*
* zephyr_ll_task_free() is trying to free this task.
* complete it and signal the semaphore to let the
* function proceed
*/
zephyr_ll_task_done(sch, task);
k_sem_give(&pdata->sem);
} else if (state == SOF_TASK_STATE_COMPLETED) {
if (pdata->freeing || state == SOF_TASK_STATE_COMPLETED) {
zephyr_ll_task_done(sch, task);
} else {
/*
Expand Down

0 comments on commit ee7976b

Please sign in to comment.