Skip to content

audio: pipeline: change locking strategy for user LL builds#10957

Open
kv2019i wants to merge 3 commits into
thesofproject:mainfrom
kv2019i:202606-ll-locking-change
Open

audio: pipeline: change locking strategy for user LL builds#10957
kv2019i wants to merge 3 commits into
thesofproject:mainfrom
kv2019i:202606-ll-locking-change

Conversation

@kv2019i

@kv2019i kv2019i commented Jun 25, 2026

Copy link
Copy Markdown
Collaborator

A set of patches to change the locking approach for LL audio pipeline scheduling when SOF is built to run all LL pipelines in user-space. The target is to simplify the design and decrease the syscall overhead during typical audio use-cases.

Tested as part of #10558

@kv2019i

kv2019i commented Jun 25, 2026

Copy link
Copy Markdown
Collaborator Author

Keeping as drafts until dependencies are marged and will then update this PR and mark as ready for review.

@kv2019i kv2019i force-pushed the 202606-ll-locking-change branch 2 times, most recently from f1b280d to 1998a42 Compare June 25, 2026 16:07
@kv2019i kv2019i changed the title audio: pipeline: change locking strategy for user LL builds (depends on PR10821) audio: pipeline: change locking strategy for user LL builds Jun 25, 2026
@kv2019i

kv2019i commented Jun 25, 2026

Copy link
Copy Markdown
Collaborator Author

V2 pushed:

  • quick modification to remove the dependency to lock granting PR, now can mark this ready for review

@kv2019i kv2019i marked this pull request as ready for review June 25, 2026 16:09
Copilot AI review requested due to automatic review settings June 25, 2026 16:09

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR changes how mutual exclusion is enforced between the IPC thread and the low-latency (LL) pipeline scheduling path when SOF is built to run LL pipelines in Zephyr user-space, aiming to simplify locking and reduce syscall overhead.

Changes:

  • Keep the LL scheduler mutex held while executing LL tasks in user-space LL builds, shifting protection to a single scheduler-level lock.
  • Introduce user_ll_lock_sched() / user_ll_unlock_sched() as a shared locking API for IPC-side operations that must exclude the LL thread.
  • Remove the per-component list mutex and update IPC/pipeline graph operations to use the LL scheduler lock instead.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/schedule/zephyr_ll.c Holds the scheduler lock while running LL tasks in user-space builds; adds exported scheduler lock/unlock helpers.
src/ipc/ipc4/helper.c Uses the scheduler lock to protect pipeline/module free and updates LL blocking macros to accept src/dst cores.
src/ipc/ipc-helper.c Uses the scheduler lock (user-space builds) instead of IRQ disable/enable when freeing components and manipulating buffer lists.
src/include/sof/schedule/ll_schedule_domain.h Declares the new user_ll_lock_sched() / user_ll_unlock_sched() APIs.
src/include/sof/audio/component.h Removes the user-space-only per-component list mutex.
src/audio/pipeline/pipeline-stream.c Adds scheduler locking around pipeline_copy() in user-space LL builds.
src/audio/pipeline/pipeline-graph.c Switches connect/disconnect list protection to the scheduler lock (or IRQ disable in kernel builds).

Comment thread src/schedule/zephyr_ll.c Outdated
Comment thread src/ipc/ipc-helper.c Outdated
Comment thread src/audio/pipeline/pipeline-stream.c Outdated
Comment thread src/schedule/zephyr_ll.c Outdated
Comment thread src/schedule/zephyr_ll.c Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Comment thread src/schedule/zephyr_ll.c Outdated
Comment thread src/audio/pipeline/pipeline-stream.c Outdated
Comment thread src/ipc/ipc-helper.c
@kv2019i kv2019i force-pushed the 202606-ll-locking-change branch 2 times, most recently from 0705e81 to cb4edfd Compare June 26, 2026 12:36
@kv2019i

kv2019i commented Jun 26, 2026

Copy link
Copy Markdown
Collaborator Author

V2 and V3 pushed:

  • remove the redundant lock calls and turn them into asserts
  • fix typos in code comments

Comment thread src/audio/pipeline/pipeline-graph.c Outdated
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <sof/schedule/ll_schedule_domain.h>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one too many

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed in V4.

Comment thread src/audio/pipeline/pipeline-graph.c Outdated
assert(ret == 0); \
} while (0)
#define PPL_LOCK(x) user_ll_assert_locked(x)
#define PPL_UNLOCK(x)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so PPL_UNLOCK() doesn't need the argument?

@kv2019i kv2019i Jun 30, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, yes, stricly not needed. Can drop in next version. UPDATE: done in V4.

Comment thread src/ipc/ipc4/helper.c Outdated
#define ll_unblock(cross_core_bind, flags) irq_local_enable(flags)
#if CONFIG_SOF_USERSPACE_LL
/* note: cross-core streams are disabled in the build in this branch,
* so we can safely use 'src_core' only */

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could explicitly add a comment that src_core == dst_core

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in V4.

Comment thread src/schedule/zephyr_ll.c
#else
static inline void zephyr_ll_lock_acquired(int core) { (void)core; }
static inline void zephyr_ll_lock_releasing(int core) { (void)core; }
#endif /* CONFIG_ASSERT */

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to the commit description - sorry, couldn't quite follow how it describes this commit. Could you point out where the lock is taken for the whole duration of the LL tick processing? That's what the commit description is saying, right?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lyakh ack, I should merge patches 2 and 3. The actual lock is taken in patch 2, should be merged. Will fix.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I kept these as separate patches (one for scheduler, one for audio pipeline code), but reworded the text in 3rd commit. So 2nd patch changes locking strategy in ll scheduler, 3rd patch removes the now unnecessary locks in audio pipeline level. Changed in V4.

@kv2019i kv2019i force-pushed the 202606-ll-locking-change branch from cb4edfd to a57c14b Compare June 30, 2026 21:54
@kv2019i

kv2019i commented Jun 30, 2026

Copy link
Copy Markdown
Collaborator Author

V4 pushed:

  • addressed comments so far

kv2019i added 3 commits July 1, 2026 01:03
Add new functions to lock/unlock the LL scheduler for a given
core. This is intended for audio application code that needs
to modify the audio pipelines and needs an interface to
get exclusive access to the pipelines on a particular core.

This interface is specific to SOF builds with CONFIG_SOF_USERSPACE_LL.
If LL scheduler is running in kernel space, there is option
to disable interrupts for similar effect. For now these code
paths are kept separate.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
In user-space LL builds (CONFIG_SOF_USERSPACE_LL), the IPC user thread
cannot block interrupts while making modifications to the audio graph.

To workaround this limitation, one could either protect each pipeline
object with locks, or keep the LL level lock held while executing
LL tasks.

This patch implements support for the latter approach. If building SOF
for user LL, do not release the lock when running a task. This will help
to reduce number of syscalls during a LL iteration, while still allowing
to safely implement IPC handlers that need to modify the audio graph.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Modify the locking approach for CONFIG_SOF_USERSPACE_LL builds.
Kernel LL implementation heavily relies on ability to disable
interrupts when IPC handler is modifying the graph. This ensures
a new LL tick and execution of a new graph cycle does not start
before the graph modifications done by IPC handler are complete.

In user-space, this approach is not available as user-space thread
cannot disable interrupts. In commit 1e59ce2 ("pipeline: protect
component connections with a mutex"), a sys_mutex based locking was
implemented to protect the component list and modifications to it. This
approach does not scale in the end as this would require taking the
mutex for each component of each pipeline, and take the locks on every
LL cycle tick. This results in significant system call overhead.
Additionally Zephyr sys_mutex does not work correctly if the lock
object is put into dynamically allocated user memory.

The LL scheduler logic was changed to keep the LL lock when building
with CONFIG_SOF_USERS_SPACE. A single lock is used to protect the whole
LL graph, and the lock is taken at start of LL tick. Take benefit of
this in audio pipeline code and remove redundant locking.

The patch only changes behaviour for userspace LL SOF builds. If
LL scheduling is kept in kernel, locking is done as before.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
@kv2019i kv2019i force-pushed the 202606-ll-locking-change branch from a57c14b to 2a36aba Compare June 30, 2026 22:04
@kv2019i

kv2019i commented Jun 30, 2026

Copy link
Copy Markdown
Collaborator Author

V5 pushed:

  • fix a git squash mistake

#include <sof/audio/module_adapter/module/generic.h>
#include <sof/audio/pipeline.h>
#include <sof/ipc/msg.h>
#include <sof/schedule/ll_schedule_domain.h>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CONFIG_SOF_USERS_SPACE in commit description seems to be wrong

/* Assert that the calling context already holds the LL lock for 'core'. */
void user_ll_assert_locked(int core);
#else
static inline void user_ll_assert_locked(int core) { (void)core; }

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could be ARG_UNUSED(), not important

Comment thread src/ipc/ipc4/helper.c
#if CONFIG_SOF_USERSPACE_LL
/* note: cross-core streams are disabled so src_core==dst_core */
#define ll_block(src_core, dst_core, flags) do { user_ll_lock_sched(src_core); (void)flags; } while(0)
#define ll_unblock(src_core, dst_core, flags) do { user_ll_unlock_sched(src_core) ; (void)flags; } while(0)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also ARG_UNUSED() and also unimportant

Comment thread src/ipc/ipc4/helper.c
#ifdef CONFIG_SOF_USERSPACE_LL
ppl_core = icd->core;
user_ll_lock_sched(ppl_core);
#endif

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

currently this is working with no locking at all, right? Theoretically this could race against pipeline streaming if we have a forking graph where one branch is stopped and freed while the other one is still running, correct? So I suppose we have a guard in place that would prevent the streaming loop from entering the stopped branch safely somehow?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants