Skip to content

Commit 45cb707

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 45cb707

3 files changed

Lines changed: 91 additions & 10 deletions

File tree

src/include/sof/schedule/schedule.h

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

183+
struct schedulers **arch_user_schedulers_get(void);
184+
185+
#if CONFIG_SOF_USERSPACE_LL
186+
struct schedulers **arch_user_schedulers_get_for_core(int core);
187+
#endif
188+
183189
/**
184190
* Retrieves scheduler's data.
185191
* @param type SOF_SCHEDULE_ type.
@@ -322,17 +328,13 @@ static inline void schedule_free(uint32_t flags)
322328
/** See scheduler_ops::scheduler_init_context */
323329
static inline struct k_thread *scheduler_init_context(struct task *task)
324330
{
325-
struct schedulers *schedulers = *arch_schedulers_get();
326331
struct schedule_data *sch;
327-
struct list_item *slist;
328332

329-
assert(schedulers);
333+
assert(task && task->sch);
334+
sch = task->sch;
330335

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-
}
336+
if (sch->ops->scheduler_init_context)
337+
return sch->ops->scheduler_init_context(sch->data, task);
336338

337339
return NULL;
338340
}

src/schedule/schedule.c

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

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

25+
#ifdef CONFIG_SOF_USERSPACE_LL
26+
static inline bool scheduler_is_user(int type)
27+
{
28+
/*
29+
* currently only LL managed in user-space, but longterm
30+
* goal is to move all audio application level scheduling
31+
* to user-space and only keep Zephyr scheduler logic in
32+
* kernel
33+
*/
34+
return type == SOF_SCHEDULE_LL_TIMER;
35+
}
36+
#endif
37+
2538
int schedule_task_init(struct task *task,
2639
const struct sof_uuid_entry *uid, uint16_t type,
2740
uint16_t priority, enum task_state (*run)(void *data),
2841
void *data, uint16_t core, uint32_t flags)
2942
{
30-
struct schedulers *schedulers = *arch_schedulers_get();
43+
struct schedulers *schedulers;
3144
struct schedule_data *sch = NULL;
3245
struct list_item *slist;
3346

@@ -36,6 +49,15 @@ int schedule_task_init(struct task *task,
3649
return -EINVAL;
3750
}
3851

52+
#ifdef CONFIG_SOF_USERSPACE_LL
53+
if (scheduler_is_user(type))
54+
schedulers = *arch_user_schedulers_get_for_core(core);
55+
else
56+
schedulers = *arch_schedulers_get();
57+
#else
58+
schedulers = *arch_schedulers_get();
59+
#endif
60+
3961
if (!schedulers)
4062
return -ENODEV;
4163

@@ -69,6 +91,11 @@ static void scheduler_register(struct schedule_data *scheduler)
6991
{
7092
struct schedulers **sch = arch_schedulers_get();
7193

94+
#ifdef CONFIG_SOF_USERSPACE_LL
95+
if (scheduler_is_user(scheduler->type))
96+
sch = arch_user_schedulers_get();
97+
#endif
98+
7299
if (!*sch) {
73100
/* init schedulers list */
74101
*sch = rzalloc(SOF_MEM_FLAG_KERNEL,

zephyr/schedule.c

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,66 @@
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 *_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 *_schedulers_user[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
{
36+
#if CONFIG_SOF_USERSPACE_LL
37+
/* user-space callers must use arch_user_schedulers_get() */
38+
assert(!k_is_user_context());
39+
#endif
2540
return _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 _schedulers_user + cpu_get_id();
57+
#else
58+
return NULL;
59+
#endif
60+
}
61+
EXPORT_SYMBOL(arch_user_schedulers_get);
62+
63+
/**
64+
* Retrieves registered user schedulers for the given core.
65+
*
66+
* Unlike arch_user_schedulers_get(), this takes the core explicitly and
67+
* is therefore safe to call from a user-space context.
68+
*
69+
* @return List of registered schedulers.
70+
*/
71+
struct schedulers **arch_user_schedulers_get_for_core(int core)
72+
{
73+
#ifdef CONFIG_SOF_USERSPACE_LL
74+
return _schedulers_user + core;
75+
#else
76+
return NULL;
77+
#endif
78+
}
79+
EXPORT_SYMBOL(arch_user_schedulers_get_for_core);

0 commit comments

Comments
 (0)