Add an API to allow tasks to be added to the scheduler task list but not run until the DSP enters an idle state. i.e. we schedule the task as normal but dont immediately call schedule() to schedule that task for execution and instead wait until schedule() is next called (at the end of some other work).
This patch also calls schedule() before entering the idle state in the main processing loop.
Signed-off-by: Liam Girdwood liam.r.girdwood@linux.intel.com --- src/include/reef/schedule.h | 2 ++ src/lib/schedule.c | 49 ++++++++++++++++++++++++++++++++++----------- src/tasks/audio.c | 3 +++ 3 files changed, 42 insertions(+), 12 deletions(-)
diff --git a/src/include/reef/schedule.h b/src/include/reef/schedule.h index 6d94788..68aa0ad 100644 --- a/src/include/reef/schedule.h +++ b/src/include/reef/schedule.h @@ -77,6 +77,8 @@ void schedule(void);
void schedule_task(struct task *task, uint64_t start, uint64_t deadline);
+void schedule_task_idle(struct task *task, uint64_t deadline); + void schedule_task_complete(struct task *task);
static inline void schedule_task_init(struct task *task, void (*func)(void *), diff --git a/src/lib/schedule.c b/src/lib/schedule.c index 942067c..1310e83 100644 --- a/src/lib/schedule.c +++ b/src/lib/schedule.c @@ -233,15 +233,8 @@ out: } #endif
-/* - * Add a new task to the scheduler to be run and define a scheduling - * window in time for the task to be ran. i.e. task will run between start and - * deadline times. - * - * start is in microseconds relative to last task start time. - * deadline is in microseconds relative to start. - */ -void schedule_task(struct task *task, uint64_t start, uint64_t deadline) + +static int _schedule_task(struct task *task, uint64_t start, uint64_t deadline) { uint32_t flags; uint64_t current; @@ -254,7 +247,7 @@ void schedule_task(struct task *task, uint64_t start, uint64_t deadline) if (task->state == TASK_STATE_RUNNING) { trace_pipe("tsk"); spin_unlock_irq(&sch->lock, flags); - return; + return 0; }
/* get the current time */ @@ -275,8 +268,40 @@ void schedule_task(struct task *task, uint64_t start, uint64_t deadline) task->state = TASK_STATE_QUEUED; spin_unlock_irq(&sch->lock, flags);
- /* rerun scheduler */ - schedule(); + return 1; +} + +/* + * Add a new task to the scheduler to be run and define a scheduling + * deadline in time for the task to be ran. Do not invoke the scheduler + * immediately to run task, but wait intil schedule is next called. + * + * deadline is in microseconds relative to start. + */ +void schedule_task_idle(struct task *task, uint64_t deadline) +{ + _schedule_task(task, 0, deadline); +} + +/* + * Add a new task to the scheduler to be run and define a scheduling + * window in time for the task to be ran. i.e. task will run between start and + * deadline times. + * + * start is in microseconds relative to last task start time. + * deadline is in microseconds relative to start. + */ +void schedule_task(struct task *task, uint64_t start, uint64_t deadline) +{ + int need_sched; + + need_sched = _schedule_task(task, start, deadline); + + /* need to run scheduler if task not already running */ + if (need_sched) { + /* rerun scheduler */ + schedule(); + } }
/* Remove a task from the scheduler when complete */ diff --git a/src/tasks/audio.c b/src/tasks/audio.c index 68f7702..af241d7 100644 --- a/src/tasks/audio.c +++ b/src/tasks/audio.c @@ -85,6 +85,9 @@ int do_task(struct reef *reef)
/* now process any IPC messages from host */ ipc_process_msg_queue(); + + /* schedule any idle taks */ + schedule(); }
/* something bad happened */