Skip to content

Commit 4da3a94

Browse files
committed
schedule: add support for LL userspace tasks
Add support for registering user-space LL tasks, and ability to use the task scheduling functions from user-space. The implementation splits scheduler list into kernel and user portions if SOF is built with CONFIG_SOF_USERSPACE_LL. A scheduler type can be either maintained in kernel or user, never both. With this patch, the SOF_SCHEDULE_LL_TIMER is moved to user managed if CONFIG_SOF_USERSPACE_LL is used. Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
1 parent 901c0ce commit 4da3a94

3 files changed

Lines changed: 80 additions & 11 deletions

File tree

src/include/sof/schedule/schedule.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,10 @@ struct schedulers {
180180
*/
181181
struct schedulers **arch_schedulers_get(void);
182182

183+
struct schedulers **arch_user_schedulers_get(void);
184+
185+
struct schedulers **arch_user_schedulers_get_for_core(int core);
186+
183187
/**
184188
* Retrieves scheduler's data.
185189
* @param type SOF_SCHEDULE_ type.
@@ -322,17 +326,13 @@ static inline void schedule_free(uint32_t flags)
322326
/** See scheduler_ops::scheduler_init_context */
323327
static inline struct k_thread *scheduler_init_context(struct task *task)
324328
{
325-
struct schedulers *schedulers = *arch_schedulers_get();
326329
struct schedule_data *sch;
327-
struct list_item *slist;
328330

329-
assert(schedulers);
331+
assert(task && task->sch);
332+
sch = task->sch;
330333

331-
list_for_item(slist, &schedulers->list) {
332-
sch = container_of(slist, struct schedule_data, list);
333-
if (task->type == sch->type && sch->ops->scheduler_init_context)
334-
return sch->ops->scheduler_init_context(sch->data, task);
335-
}
334+
if (sch->ops->scheduler_init_context)
335+
return sch->ops->scheduler_init_context(sch->data, task);
336336

337337
return NULL;
338338
}

src/schedule/schedule.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,23 @@ SOF_DEFINE_REG_UUID(schedule);
2222

2323
DECLARE_TR_CTX(sch_tr, SOF_UUID(schedule_uuid), LOG_LEVEL_INFO);
2424

25+
static inline bool scheduler_is_user(int type)
26+
{
27+
/*
28+
* currently only LL managed in user-space, but longterm
29+
* goal is to move all audio application level scheduling
30+
* to user-space and only keep Zephyr scheduler logic in
31+
* kernel
32+
*/
33+
return type == SOF_SCHEDULE_LL_TIMER;
34+
}
35+
2536
int schedule_task_init(struct task *task,
2637
const struct sof_uuid_entry *uid, uint16_t type,
2738
uint16_t priority, enum task_state (*run)(void *data),
2839
void *data, uint16_t core, uint32_t flags)
2940
{
30-
struct schedulers *schedulers = *arch_schedulers_get();
41+
struct schedulers *schedulers;
3142
struct schedule_data *sch = NULL;
3243
struct list_item *slist;
3344

@@ -36,6 +47,11 @@ int schedule_task_init(struct task *task,
3647
return -EINVAL;
3748
}
3849

50+
if (IS_ENABLED(CONFIG_SOF_USERSPACE_LL) && scheduler_is_user(type))
51+
schedulers = *arch_user_schedulers_get_for_core(core);
52+
else
53+
schedulers = *arch_schedulers_get();
54+
3955
if (!schedulers)
4056
return -ENODEV;
4157

@@ -69,6 +85,9 @@ static void scheduler_register(struct schedule_data *scheduler)
6985
{
7086
struct schedulers **sch = arch_schedulers_get();
7187

88+
if (IS_ENABLED(CONFIG_SOF_USERSPACE_LL) && scheduler_is_user(scheduler->type))
89+
sch = arch_user_schedulers_get();
90+
7291
if (!*sch) {
7392
/* init schedulers list */
7493
*sch = rzalloc(SOF_MEM_FLAG_KERNEL,

zephyr/schedule.c

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,64 @@
1414
#include <sof/lib/cpu.h>
1515
#include <ipc/topology.h>
1616

17-
static APP_SYSUSER_BSS struct schedulers *_schedulers[CONFIG_CORE_COUNT];
17+
/* Kernel-only scheduler list — depending on how SOF is built,
18+
* either holds all or subset of scheduler types.
19+
* Not accessible from user-space threads.
20+
*/
21+
static struct schedulers *_k_schedulers[CONFIG_CORE_COUNT];
22+
23+
#if CONFIG_SOF_USERSPACE_LL
24+
/* User-accessible scheduler list — holds the subset of scheduler
25+
* types that are managed in user-space
26+
*/
27+
static APP_SYSUSER_BSS struct schedulers *_u_schedulers[CONFIG_CORE_COUNT];
28+
#endif
1829

1930
/**
2031
* Retrieves registered schedulers.
2132
* @return List of registered schedulers.
2233
*/
2334
struct schedulers **arch_schedulers_get(void)
2435
{
25-
return _schedulers + cpu_get_id();
36+
#if CONFIG_SOF_USERSPACE_LL
37+
/* user-space callers must use arch_user_schedulers_get() */
38+
assert(!k_is_user_context());
39+
#endif
40+
return _k_schedulers + cpu_get_id();
2641
}
2742
EXPORT_SYMBOL(arch_schedulers_get);
43+
44+
/**
45+
* Retrieves registered user schedulers for the current core.
46+
*
47+
* Relies on cpu_get_id(), so it may invoke privileged functions and
48+
* must not be called from a user-space context. User-space callers
49+
* should use arch_user_schedulers_get_for_core() instead.
50+
*
51+
* @return List of registered schedulers.
52+
*/
53+
struct schedulers **arch_user_schedulers_get(void)
54+
{
55+
#ifdef CONFIG_SOF_USERSPACE_LL
56+
return _u_schedulers + cpu_get_id();
57+
#else
58+
return NULL;
59+
#endif
60+
}
61+
62+
/**
63+
* Retrieves registered user schedulers for the given core.
64+
*
65+
* Unlike arch_user_schedulers_get(), this takes the core explicitly and
66+
* is therefore safe to call from a user-space context.
67+
*
68+
* @return List of registered schedulers.
69+
*/
70+
struct schedulers **arch_user_schedulers_get_for_core(int core)
71+
{
72+
#ifdef CONFIG_SOF_USERSPACE_LL
73+
return _u_schedulers + core;
74+
#else
75+
return NULL;
76+
#endif
77+
}

0 commit comments

Comments
 (0)