schedule: zephyr_ll: implement user/kernel split with init_context()#10818
schedule: zephyr_ll: implement user/kernel split with init_context()#10818kv2019i wants to merge 3 commits into
Conversation
Add an optional method that allow the schedule.h user to get access to the thread context that will be used for scheduling. This is critical when the callbacks are run in user-space context and schedule.h client needs to grant access to objects like locks to the callback thread. Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Add new domain ops that are called from privileged context and are used to set up resources like threads and initialize other kernel objects. Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Use the new scheduler_init_context() and domain_thread_init/free() interfaces to separate LL scheduler logic into privileged and unprivileged parts. The latter can be used by the audio pipeline to add, remove and schedule tasks from the user-space audio thread. The privileged interfaces are used to set up the scheduler during firmware boot. Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
|
For context, part of #10558 |
There was a problem hiding this comment.
Pull request overview
This PR refactors the userspace LL scheduler/domain to introduce a clean kernel/user split. Privileged setup (thread creation, timer init, kernel-object access grants) is moved out of the user-callable domain_register() path into a new kernel-context scheduler_init_context() → domain_thread_init() flow, with a matching domain_thread_free() for teardown. Non-userspace builds are unaffected.
Changes:
- Add optional
scheduler_init_context()operation and helper inschedule.h, plus userspace-onlydomain_thread_init/domain_thread_freeops and inline wrappers inll_schedule_domain.h. - Split
zephyr_domain_register_user()intozephyr_domain_thread_init()(privileged setup) and a bookkeeping-only register; move thread teardown/timer stop/watchdog disable into a newzephyr_domain_thread_free(); guard the thread-fn handler invocation against NULL. - Implement
zephyr_ll_init_context()to drivedomain_thread_init()and the mutex grant; calldomain_thread_free()fromzephyr_ll_scheduler_free(); drop in-line access grants from the schedule hot path.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| src/include/sof/schedule/schedule.h | New optional scheduler_init_context op and dispatch helper. |
| src/include/sof/schedule/ll_schedule_domain.h | New userspace-only domain_thread_init/domain_thread_free ops and wrappers. |
| src/schedule/zephyr_domain.c | Split user register into privileged init + bookkeeping; add thread_free; NULL-handler guard. |
| src/schedule/zephyr_ll.c | Implement zephyr_ll_init_context, wire new ops, call domain_thread_free on scheduler free, drop in-path grants. |
| tr_err(&ll_tr, "%u tasks are still active!", | ||
| sch->n_tasks); | ||
|
|
||
| #if CONFIG_SOF_USERSPACE_LL |
| int core = cpu_get_id(); | ||
| struct zephyr_domain_thread *dt = zephyr_domain->domain_thread + core; |
| ret = domain_register(sch->ll_domain, task, &schedule_ll_callback, sch); | ||
| if (ret < 0) | ||
| tr_err(&ll_tr, "cannot register domain %d", | ||
| ret); | ||
|
|
||
| #if CONFIG_SOF_USERSPACE_LL | ||
| k_thread_access_grant(zephyr_domain_thread_tid(sch->ll_domain), sch->lock); | ||
|
|
||
| tr_dbg(&ll_tr, "granting access to lock %p for thread %p", sch->lock, | ||
| zephyr_domain_thread_tid(sch->ll_domain)); | ||
| tr_dbg(&ll_tr, "granting access to domain lock %p for thread %p", &sch->ll_domain->lock, | ||
| zephyr_domain_thread_tid(sch->ll_domain)); | ||
| #endif | ||
| tr_err(&ll_tr, "cannot register domain %d", ret); | ||
|
|
||
| return 0; |
lgirdwood
left a comment
There was a problem hiding this comment.
LGTM, some opens from copilot
| list_for_item(slist, &schedulers->list) { | ||
| sch = container_of(slist, struct schedule_data, list); | ||
| if (task->type == sch->type && sch->ops->scheduler_init_context) | ||
| return sch->ops->scheduler_init_context(sch->data, task); |
There was a problem hiding this comment.
nitpick - when called for schedulers, which don't have .scheduler_init_context() the loop will iterate over all schedulers instead of return NULL when found. We only have under 5 schedulers so it's a non-issue, but still
| #endif | ||
|
|
||
| dt->handler(dt->arg); | ||
| if (dt->handler) |
A set of changes to SOF schedule.h to allow implementation of clean user/kernel split of the scheduler interface towards the user-space (option build feature) audio pipeline thread.
No functional impact to non-userspace builds.