zephyr: fix a race in LL-scheduler

If a timer interrupt happens before the scheduler thread suspends,
it will be missed. Use a semaphore to count interrupts as they occur.

BugLink: https://github.com/thesofproject/sof/issues/4306
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
This commit is contained in:
Guennadi Liakhovetski 2021-06-11 12:11:57 +02:00 committed by Liam Girdwood
parent 91467d0924
commit 1eabb71264
1 changed files with 5 additions and 2 deletions

View File

@ -63,6 +63,7 @@ struct zephyr_domain_thread {
struct zephyr_domain {
struct k_timer timer;
struct k_sem sem;
struct timer *ll_timer;
struct zephyr_domain_thread domain_thread[CONFIG_CORE_COUNT];
struct ll_schedule_domain *ll_domain;
@ -76,7 +77,7 @@ static void zephyr_domain_thread_fn(void *p1, void *p2, void *p3)
for (;;) {
/* immediately go to sleep, waiting to be woken up by the timer */
k_thread_suspend(_current);
k_sem_take(&zephyr_domain->sem, K_FOREVER);
dt->handler(dt->arg);
}
@ -93,7 +94,7 @@ static void zephyr_domain_timer_fn(struct k_timer *timer)
for (core = 0; core < CONFIG_CORE_COUNT; core++)
if (zephyr_domain->domain_thread[core].handler)
k_wakeup(&zephyr_domain->domain_thread[core].ll_thread);
k_sem_give(&zephyr_domain->sem);
}
static int zephyr_domain_register(struct ll_schedule_domain *domain,
@ -195,6 +196,8 @@ struct ll_schedule_domain *timer_domain_init(struct timer *timer, int clk)
zephyr_domain->ll_timer = timer;
zephyr_domain->ll_domain = domain;
/* 10 is rather random, we better not accumulate 10 missed timer interrupts */
k_sem_init(&zephyr_domain->sem, 0, 10);
ll_sch_domain_set_pdata(domain, zephyr_domain);