Skip to content

Commit bbef32b

Browse files
committed
schedule: bind scheduler to a task at task init time
Change the operation model of schedule.h such that a task is bound to a scheduler instance at task init time. In the past, the scheduler instance has been looked up at each task scheduling invocation. The old model assume all schedule.h callers have access to all scheduler objects in the system. This complicates implementation of user-space support in SOF. Store a pointer to the matching schedule_data in the task struct at schedule_task_init() time. This allows all schedule API functions (schedule_task, schedule_task_before, schedule_task_after, reschedule_task, schedule_task_cancel, schedule_task_free, and schedule_task_running) to use the cached scheduler reference directly from task->sch, instead of iterating the global scheduler list on every call. This reduces runtime overhead and simplifies the inline functions in schedule.h, removing the repeated list traversal and type matching logic. The scheduler binding is validated at init time, so subsequent operations can assume a valid task->sch pointer. Note: in Zephyr builds, arch_schedulers_get() is sensitive on which core it is executed on, so add an assert to ensure schedule_task_init() is called on the target core. Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
1 parent d94306c commit bbef32b

7 files changed

Lines changed: 90 additions & 79 deletions

File tree

posix/include/rtos/task.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
struct comp_dev;
2020
struct sof;
21+
struct schedule_data;
2122

2223
/** \brief Predefined LL task priorities. */
2324
#define SOF_TASK_PRI_HIGH 0 /* priority level 0 - high */
@@ -60,6 +61,7 @@ struct task {
6061
uint16_t priority; /**< priority of the task (used by LL) */
6162
uint16_t core; /**< execution core */
6263
uint16_t flags; /**< custom flags */
64+
struct schedule_data *sch; /**< scheduler bound to task */
6365
enum task_state state; /**< current state */
6466
void *data; /**< custom data passed to all ops */
6567
struct list_item list; /**< used by schedulers to hold tasks */

src/include/sof/schedule/schedule.h

Lines changed: 36 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -203,149 +203,106 @@ static inline void *scheduler_get_data(uint16_t type)
203203
/** See scheduler_ops::schedule_task_running */
204204
static inline int schedule_task_running(struct task *task)
205205
{
206-
struct schedulers *schedulers = *arch_schedulers_get();
207206
struct schedule_data *sch;
208-
struct list_item *slist;
209207

210-
list_for_item(slist, &schedulers->list) {
211-
sch = container_of(slist, struct schedule_data, list);
212-
if (task->type == sch->type) {
213-
/* optional operation */
214-
if (!sch->ops->schedule_task_running)
215-
return 0;
208+
assert(task);
209+
sch = task->sch;
216210

217-
return sch->ops->schedule_task_running(sch->data, task);
218-
}
219-
}
211+
if (!sch->ops->schedule_task_running)
212+
return 0;
220213

221-
return -ENODEV;
214+
return sch->ops->schedule_task_running(sch->data, task);
222215
}
223216

224217
/** See scheduler_ops::schedule_task */
225218
static inline int schedule_task(struct task *task, uint64_t start,
226219
uint64_t period)
227220
{
228-
struct schedulers *schedulers = *arch_schedulers_get();
229221
struct schedule_data *sch;
230-
struct list_item *slist;
231222

232223
if (!task)
233224
return -EINVAL;
234225

235-
list_for_item(slist, &schedulers->list) {
236-
sch = container_of(slist, struct schedule_data, list);
237-
if (task->type == sch->type)
238-
return sch->ops->schedule_task(sch->data, task, start,
239-
period);
240-
}
226+
sch = task->sch;
241227

242-
return -ENODEV;
228+
return sch->ops->schedule_task(sch->data, task, start, period);
243229
}
244230

245231
/** See scheduler_ops::schedule_task_before */
246232
static inline int schedule_task_before(struct task *task, uint64_t start,
247233
uint64_t period, struct task *before)
248234
{
249-
struct schedulers *schedulers = *arch_schedulers_get();
250235
struct schedule_data *sch;
251-
struct list_item *slist;
252236

253237
if (!task || !before)
254238
return -EINVAL;
255239

256-
list_for_item(slist, &schedulers->list) {
257-
sch = container_of(slist, struct schedule_data, list);
258-
if (task->type == sch->type) {
259-
if (sch->ops->schedule_task_before)
260-
return sch->ops->schedule_task_before(sch->data, task, start,
261-
period, before);
262-
263-
return sch->ops->schedule_task(sch->data, task, start,
264-
period);
265-
}
266-
}
240+
sch = task->sch;
241+
242+
if (sch->ops->schedule_task_before)
243+
return sch->ops->schedule_task_before(sch->data, task, start,
244+
period, before);
267245

268-
return -ENODEV;
246+
return sch->ops->schedule_task(sch->data, task, start, period);
269247
}
270248

271249
/** See scheduler_ops::schedule_task_after */
272250
static inline int schedule_task_after(struct task *task, uint64_t start,
273251
uint64_t period, struct task *after)
274252
{
275-
struct schedulers *schedulers = *arch_schedulers_get();
276253
struct schedule_data *sch;
277-
struct list_item *slist;
278254

279255
if (!task || !after)
280256
return -EINVAL;
281257

282-
list_for_item(slist, &schedulers->list) {
283-
sch = container_of(slist, struct schedule_data, list);
284-
if (task->type == sch->type) {
285-
if (sch->ops->schedule_task_after)
286-
return sch->ops->schedule_task_after(sch->data, task, start,
287-
period, after);
288-
289-
return sch->ops->schedule_task(sch->data, task, start,
290-
period);
291-
}
292-
}
258+
sch = task->sch;
293259

294-
return -ENODEV;
260+
if (sch->ops->schedule_task_after)
261+
return sch->ops->schedule_task_after(sch->data, task, start,
262+
period, after);
263+
264+
return sch->ops->schedule_task(sch->data, task, start, period);
295265
}
296266

297267
/** See scheduler_ops::reschedule_task */
298268
static inline int reschedule_task(struct task *task, uint64_t start)
299269
{
300-
struct schedulers *schedulers = *arch_schedulers_get();
301270
struct schedule_data *sch;
302-
struct list_item *slist;
303271

304-
list_for_item(slist, &schedulers->list) {
305-
sch = container_of(slist, struct schedule_data, list);
306-
if (task->type == sch->type) {
307-
/* optional operation */
308-
if (!sch->ops->reschedule_task)
309-
return 0;
310-
311-
return sch->ops->reschedule_task(sch->data, task,
312-
start);
313-
}
314-
}
272+
assert(task);
273+
sch = task->sch;
315274

316-
return -ENODEV;
275+
/* optional operation */
276+
if (!sch->ops->reschedule_task)
277+
return 0;
278+
279+
return sch->ops->reschedule_task(sch->data, task, start);
317280
}
318281

319282
/** See scheduler_ops::schedule_task_cancel */
320283
static inline int schedule_task_cancel(struct task *task)
321284
{
322-
struct schedulers *schedulers = *arch_schedulers_get();
323285
struct schedule_data *sch;
324-
struct list_item *slist;
325286

326-
list_for_item(slist, &schedulers->list) {
327-
sch = container_of(slist, struct schedule_data, list);
328-
if (task->type == sch->type)
329-
return sch->ops->schedule_task_cancel(sch->data, task);
330-
}
287+
if (!task || !task->sch)
288+
return -EINVAL;
289+
290+
sch = task->sch;
331291

332-
return -ENODEV;
292+
return sch->ops->schedule_task_cancel(sch->data, task);
333293
}
334294

335295
/** See scheduler_ops::schedule_task_free */
336296
static inline int schedule_task_free(struct task *task)
337297
{
338-
struct schedulers *schedulers = *arch_schedulers_get();
339298
struct schedule_data *sch;
340-
struct list_item *slist;
341299

342-
list_for_item(slist, &schedulers->list) {
343-
sch = container_of(slist, struct schedule_data, list);
344-
if (task->type == sch->type)
345-
return sch->ops->schedule_task_free(sch->data, task);
346-
}
300+
if (!task || !task->sch)
301+
return -EINVAL;
302+
303+
sch = task->sch;
347304

348-
return -ENODEV;
305+
return sch->ops->schedule_task_free(sch->data, task);
349306
}
350307

351308
/** See scheduler_ops::scheduler_free */

src/platform/library/schedule/schedule.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,29 @@ int schedule_task_init(struct task *task,
2525
uint16_t priority, enum task_state (*run)(void *data),
2626
void *data, uint16_t core, uint32_t flags)
2727
{
28+
struct schedulers *schedulers = *arch_schedulers_get();
29+
struct schedule_data *sch = NULL;
30+
struct list_item *slist;
31+
2832
if (type >= SOF_SCHEDULE_COUNT)
2933
return -EINVAL;
3034

35+
if (!schedulers)
36+
return -ENODEV;
37+
38+
task->sch = NULL;
39+
list_for_item(slist, &schedulers->list) {
40+
sch = container_of(slist, struct schedule_data, list);
41+
if (type == sch->type) {
42+
task->sch = sch;
43+
break;
44+
}
45+
}
46+
47+
if (!task->sch) {
48+
return -ENODEV;
49+
}
50+
3151
task->uid = uid;
3252
task->type = type;
3353
task->priority = priority;

src/schedule/schedule.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,32 @@ int schedule_task_init(struct task *task,
2727
uint16_t priority, enum task_state (*run)(void *data),
2828
void *data, uint16_t core, uint32_t flags)
2929
{
30+
struct schedulers *schedulers = *arch_schedulers_get();
31+
struct schedule_data *sch = NULL;
32+
struct list_item *slist;
33+
3034
if (type >= SOF_SCHEDULE_COUNT) {
3135
tr_err(&sch_tr, "invalid task type");
3236
return -EINVAL;
3337
}
3438

39+
if (!schedulers)
40+
return -ENODEV;
41+
42+
task->sch = NULL;
43+
list_for_item(slist, &schedulers->list) {
44+
sch = container_of(slist, struct schedule_data, list);
45+
if (type == sch->type) {
46+
task->sch = sch;
47+
break;
48+
}
49+
}
50+
51+
if (!task->sch) {
52+
tr_err(&sch_tr, "unable to bind scheduler to task %p (type %d)", task, type);
53+
return -ENODEV;
54+
}
55+
3556
task->uid = uid;
3657
task->type = type;
3758
task->priority = priority;

src/schedule/zephyr_ll.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,12 @@ int zephyr_ll_task_init(struct task *task,
571571
if (task->priv_data)
572572
return -EEXIST;
573573

574+
/*
575+
* schedule_task_init() must be run on target core, see
576+
* sof/zephyr/schedule.c:arch_schedulers_get()
577+
*/
578+
assert(cpu_get_id() == core);
579+
574580
ret = schedule_task_init(task, uid, type, priority, run, data, core,
575581
flags);
576582
if (ret < 0)

test/cmocka/src/audio/pipeline/pipeline_connection_mocks.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ struct pipeline_connect_data *get_standard_connect_objects(void)
4949
sch->ops = &schedule_mock_ops;
5050
list_item_append(&sch->list, &schedulers->list);
5151

52+
/* Bind the scheduler to the task, as schedule_task_init() would */
53+
pipe->pipe_task->sch = sch;
54+
5255
struct comp_dev *first = calloc(sizeof(struct comp_dev), 1);
5356
struct comp_ipc_config *first_comp = &first->ipc_config;
5457

zephyr/include/rtos/task.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
struct comp_dev;
1919
struct sof;
20+
struct schedule_data;
2021

2122
/** \brief Predefined LL task priorities. */
2223
#define SOF_TASK_PRI_HIGH 0 /* priority level 0 - high */
@@ -59,6 +60,7 @@ struct task {
5960
uint16_t priority; /**< priority of the task (used by LL) */
6061
uint16_t core; /**< execution core */
6162
uint16_t flags; /**< custom flags */
63+
struct schedule_data *sch; /**< scheduler bound to task */
6264
enum task_state state; /**< current state */
6365
void *data; /**< custom data passed to all ops */
6466
struct list_item list; /**< used by schedulers to hold tasks */

0 commit comments

Comments
 (0)