Skip to content

Commit 40f9749

Browse files
authored
Merge pull request #373 from xiulipan/merge12_2
Merge stable 1.2 task and scheduler fix into master
2 parents f17abe6 + 4f3f4d7 commit 40f9749

8 files changed

Lines changed: 82 additions & 39 deletions

File tree

src/arch/xtensa/include/arch/task.h

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -101,20 +101,28 @@ static inline uint32_t task_get_irq(struct task *task)
101101
static inline void task_set_data(struct task *task)
102102
{
103103
struct list_item *dst = NULL;
104+
struct irq_task *irq_task;
105+
uint32_t flags;
104106

105107
switch (task->priority) {
106108
case TASK_PRI_MED + 1 ... TASK_PRI_LOW:
107-
dst = &((*task_irq_low_get())->list);
109+
irq_task = *task_irq_low_get();
110+
dst = &irq_task->list;
108111
break;
109112
case TASK_PRI_HIGH ... TASK_PRI_MED - 1:
110-
dst = &((*task_irq_high_get())->list);
113+
irq_task = *task_irq_high_get();
114+
dst = &irq_task->list;
111115
break;
112116
case TASK_PRI_MED:
113117
default:
114-
dst = &((*task_irq_med_get())->list);
118+
irq_task = *task_irq_med_get();
119+
dst = &irq_task->list;
115120
break;
116121
}
122+
123+
spin_lock_irq(&irq_task->lock, flags);
117124
list_item_append(&task->irq_list, dst);
125+
spin_unlock_irq(&irq_task->lock, flags);
118126
}
119127

120128
/**
@@ -129,21 +137,19 @@ static void _irq_task(void *arg)
129137
struct task *task;
130138
uint32_t flags;
131139

132-
/* intentionally don't lock list to have task added from schedule irq */
133-
list_for_item(tlist, &irq_task->list) {
134-
task = container_of(tlist, struct task, irq_list);
140+
spin_lock_irq(&irq_task->lock, flags);
141+
list_for_item_safe(clist, tlist, &irq_task->list) {
135142

136-
if (task->func)
137-
task->func(task->data);
143+
task = container_of(clist, struct task, irq_list);
144+
list_item_del(clist);
138145

139-
schedule_task_complete(task);
140-
}
146+
spin_unlock_irq(&irq_task->lock, flags);
141147

142-
spin_lock_irq(&irq_task->lock, flags);
148+
if (task->func && task->state == TASK_STATE_RUNNING)
149+
task->func(task->data);
143150

144-
list_for_item_safe(clist, tlist, &irq_task->list) {
145-
task = container_of(clist, struct task, irq_list);
146-
list_item_del(&task->irq_list);
151+
schedule_task_complete(task);
152+
spin_lock_irq(&irq_task->lock, flags);
147153
}
148154

149155
interrupt_clear(irq_task->irq);

src/audio/pipeline.c

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

12761276
void pipeline_schedule_cancel(struct pipeline *p)
12771277
{
1278-
schedule_task_complete(&p->pipe_task);
1278+
int err;
1279+
1280+
/* cancel and wait for pipeline to complete */
1281+
err = schedule_task_cancel(&p->pipe_task);
1282+
if (err < 0)
1283+
trace_pipe_error("pC0");
12791284
}
12801285

12811286
static void pipeline_task(void *arg)

src/include/sof/schedule.h

Lines changed: 8 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 schedule_data;
4344
struct sof;
@@ -56,6 +57,10 @@ struct sof;
5657
#define TASK_PRI_MED 0
5758
#define TASK_PRI_HIGH -20
5859

60+
#define TASK_PRI_IPC 1
61+
62+
/* maximun task time slice in microseconds */
63+
#define SCHEDULE_TASK_MAX_TIME_SLICE 5000
5964

6065
/* task descriptor */
6166
struct task {
@@ -73,6 +78,7 @@ struct task {
7378

7479
/* runtime duration in scheduling clock base */
7580
uint64_t max_rtime; /* max time taken to run */
81+
completion_t complete;
7682
};
7783

7884
struct schedule_data **arch_schedule_get(void);
@@ -83,6 +89,8 @@ void schedule_task(struct task *task, uint64_t start, uint64_t deadline);
8389

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

92+
int schedule_task_cancel(struct task *task);
93+
8694
void schedule_task_complete(struct task *task);
8795

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

src/ipc/apl-ipc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ int platform_ipc_init(struct ipc *ipc)
195195

196196
/* schedule */
197197
schedule_task_init(&_ipc->ipc_task, ipc_process_task, _ipc);
198-
schedule_task_config(&_ipc->ipc_task, 0, 0);
198+
schedule_task_config(&_ipc->ipc_task, TASK_PRI_IPC, 0);
199199

200200
#ifdef CONFIG_HOST_PTABLE
201201
/* allocate page table buffer */

src/ipc/byt-ipc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ int platform_ipc_init(struct ipc *ipc)
217217

218218
/* schedule */
219219
schedule_task_init(&_ipc->ipc_task, ipc_process_task, _ipc);
220-
schedule_task_config(&_ipc->ipc_task, 0, 0);
220+
schedule_task_config(&_ipc->ipc_task, TASK_PRI_IPC, 0);
221221

222222
#ifdef CONFIG_HOST_PTABLE
223223
/* allocate page table buffer */

src/ipc/cnl-ipc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ int platform_ipc_init(struct ipc *ipc)
196196

197197
/* schedule */
198198
schedule_task_init(&_ipc->ipc_task, ipc_process_task, _ipc);
199-
schedule_task_config(&_ipc->ipc_task, 0, 0);
199+
schedule_task_config(&_ipc->ipc_task, TASK_PRI_IPC, 0);
200200

201201
#ifdef CONFIG_HOST_PTABLE
202202
/* allocate page table buffer */

src/ipc/hsw-ipc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ int platform_ipc_init(struct ipc *ipc)
212212

213213
/* schedule */
214214
schedule_task_init(&_ipc->ipc_task, ipc_process_task, _ipc);
215-
schedule_task_config(&_ipc->ipc_task, 0, 0);
215+
schedule_task_config(&_ipc->ipc_task, TASK_PRI_IPC, 0);
216216

217217
#ifdef CONFIG_HOST_PTABLE
218218
/* allocate page table buffer */

src/lib/schedule.c

Lines changed: 44 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ static inline struct task *edf_get_next(uint64_t current,
9898
struct list_item *clist;
9999
struct list_item *tlist;
100100
uint64_t next_delta = UINT64_MAX;
101+
int next_priority = TASK_PRI_LOW;
101102
uint64_t delta;
102103
uint64_t deadline;
103104
int reschedule = 0;
@@ -126,23 +127,31 @@ static inline struct task *edf_get_next(uint64_t current,
126127
/* include the length of task in deadline calc */
127128
deadline = task->deadline - task->max_rtime;
128129

129-
/* get earliest deadline */
130130
if (current < deadline) {
131131
delta = deadline - current;
132132

133-
if (delta < next_delta) {
133+
/* get highest priority */
134+
if (task->priority < next_priority) {
135+
next_priority = task->priority;
134136
next_delta = delta;
135137
next_task = task;
138+
} else if (task->priority == next_priority) {
139+
/* get earliest deadline */
140+
if (delta < next_delta) {
141+
next_delta = delta;
142+
next_task = task;
143+
}
136144
}
137-
138145
} else {
139146
/* missed scheduling - will be rescheduled */
140147
trace_pipe("ed!");
141148

142149
/* have we already tried to rescheule ? */
143-
if (reschedule++)
150+
if (!reschedule) {
151+
reschedule++;
152+
trace_pipe("edr");
144153
edf_reschedule(task, current);
145-
else {
154+
} else {
146155
/* reschedule failed */
147156
list_item_del(&task->list);
148157
task->state = TASK_STATE_CANCEL;
@@ -170,9 +179,11 @@ static uint64_t sch_work(void *data, uint64_t delay)
170179
*/
171180
static struct task *schedule_edf(void)
172181
{
182+
struct schedule_data *sch = *arch_schedule_get();
173183
struct task *task;
174184
struct task *future_task = NULL;
175185
uint64_t current;
186+
uint32_t flags;
176187

177188
tracev_pipe("edf");
178189

@@ -195,42 +206,46 @@ static struct task *schedule_edf(void)
195206
} else {
196207
/* yes, run current task */
197208
task->start = current;
209+
210+
/* init task for running */
211+
wait_init(&task->complete);
212+
spin_lock_irq(&sch->lock, flags);
198213
task->state = TASK_STATE_RUNNING;
214+
list_item_del(&task->list);
215+
spin_unlock_irq(&sch->lock, flags);
216+
217+
/* now run task at correct run level */
199218
run_task(task);
200219
}
201220

202221
/* tell caller about future task */
203222
return future_task;
204223
}
205224

206-
#if 0 /* FIXME: is this needed ? */
207-
/* delete task from scheduler */
208-
static int schedule_task_del(struct task *task)
225+
/* cancel and delete task from scheduler - won't stop it if already running */
226+
int schedule_task_cancel(struct task *task)
209227
{
210228
struct schedule_data *sch = *arch_schedule_get();
211229
uint32_t flags;
212230
int ret = 0;
213231

214232
tracev_pipe("del");
215233

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

219-
/* is task already running ? */
220-
if (task->state == TASK_STATE_RUNNING) {
221-
ret = -EAGAIN;
222-
goto out;
236+
/* check current task state, delete it if it is queued
237+
* if it is already running, nothing we can do about it atm
238+
*/
239+
if (task->state == TASK_STATE_QUEUED) {
240+
/* delete task */
241+
task->state = TASK_STATE_CANCEL;
242+
list_item_del(&task->list);
223243
}
224244

225-
list_item_del(&task->list);
226-
task->state = TASK_STATE_COMPLETED;
227-
228-
out:
229245
spin_unlock_irq(&sch->lock, flags);
246+
230247
return ret;
231248
}
232-
#endif
233-
234249

235250
static int _schedule_task(struct task *task, uint64_t start, uint64_t deadline)
236251
{
@@ -249,6 +264,13 @@ static int _schedule_task(struct task *task, uint64_t start, uint64_t deadline)
249264
return 0;
250265
}
251266

267+
/* is task already running ? - not enough MIPS to complete ? */
268+
if (task->state == TASK_STATE_QUEUED) {
269+
trace_pipe("tsq");
270+
spin_unlock_irq(&sch->lock, flags);
271+
return 0;
272+
}
273+
252274
/* get the current time */
253275
current = platform_timer_get(platform_timer);
254276

@@ -312,9 +334,11 @@ void schedule_task_complete(struct task *task)
312334
tracev_pipe("com");
313335

314336
spin_lock_irq(&sch->lock, flags);
315-
list_item_del(&task->list);
316337
task->state = TASK_STATE_COMPLETED;
317338
spin_unlock_irq(&sch->lock, flags);
339+
340+
/* tell any waiter that task has completed */
341+
wait_completed(&task->complete);
318342
}
319343

320344
static void scheduler_run(void *unused)

0 commit comments

Comments
 (0)