Skip to content

Commit 87912a9

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 1f4b8f0 commit 87912a9

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
@@ -202,149 +202,106 @@ static inline void *scheduler_get_data(uint16_t type)
202202
/** See scheduler_ops::schedule_task_running */
203203
static inline int schedule_task_running(struct task *task)
204204
{
205-
struct schedulers *schedulers = *arch_schedulers_get();
206205
struct schedule_data *sch;
207-
struct list_item *slist;
208206

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

216-
return sch->ops->schedule_task_running(sch->data, task);
217-
}
218-
}
210+
if (!sch->ops->schedule_task_running)
211+
return 0;
219212

220-
return -ENODEV;
213+
return sch->ops->schedule_task_running(sch->data, task);
221214
}
222215

223216
/** See scheduler_ops::schedule_task */
224217
static inline int schedule_task(struct task *task, uint64_t start,
225218
uint64_t period)
226219
{
227-
struct schedulers *schedulers = *arch_schedulers_get();
228220
struct schedule_data *sch;
229-
struct list_item *slist;
230221

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

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

241-
return -ENODEV;
227+
return sch->ops->schedule_task(sch->data, task, start, period);
242228
}
243229

244230
/** See scheduler_ops::schedule_task_before */
245231
static inline int schedule_task_before(struct task *task, uint64_t start,
246232
uint64_t period, struct task *before)
247233
{
248-
struct schedulers *schedulers = *arch_schedulers_get();
249234
struct schedule_data *sch;
250-
struct list_item *slist;
251235

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

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

267-
return -ENODEV;
245+
return sch->ops->schedule_task(sch->data, task, start, period);
268246
}
269247

270248
/** See scheduler_ops::schedule_task_after */
271249
static inline int schedule_task_after(struct task *task, uint64_t start,
272250
uint64_t period, struct task *after)
273251
{
274-
struct schedulers *schedulers = *arch_schedulers_get();
275252
struct schedule_data *sch;
276-
struct list_item *slist;
277253

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

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

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

296266
/** See scheduler_ops::reschedule_task */
297267
static inline int reschedule_task(struct task *task, uint64_t start)
298268
{
299-
struct schedulers *schedulers = *arch_schedulers_get();
300269
struct schedule_data *sch;
301-
struct list_item *slist;
302270

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

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

318281
/** See scheduler_ops::schedule_task_cancel */
319282
static inline int schedule_task_cancel(struct task *task)
320283
{
321-
struct schedulers *schedulers = *arch_schedulers_get();
322284
struct schedule_data *sch;
323-
struct list_item *slist;
324285

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

331-
return -ENODEV;
291+
return sch->ops->schedule_task_cancel(sch->data, task);
332292
}
333293

334294
/** See scheduler_ops::schedule_task_free */
335295
static inline int schedule_task_free(struct task *task)
336296
{
337-
struct schedulers *schedulers = *arch_schedulers_get();
338297
struct schedule_data *sch;
339-
struct list_item *slist;
340298

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

347-
return -ENODEV;
304+
return sch->ops->schedule_task_free(sch->data, task);
348305
}
349306

350307
/** 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
@@ -543,6 +543,12 @@ int zephyr_ll_task_init(struct task *task,
543543
if (task->priv_data)
544544
return -EEXIST;
545545

546+
/*
547+
* schedule_task_init() must be run on target core, see
548+
* sof/zephyr/schedule.c:arch_schedulers_get()
549+
*/
550+
assert(cpu_get_id() == core);
551+
546552
ret = schedule_task_init(task, uid, type, priority, run, data, core,
547553
flags);
548554
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)