Skip to content

Commit 904bf2f

Browse files
committed
schedule: zephyr_ll: add user_ll_lock/unlock_sched()
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>
1 parent ef1bcdb commit 904bf2f

2 files changed

Lines changed: 38 additions & 0 deletions

File tree

src/include/sof/schedule/ll_schedule_domain.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ struct task *zephyr_ll_task_alloc(void);
120120
struct k_heap *zephyr_ll_user_heap(void);
121121
bool zephyr_ll_user_heap_verify(struct k_heap *heap);
122122
void zephyr_ll_user_resources_init(void);
123+
void user_ll_lock_sched(int core);
124+
void user_ll_unlock_sched(int core);
123125
#endif /* CONFIG_SOF_USERSPACE_LL */
124126

125127
static inline struct ll_schedule_domain *domain_init

src/schedule/zephyr_ll.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,15 @@ struct zephyr_ll_pdata {
4444
struct k_sem sem;
4545
};
4646

47+
#if CONFIG_SOF_USERSPACE_LL
48+
/*
49+
* Mutex pointer in user-accessible partition so user-space threads
50+
* can read the pointer for syscalls. The actual lock object resides
51+
* in kernel memory, there are just handles!
52+
*/
53+
static APP_SYSUSER_BSS struct k_mutex *zephyr_ll_locks[CONFIG_CORE_COUNT];
54+
#endif
55+
4756
static void zephyr_ll_lock(struct zephyr_ll *sch, uint32_t *flags)
4857
{
4958
#if CONFIG_SOF_USERSPACE_LL
@@ -561,6 +570,31 @@ struct task *zephyr_ll_task_alloc(void)
561570

562571
return task;
563572
}
573+
574+
/**
575+
* Lock the LL scheduler to prevent it from processing tasks.
576+
*
577+
* Uses the LL scheduler's own k_mutex which is re-entrant, so
578+
* schedule_task() calls within the locked section will not deadlock.
579+
* Must be paired with user_ll_unlock_sched().
580+
*/
581+
void user_ll_lock_sched(int core)
582+
{
583+
assert(core < CONFIG_CORE_COUNT && zephyr_ll_locks[core] != NULL);
584+
int __maybe_unused ret = k_mutex_lock(zephyr_ll_locks[core], K_FOREVER);
585+
assert(!ret);
586+
}
587+
588+
/**
589+
* Unlock the LL scheduler after a previous user_ll_lock_sched() call.
590+
*/
591+
void user_ll_unlock_sched(int core)
592+
{
593+
assert(core < CONFIG_CORE_COUNT && zephyr_ll_locks[core] != NULL);
594+
int __maybe_unused ret = k_mutex_unlock(zephyr_ll_locks[core]);
595+
assert(!ret);
596+
}
597+
564598
#endif /* CONFIG_SOF_USERSPACE_LL */
565599

566600
int zephyr_ll_task_init(struct task *task,
@@ -649,6 +683,8 @@ __cold int zephyr_ll_scheduler_init(struct ll_schedule_domain *domain)
649683
sof_heap_free(sch->heap, sch);
650684
return -ENOMEM;
651685
}
686+
assert(core < CONFIG_CORE_COUNT && zephyr_ll_locks[core] == NULL);
687+
zephyr_ll_locks[core] = sch->lock;
652688
k_mutex_init(sch->lock);
653689

654690
tr_dbg(&ll_tr, "ll-scheduler init done, sch %p sch->lock %p", sch, sch->lock);

0 commit comments

Comments
 (0)