diff --git a/src/arch/xtensa/include/arch/task.h b/src/arch/xtensa/include/arch/task.h index de8ded4f91fb..f25dd2d6317f 100644 --- a/src/arch/xtensa/include/arch/task.h +++ b/src/arch/xtensa/include/arch/task.h @@ -160,7 +160,7 @@ static void _irq_task(void *arg) task = container_of(clist, struct task, irq_list); list_item_del(clist); - if (task->func && task->state == TASK_STATE_PENDING) { + if (task->func) { schedule_task_running(task); run_task = 1; } else { diff --git a/src/audio/pipeline.c b/src/audio/pipeline.c index 12722031b76e..8d2ae47830d2 100644 --- a/src/audio/pipeline.c +++ b/src/audio/pipeline.c @@ -1271,7 +1271,8 @@ void pipeline_schedule_copy(struct pipeline *p, uint64_t start) * buffers prior to trigger start. */ void pipeline_schedule_copy_idle(struct pipeline *p) { - schedule_task_idle(&p->pipe_task, p->ipc_pipe.deadline); +// schedule_task_idle(&p->pipe_task, p->ipc_pipe.deadline); + schedule_task(&p->pipe_task, 0, p->ipc_pipe.deadline); } void pipeline_schedule_cancel(struct pipeline *p) diff --git a/src/include/sof/schedule.h b/src/include/sof/schedule.h index a5609ab1bb55..b6b619ebfbe1 100644 --- a/src/include/sof/schedule.h +++ b/src/include/sof/schedule.h @@ -91,6 +91,8 @@ struct task { /* runtime duration in scheduling clock base */ uint64_t max_rtime; /* max time taken to run */ completion_t complete; + + uint32_t pending_cnt; }; struct schedule_data **arch_schedule_get(void); @@ -111,6 +113,7 @@ static inline void schedule_task_init(struct task *task, void (*func)(void *), void *data) { task->core = 0; + task->pending_cnt = 0; task->state = TASK_STATE_INIT; task->func = func; task->data = data; @@ -119,6 +122,7 @@ static inline void schedule_task_init(struct task *task, void (*func)(void *), static inline void schedule_task_free(struct task *task) { task->state = TASK_STATE_FREE; + task->pending_cnt = 0; task->func = NULL; task->data = NULL; } diff --git a/src/lib/schedule.c b/src/lib/schedule.c index 616c6dd4d43a..faff023db4fd 100644 --- a/src/lib/schedule.c +++ b/src/lib/schedule.c @@ -263,17 +263,17 @@ static int _schedule_task(struct task *task, uint64_t start, uint64_t deadline) spin_lock_irq(&sch->lock, flags); - /* is task already pending ? - not enough MIPS to complete ? */ - if (task->state == TASK_STATE_PENDING) { - trace_schedule("_schedule_task(), task already pending"); - spin_unlock_irq(&sch->lock, flags); - return 0; - } - - /* is task already queued ? - not enough MIPS to complete ? */ - if (task->state == TASK_STATE_QUEUED) { - trace_schedule("_schedule_task(), task already queued"); - spin_unlock_irq(&sch->lock, flags); + /* + * increase pending_cnt, will schedule it after this + * pending one is finished. + */ + if (task->state == TASK_STATE_PENDING || + task->state == TASK_STATE_QUEUED || + task->state == TASK_STATE_RUNNING || + task->state == TASK_STATE_PREEMPTED) { + trace_schedule("task 0x%xalready WIP, schedule it later...", + (uint32_t)(uint32_t *)task); + task->pending_cnt++; return 0; } @@ -292,6 +292,9 @@ static int _schedule_task(struct task *task, uint64_t start, uint64_t deadline) /* calculate deadline - TODO: include MIPS */ task->deadline = task->start + ticks_per_ms * deadline / 1000; + if (task->pending_cnt) + task->pending_cnt--; + /* add task to list */ list_item_append(&task->list, &sch->list); task->state = TASK_STATE_QUEUED; @@ -337,6 +340,8 @@ void schedule_task(struct task *task, uint64_t start, uint64_t deadline) void schedule_task_complete(struct task *task) { struct schedule_data *sch = *arch_schedule_get(); + uint64_t ticks_per_ms; + uint64_t deadline; uint32_t flags; tracev_schedule("schedule_task_complete()"); @@ -367,6 +372,13 @@ void schedule_task_complete(struct task *task) /* tell any waiter that task has completed */ wait_completed(&task->complete); + + /* schedule the same pending task */ + if (task->pending_cnt) { + ticks_per_ms = clock_ms_to_ticks(sch->clock, 1); + deadline = (task->deadline - task->start) * 1000 / ticks_per_ms; + schedule_task(task, 0, deadline); + } } /* Update task state to running */