Skip to content

Commit facb416

Browse files
committed
dp: fork and optimise a native version
Fork a version of the deviating DP functions for a native (proxy- free) implementation. The first deviation is the removal of task recalculation at the end of DP task runs. DP tasks are recalculated on every LL tick (typically every 1ms). DP threads then run with varying periodicity and duration. They can take 10 or even 100ms to run. Also recalculating tasks in the end of those runs doesn't improve anything and only adds load and a need to protect data. This is even worse when DP threads run in user space. Skip recalculation for the native version. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
1 parent baf62c3 commit facb416

File tree

2 files changed

+170
-4
lines changed

2 files changed

+170
-4
lines changed

src/schedule/CMakeLists.txt

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,17 @@ else()
3838
)
3939
endif()
4040

41-
zephyr_library_sources_ifdef(CONFIG_ZEPHYR_DP_SCHEDULER
42-
zephyr_dp_schedule.c
43-
zephyr_dp_schedule_proxy.c
44-
)
41+
if (CONFIG_SOF_USERSPACE_PROXY OR NOT CONFIG_USERSPACE)
42+
zephyr_library_sources_ifdef(CONFIG_ZEPHYR_DP_SCHEDULER
43+
zephyr_dp_schedule.c
44+
zephyr_dp_schedule_proxy.c
45+
)
46+
else()
47+
zephyr_library_sources_ifdef(CONFIG_ZEPHYR_DP_SCHEDULER
48+
zephyr_dp_schedule.c
49+
zephyr_dp_schedule_native.c
50+
)
51+
endif()
4552

4653
zephyr_library_sources_ifdef(CONFIG_ZEPHYR_TWB_SCHEDULER
4754
zephyr_twb_schedule.c
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
// SPDX-License-Identifier: BSD-3-Clause
2+
/*
3+
* Copyright(c) 2025 Intel Corporation. All rights reserved.
4+
*
5+
* Author: Marcin Szkudlinski
6+
*/
7+
8+
#include <rtos/task.h>
9+
10+
#include <sof/audio/module_adapter/module/generic.h>
11+
#include <sof/common.h>
12+
#include <sof/list.h>
13+
#include <sof/schedule/ll_schedule_domain.h>
14+
15+
#include <zephyr/kernel.h>
16+
17+
#include <stdbool.h>
18+
#include <stdint.h>
19+
20+
#include "zephyr_dp_schedule.h"
21+
22+
/* Go through all DP tasks and recalculate their readiness and deadlines
23+
* NOT REENTRANT, should be called with scheduler_dp_lock()
24+
*/
25+
void scheduler_dp_recalculate(struct scheduler_dp_data *dp_sch, bool is_ll_post_run)
26+
{
27+
struct list_item *tlist;
28+
struct task *curr_task;
29+
struct task_dp_pdata *pdata;
30+
31+
list_for_item(tlist, &dp_sch->tasks) {
32+
curr_task = container_of(tlist, struct task, list);
33+
pdata = curr_task->priv_data;
34+
struct processing_module *mod = pdata->mod;
35+
bool trigger_task = false;
36+
37+
/* decrease number of LL ticks/cycles left till the module reaches its deadline */
38+
if (mod->dp_startup_delay && is_ll_post_run && pdata->ll_cycles_to_start) {
39+
pdata->ll_cycles_to_start--;
40+
if (!pdata->ll_cycles_to_start)
41+
/* delayed start complete, clear startup delay flag.
42+
* see dp_startup_delay comment for details
43+
*/
44+
mod->dp_startup_delay = false;
45+
}
46+
47+
if (curr_task->state == SOF_TASK_STATE_QUEUED) {
48+
bool mod_ready;
49+
50+
mod_ready = module_is_ready_to_process(mod, mod->sources,
51+
mod->num_of_sources,
52+
mod->sinks,
53+
mod->num_of_sinks);
54+
if (mod_ready) {
55+
/* trigger the task */
56+
curr_task->state = SOF_TASK_STATE_RUNNING;
57+
if (mod->dp_startup_delay && !pdata->ll_cycles_to_start) {
58+
/* first time run - use delayed start */
59+
pdata->ll_cycles_to_start =
60+
module_get_lpt(pdata->mod) / LL_TIMER_PERIOD_US;
61+
62+
/* in case LPT < LL cycle - delay at least cycle */
63+
if (!pdata->ll_cycles_to_start)
64+
pdata->ll_cycles_to_start = 1;
65+
}
66+
trigger_task = true;
67+
k_sem_give(pdata->sem);
68+
}
69+
}
70+
if (curr_task->state == SOF_TASK_STATE_RUNNING) {
71+
/* (re) calculate deadline for all running tasks */
72+
/* get module deadline in us*/
73+
uint32_t deadline = module_get_deadline(mod);
74+
75+
/* if a deadline cannot be calculated, use a fixed value relative to its
76+
* first start
77+
*/
78+
if (deadline >= UINT32_MAX / 2 && trigger_task)
79+
deadline = module_get_lpt(mod);
80+
81+
if (deadline < UINT32_MAX) {
82+
/* round down to 1ms */
83+
deadline = deadline / 1000;
84+
85+
/* calculate number of ticks */
86+
deadline = deadline * (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / 1000);
87+
88+
/* add to "NOW", overflows are OK */
89+
deadline = dp_sch->last_ll_tick_timestamp + deadline;
90+
91+
/* set in Zephyr. Note that it may be in past, it does not matter,
92+
* Zephyr still will schedule the thread with earlier deadline
93+
* first
94+
*/
95+
k_thread_absolute_deadline_set(pdata->thread_id, deadline);
96+
}
97+
}
98+
}
99+
}
100+
101+
/* Thread function called in component context, on target core */
102+
void dp_thread_fn(void *p1, void *p2, void *p3)
103+
{
104+
struct task *task = p1;
105+
(void)p2;
106+
(void)p3;
107+
struct task_dp_pdata *task_pdata = task->priv_data;
108+
unsigned int lock_key;
109+
enum task_state state;
110+
bool task_stop;
111+
112+
do {
113+
/*
114+
* the thread is started immediately after creation, it will stop on semaphore
115+
* Semaphore will be released once the task is ready to process
116+
*/
117+
k_sem_take(task_pdata->sem, K_FOREVER);
118+
119+
if (task->state == SOF_TASK_STATE_RUNNING)
120+
state = task_run(task);
121+
else
122+
state = task->state; /* to avoid undefined variable warning */
123+
124+
lock_key = scheduler_dp_lock(task->core);
125+
/*
126+
* check if task is still running, may have been canceled by external call
127+
* if not, set the state returned by run procedure
128+
*/
129+
if (task->state == SOF_TASK_STATE_RUNNING) {
130+
task->state = state;
131+
switch (state) {
132+
case SOF_TASK_STATE_RESCHEDULE:
133+
/* mark to reschedule, schedule time is already calculated */
134+
task->state = SOF_TASK_STATE_QUEUED;
135+
break;
136+
137+
case SOF_TASK_STATE_CANCEL:
138+
case SOF_TASK_STATE_COMPLETED:
139+
/* remove from scheduling */
140+
list_item_del(&task->list);
141+
break;
142+
143+
default:
144+
/* illegal state, serious defect, won't happen */
145+
k_panic();
146+
}
147+
}
148+
149+
/* if true exit the while loop, terminate the thread */
150+
task_stop = task->state == SOF_TASK_STATE_COMPLETED ||
151+
task->state == SOF_TASK_STATE_CANCEL;
152+
153+
scheduler_dp_unlock(lock_key);
154+
} while (!task_stop);
155+
156+
/* call task_complete */
157+
if (task->state == SOF_TASK_STATE_COMPLETED)
158+
task_complete(task);
159+
}

0 commit comments

Comments
 (0)