Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/audio/pipeline.c
Original file line number Diff line number Diff line change
Expand Up @@ -1131,7 +1131,12 @@ void pipeline_schedule_copy_idle(struct pipeline *p)

void pipeline_schedule_cancel(struct pipeline *p)
{
schedule_task_complete(&p->pipe_task);
int err;

/* cancel and wait for pipeline to complete */
err = schedule_task_cancel(&p->pipe_task, 1);
if (err < 0)
trace_pipe_error("pC0");
}

static void pipeline_task(void *arg)
Expand Down
6 changes: 6 additions & 0 deletions src/include/sof/schedule.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include <sof/lock.h>
#include <sof/list.h>
#include <sof/work.h>
#include <sof/wait.h>

struct sof;

Expand All @@ -55,6 +56,8 @@ struct sof;
#define TASK_PRI_MED 0
#define TASK_PRI_HIGH -20

/* maximun task time slice in microseconds */
#define SCHEDULE_TASK_MAX_TIME_SLICE 5000

/* task descriptor */
struct task {
Expand All @@ -72,6 +75,7 @@ struct task {

/* runtime duration in scheduling clock base */
uint64_t max_rtime; /* max time taken to run */
completion_t complete;
};

void schedule(void);
Expand All @@ -80,6 +84,8 @@ void schedule_task(struct task *task, uint64_t start, uint64_t deadline);

void schedule_task_idle(struct task *task, uint64_t deadline);

int schedule_task_cancel(struct task *task, int wait);

void schedule_task_complete(struct task *task);

static inline void schedule_task_init(struct task *task, void (*func)(void *),
Expand Down
49 changes: 35 additions & 14 deletions src/lib/schedule.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ static struct task *schedule_edf(void)
struct task *task;
struct task *future_task = NULL;
uint64_t current;
uint32_t flags;

tracev_pipe("edf");

Expand All @@ -196,41 +197,59 @@ static struct task *schedule_edf(void)
} else {
/* yes, run current task */
task->start = current;

/* init task for running */
wait_init(&task->complete);
spin_lock_irq(&sch->lock, flags);
task->state = TASK_STATE_RUNNING;
list_item_del(&task->list);
spin_unlock_irq(&sch->lock, flags);

/* now run task at correct run level */
arch_run_task(task);
}

/* tell caller about future task */
return future_task;
}

#if 0 /* FIXME: is this needed ? */
/* delete task from scheduler */
static int schedule_task_del(struct task *task)
/* cancel and delete task from scheduler - won't stop it if already running */
int schedule_task_cancel(struct task *task, int wait)
{
uint32_t flags;
int ret = 0;

tracev_pipe("del");

/* add task to list */
spin_lock_irq(&sch->lock, flags);

/* is task already running ? */
if (task->state == TASK_STATE_RUNNING) {
ret = -EAGAIN;
goto out;
/* check current task state */
switch (task->state) {
case TASK_STATE_QUEUED:
/* delete task */
task->state = TASK_STATE_CANCEL;
list_item_del(&task->list);
break;
case TASK_STATE_RUNNING:
/* already running, nothing we can do about it atm */
if (wait) {
task->complete.timeout = SCHEDULE_TASK_MAX_TIME_SLICE;
spin_unlock_irq(&sch->lock, flags);
ret = wait_for_completion_timeout(&task->complete);
goto out;
} else {
ret = -EBUSY;
}
break;
default:
break;
}

list_item_del(&task->list);
task->state = TASK_STATE_COMPLETED;
spin_unlock_irq(&sch->lock, flags);

out:
spin_unlock_irq(&sch->lock, flags);
return ret;
}
#endif


static int _schedule_task(struct task *task, uint64_t start, uint64_t deadline)
{
Expand Down Expand Up @@ -310,9 +329,11 @@ void schedule_task_complete(struct task *task)
tracev_pipe("com");

spin_lock_irq(&sch->lock, flags);
list_item_del(&task->list);
task->state = TASK_STATE_COMPLETED;
spin_unlock_irq(&sch->lock, flags);

/* tell any waiter that task has completed */
wait_completed(&task->complete);
}

static void scheduler_run(void *unused)
Expand Down