Skip to content

Commit 90b455e

Browse files
authored
Merge pull request #292 from RanderWang/loop-1.2
pipe: fix a infinite loop issue in schedule module
2 parents 8152dc9 + 3b43833 commit 90b455e

3 files changed

Lines changed: 47 additions & 15 deletions

File tree

src/audio/pipeline.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1131,7 +1131,12 @@ void pipeline_schedule_copy_idle(struct pipeline *p)
11311131

11321132
void pipeline_schedule_cancel(struct pipeline *p)
11331133
{
1134-
schedule_task_complete(&p->pipe_task);
1134+
int err;
1135+
1136+
/* cancel and wait for pipeline to complete */
1137+
err = schedule_task_cancel(&p->pipe_task, 1);
1138+
if (err < 0)
1139+
trace_pipe_error("pC0");
11351140
}
11361141

11371142
static void pipeline_task(void *arg)

src/include/sof/schedule.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include <sof/lock.h>
3939
#include <sof/list.h>
4040
#include <sof/work.h>
41+
#include <sof/wait.h>
4142

4243
struct sof;
4344

@@ -55,6 +56,8 @@ struct sof;
5556
#define TASK_PRI_MED 0
5657
#define TASK_PRI_HIGH -20
5758

59+
/* maximun task time slice in microseconds */
60+
#define SCHEDULE_TASK_MAX_TIME_SLICE 5000
5861

5962
/* task descriptor */
6063
struct task {
@@ -72,6 +75,7 @@ struct task {
7275

7376
/* runtime duration in scheduling clock base */
7477
uint64_t max_rtime; /* max time taken to run */
78+
completion_t complete;
7579
};
7680

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

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

87+
int schedule_task_cancel(struct task *task, int wait);
88+
8389
void schedule_task_complete(struct task *task);
8490

8591
static inline void schedule_task_init(struct task *task, void (*func)(void *),

src/lib/schedule.c

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ static struct task *schedule_edf(void)
174174
struct task *task;
175175
struct task *future_task = NULL;
176176
uint64_t current;
177+
uint32_t flags;
177178

178179
tracev_pipe("edf");
179180

@@ -196,41 +197,59 @@ static struct task *schedule_edf(void)
196197
} else {
197198
/* yes, run current task */
198199
task->start = current;
200+
201+
/* init task for running */
202+
wait_init(&task->complete);
203+
spin_lock_irq(&sch->lock, flags);
199204
task->state = TASK_STATE_RUNNING;
205+
list_item_del(&task->list);
206+
spin_unlock_irq(&sch->lock, flags);
207+
208+
/* now run task at correct run level */
200209
arch_run_task(task);
201210
}
202211

203212
/* tell caller about future task */
204213
return future_task;
205214
}
206215

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

214222
tracev_pipe("del");
215223

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

219-
/* is task already running ? */
220-
if (task->state == TASK_STATE_RUNNING) {
221-
ret = -EAGAIN;
222-
goto out;
226+
/* check current task state */
227+
switch (task->state) {
228+
case TASK_STATE_QUEUED:
229+
/* delete task */
230+
task->state = TASK_STATE_CANCEL;
231+
list_item_del(&task->list);
232+
break;
233+
case TASK_STATE_RUNNING:
234+
/* already running, nothing we can do about it atm */
235+
if (wait) {
236+
task->complete.timeout = SCHEDULE_TASK_MAX_TIME_SLICE;
237+
spin_unlock_irq(&sch->lock, flags);
238+
ret = wait_for_completion_timeout(&task->complete);
239+
goto out;
240+
} else {
241+
ret = -EBUSY;
242+
}
243+
break;
244+
default:
245+
break;
223246
}
224247

225-
list_item_del(&task->list);
226-
task->state = TASK_STATE_COMPLETED;
248+
spin_unlock_irq(&sch->lock, flags);
227249

228250
out:
229-
spin_unlock_irq(&sch->lock, flags);
230251
return ret;
231252
}
232-
#endif
233-
234253

235254
static int _schedule_task(struct task *task, uint64_t start, uint64_t deadline)
236255
{
@@ -310,9 +329,11 @@ void schedule_task_complete(struct task *task)
310329
tracev_pipe("com");
311330

312331
spin_lock_irq(&sch->lock, flags);
313-
list_item_del(&task->list);
314332
task->state = TASK_STATE_COMPLETED;
315333
spin_unlock_irq(&sch->lock, flags);
334+
335+
/* tell any waiter that task has completed */
336+
wait_completed(&task->complete);
316337
}
317338

318339
static void scheduler_run(void *unused)

0 commit comments

Comments
 (0)