Skip to content

Commit 1c64411

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 1c64411

6 files changed

Lines changed: 86 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: 35 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -202,149 +202,105 @@ 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+
assert(task);
226+
sch = task->sch;
240227

241-
return -ENODEV;
228+
return sch->ops->schedule_task(sch->data, task, start, period);
242229
}
243230

244231
/** See scheduler_ops::schedule_task_before */
245232
static inline int schedule_task_before(struct task *task, uint64_t start,
246233
uint64_t period, struct task *before)
247234
{
248-
struct schedulers *schedulers = *arch_schedulers_get();
249235
struct schedule_data *sch;
250-
struct list_item *slist;
251236

252237
if (!task || !before)
253238
return -EINVAL;
254239

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-
}
240+
assert(task);
241+
sch = task->sch;
266242

267-
return -ENODEV;
243+
if (sch->ops->schedule_task_before)
244+
return sch->ops->schedule_task_before(sch->data, task, start,
245+
period, before);
246+
247+
return sch->ops->schedule_task(sch->data, task, start, period);
268248
}
269249

270250
/** See scheduler_ops::schedule_task_after */
271251
static inline int schedule_task_after(struct task *task, uint64_t start,
272252
uint64_t period, struct task *after)
273253
{
274-
struct schedulers *schedulers = *arch_schedulers_get();
275254
struct schedule_data *sch;
276-
struct list_item *slist;
277255

278256
if (!task || !after)
279257
return -EINVAL;
280258

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-
}
259+
assert(task);
260+
sch = task->sch;
261+
262+
if (sch->ops->schedule_task_after)
263+
return sch->ops->schedule_task_after(sch->data, task, start,
264+
period, after);
292265

293-
return -ENODEV;
266+
return sch->ops->schedule_task(sch->data, task, start, period);
294267
}
295268

296269
/** See scheduler_ops::reschedule_task */
297270
static inline int reschedule_task(struct task *task, uint64_t start)
298271
{
299-
struct schedulers *schedulers = *arch_schedulers_get();
300272
struct schedule_data *sch;
301-
struct list_item *slist;
302273

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-
}
274+
assert(task);
275+
sch = task->sch;
314276

315-
return -ENODEV;
277+
/* optional operation */
278+
if (!sch->ops->reschedule_task)
279+
return 0;
280+
281+
return sch->ops->reschedule_task(sch->data, task, start);
316282
}
317283

318284
/** See scheduler_ops::schedule_task_cancel */
319285
static inline int schedule_task_cancel(struct task *task)
320286
{
321-
struct schedulers *schedulers = *arch_schedulers_get();
322287
struct schedule_data *sch;
323-
struct list_item *slist;
324288

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-
}
289+
assert(task);
290+
sch = task->sch;
330291

331-
return -ENODEV;
292+
return sch->ops->schedule_task_cancel(sch->data, task);
332293
}
333294

334295
/** See scheduler_ops::schedule_task_free */
335296
static inline int schedule_task_free(struct task *task)
336297
{
337-
struct schedulers *schedulers = *arch_schedulers_get();
338298
struct schedule_data *sch;
339-
struct list_item *slist;
340299

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-
}
300+
assert(task);
301+
sch = task->sch;
346302

347-
return -ENODEV;
303+
return sch->ops->schedule_task_free(sch->data, task);
348304
}
349305

350306
/** 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)

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)