Skip to content

Commit 364e1e1

Browse files
committed
dp: convert to user-space
Run DP threads in user-space. Move all the respective memory and kobjects to a dedicated memory domain. Work around Zephyr inability to remove memory domains on Xtensa. Signed-off-by: Guennadi Liakhovetski <[email protected]>
1 parent 9820996 commit 364e1e1

File tree

14 files changed

+484
-171
lines changed

14 files changed

+484
-171
lines changed

app/boards/intel_adsp_ace30_ptl.conf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ CONFIG_LLEXT=y
4242
CONFIG_LLEXT_STORAGE_WRITABLE=y
4343
CONFIG_LLEXT_EXPERIMENTAL=y
4444
CONFIG_MODULES=y
45+
CONFIG_USERSPACE=y
4546

4647
# Zephyr / device drivers
4748
CONFIG_DAI_INIT_PRIORITY=70

app/prj.conf

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,9 @@ CONFIG_SCHED_CPU_MASK=y
4848
CONFIG_SYS_CLOCK_TICKS_PER_SEC=15000
4949
CONFIG_DAI=y
5050
CONFIG_HEAP_MEM_POOL_SIZE=2048
51+
52+
# Support dynamic thread stack allocation
53+
CONFIG_DYNAMIC_THREAD=y
54+
CONFIG_DYNAMIC_THREAD_ALLOC=y
55+
CONFIG_DYNAMIC_THREAD_PREFER_ALLOC=y
56+
CONFIG_MAX_THREAD_BYTES=3

src/audio/buffers/comp_buffer.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <rtos/cache.h>
1919
#include <sof/lib/notifier.h>
2020
#include <sof/list.h>
21+
#include <sof/schedule/dp_schedule.h>
2122
#include <rtos/spinlock.h>
2223
#include <rtos/symbol.h>
2324
#include <ipc/topology.h>
@@ -158,8 +159,16 @@ static void comp_buffer_free(struct sof_audio_buffer *audio_buffer)
158159
/* In case some listeners didn't unregister from buffer's callbacks */
159160
notifier_unregister_all(NULL, buffer);
160161

162+
struct k_heap *heap = buffer->audio_buffer.heap;
163+
161164
rfree(buffer->stream.addr);
162-
sof_heap_free(buffer->audio_buffer.heap, buffer);
165+
sof_heap_free(heap, buffer);
166+
if (heap) {
167+
struct dp_heap_user *mod_heap_user = container_of(heap, struct dp_heap_user, heap);
168+
169+
if (!--mod_heap_user->client_count)
170+
rfree(mod_heap_user);
171+
}
163172
}
164173

165174
APP_TASK_DATA static const struct source_ops comp_buffer_source_ops = {

src/audio/module_adapter/module/generic.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ int module_load_config(struct comp_dev *dev, const void *cfg, size_t size)
7878
return ret;
7979
}
8080

81-
static void mod_resource_init(struct processing_module *mod)
81+
void mod_resource_init(struct processing_module *mod)
8282
{
8383
struct module_data *md = &mod->priv;
8484
/* Init memory list */
@@ -116,7 +116,6 @@ int module_init(struct processing_module *mod)
116116
return -EIO;
117117
}
118118

119-
mod_resource_init(mod);
120119
#if CONFIG_MODULE_MEMORY_API_DEBUG && defined(__ZEPHYR__)
121120
mod->priv.resources.rsrc_mngr = k_current_get();
122121
#endif
@@ -181,6 +180,17 @@ static void container_put(struct processing_module *mod, struct module_resource
181180
list_item_append(&container->list, &res->free_cont_list);
182181
}
183182

183+
void mod_heap_info(struct processing_module *mod, size_t *size, uintptr_t *start)
184+
{
185+
struct module_resources *res = &mod->priv.resources;
186+
187+
if (size)
188+
*size = res->heap_size;
189+
190+
if (start)
191+
*start = (uintptr_t)container_of(res->heap, struct dp_heap_user, heap);
192+
}
193+
184194
/**
185195
* Allocates aligned buffer memory block for module.
186196
* @param mod Pointer to the module this memory block is allocated for.
@@ -416,6 +426,7 @@ int z_impl_mod_free(struct processing_module *mod, const void *ptr)
416426
EXPORT_SYMBOL(z_impl_mod_free);
417427

418428
#ifdef CONFIG_USERSPACE
429+
#include <zephyr/internal/syscall_handler.h>
419430
const void *z_vrfy_mod_fast_get(struct processing_module *mod, const void * const dram_ptr,
420431
size_t size)
421432
{

src/audio/module_adapter/module_adapter.c

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -58,24 +58,27 @@ struct comp_dev *module_adapter_new(const struct comp_driver *drv,
5858
#define PAGE_SZ HOST_PAGE_SIZE
5959
#endif
6060

61-
static struct k_heap *module_adapter_dp_heap_new(const struct comp_ipc_config *config)
61+
static struct k_heap *module_adapter_dp_heap_new(const struct comp_ipc_config *config,
62+
size_t *heap_size)
6263
{
6364
/* src-lite with 8 channels has been seen allocating 14k in one go */
6465
/* FIXME: the size will be derived from configuration */
65-
const size_t heap_size = 20 * 1024;
66+
const size_t buf_size = 20 * 1024;
6667

6768
/* Keep uncached to match the default SOF heap! */
6869
uint8_t *mod_heap_mem = rballoc_align(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT,
69-
heap_size, PAGE_SZ);
70+
buf_size, PAGE_SZ);
7071

7172
if (!mod_heap_mem)
7273
return NULL;
7374

74-
struct k_heap *mod_heap = (struct k_heap *)mod_heap_mem;
75-
const size_t heap_prefix_size = ALIGN_UP(sizeof(*mod_heap), 8);
75+
struct dp_heap_user *mod_heap_user = (struct dp_heap_user *)mod_heap_mem;
76+
struct k_heap *mod_heap = &mod_heap_user->heap;
77+
const size_t heap_prefix_size = ALIGN_UP(sizeof(*mod_heap_user), 4);
7678
void *mod_heap_buf = mod_heap_mem + heap_prefix_size;
7779

78-
k_heap_init(mod_heap, mod_heap_buf, heap_size - heap_prefix_size);
80+
*heap_size = buf_size - heap_prefix_size;
81+
k_heap_init(mod_heap, mod_heap_buf, *heap_size);
7982

8083
return mod_heap;
8184
}
@@ -93,16 +96,21 @@ static struct processing_module *module_adapter_mem_alloc(const struct comp_driv
9396
*/
9497
uint32_t flags = config->proc_domain == COMP_PROCESSING_DOMAIN_DP ?
9598
SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT : SOF_MEM_FLAG_USER;
99+
struct dp_heap_user *mod_heap_user;
100+
size_t heap_size;
96101

97102
if (config->proc_domain == COMP_PROCESSING_DOMAIN_DP && IS_ENABLED(CONFIG_USERSPACE) &&
98103
!IS_ENABLED(CONFIG_SOF_USERSPACE_USE_DRIVER_HEAP)) {
99-
mod_heap = module_adapter_dp_heap_new(config);
104+
mod_heap = module_adapter_dp_heap_new(config, &heap_size);
100105
if (!mod_heap) {
101106
comp_cl_err(drv, "Failed to allocate DP module heap");
102107
return NULL;
103108
}
109+
mod_heap_user = container_of(mod_heap, struct dp_heap_user, heap);
104110
} else {
105111
mod_heap = drv->user_heap;
112+
mod_heap_user = NULL;
113+
heap_size = 0;
106114
}
107115

108116
struct processing_module *mod = sof_heap_alloc(mod_heap, flags, sizeof(*mod), 0);
@@ -114,6 +122,8 @@ static struct processing_module *module_adapter_mem_alloc(const struct comp_driv
114122

115123
memset(mod, 0, sizeof(*mod));
116124
mod->priv.resources.heap = mod_heap;
125+
mod->priv.resources.heap_size = heap_size;
126+
mod_resource_init(mod);
117127

118128
/*
119129
* Would be difficult to optimize the allocation to use cache. Only if
@@ -134,26 +144,37 @@ static struct processing_module *module_adapter_mem_alloc(const struct comp_driv
134144
mod->dev = dev;
135145
dev->mod = mod;
136146

147+
if (mod_heap_user)
148+
mod_heap_user->client_count++;
149+
137150
return mod;
138151

139152
err:
140153
sof_heap_free(mod_heap, mod);
141154
emod:
142-
if (mod_heap != drv->user_heap)
143-
rfree(mod_heap);
155+
rfree(mod_heap_user);
144156

145157
return NULL;
146158
}
147159

148160
static void module_adapter_mem_free(struct processing_module *mod)
149161
{
150162
struct k_heap *mod_heap = mod->priv.resources.heap;
163+
struct dp_heap_user *mod_heap_user = container_of(mod_heap, struct dp_heap_user, heap);
151164

165+
/*
166+
* In principle it shouldn't even be needed to free individual objects
167+
* on the module heap since we're freeing the heap itself too
168+
*/
152169
#if CONFIG_IPC_MAJOR_4
153170
sof_heap_free(mod_heap, mod->priv.cfg.input_pins);
154171
#endif
172+
list_item_del(&mod->dev->bsource_list);
173+
list_item_del(&mod->dev->bsink_list);
155174
sof_heap_free(mod_heap, mod->dev);
156175
sof_heap_free(mod_heap, mod);
176+
if (!mod_heap || !--mod_heap_user->client_count)
177+
rfree(mod_heap_user);
157178
}
158179

159180
/*
@@ -1374,11 +1395,16 @@ void module_adapter_free(struct comp_dev *dev)
13741395
comp_dbg(dev, "start");
13751396

13761397
if (dev->task) {
1377-
/* Run DP module's .free() method in its thread context */
1398+
/*
1399+
* Run DP module's .free() method in its thread context.
1400+
* Unlike with other IPCs we first run module's .free() in
1401+
* thread context, then cancel the thread, and then execute
1402+
* final clean up
1403+
*/
13781404
#if CONFIG_IPC_MAJOR_4
13791405
scheduler_dp_thread_ipc(mod, SOF_IPC4_MOD_DELETE_INSTANCE, NULL);
13801406
#endif
1381-
schedule_task_cancel(dev->task);
1407+
schedule_task_free(dev->task);
13821408
}
13831409

13841410
ret = module_free(mod);

src/include/sof/audio/component_ext.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,6 @@ struct comp_dev *comp_new_ipc4(struct ipc4_module_init_instance *module_init);
4444
/** See comp_ops::free */
4545
static inline void comp_free(struct comp_dev *dev)
4646
{
47-
struct task *task = dev->is_shared ||
48-
dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP ? dev->task : NULL;
4947
const struct comp_driver *drv = dev->drv;
5048

5149
assert(drv->ops.free);
@@ -55,12 +53,6 @@ static inline void comp_free(struct comp_dev *dev)
5553
* be freed after this.
5654
*/
5755
drv->ops.free(dev);
58-
59-
/* free task if shared component or DP task*/
60-
if (task) {
61-
schedule_task_free(task);
62-
sof_heap_free(drv->user_heap, task);
63-
}
6456
}
6557

6658
/**

src/include/sof/audio/module_adapter/module/generic.h

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ struct module_resources {
134134
size_t heap_usage;
135135
size_t heap_high_water_mark;
136136
struct k_heap *heap;
137+
size_t heap_size;
137138
#if CONFIG_MODULE_MEMORY_API_DEBUG && defined(__ZEPHYR__)
138139
k_tid_t rsrc_mngr;
139140
#endif
@@ -191,9 +192,19 @@ struct module_processing_data {
191192
int module_load_config(struct comp_dev *dev, const void *cfg, size_t size);
192193
int module_init(struct processing_module *mod);
193194
void *mod_balloc_align(struct processing_module *mod, size_t size, size_t alignment);
195+
void mod_resource_init(struct processing_module *mod);
196+
void mod_heap_info(struct processing_module *mod, size_t *size, uintptr_t *start);
197+
#if defined(__ZEPHYR__) && defined(CONFIG_SOF_FULL_ZEPHYR_APPLICATION)
194198
__syscall void *mod_alloc_ext(struct processing_module *mod, uint32_t flags, size_t size,
195199
size_t alignment);
196200
__syscall int mod_free(struct processing_module *mod, const void *ptr);
201+
#else
202+
void *z_impl_mod_alloc_ext(struct processing_module *mod, uint32_t flags, size_t size,
203+
size_t alignment);
204+
int z_impl_mod_free(struct processing_module *mod, const void *ptr);
205+
#define mod_alloc_ext z_impl_mod_alloc_ext
206+
#define mod_free z_impl_mod_free
207+
#endif
197208

198209
/**
199210
* Allocates aligned memory block for module.
@@ -234,17 +245,21 @@ struct comp_data_blob_handler *mod_data_blob_handler_new(struct processing_modul
234245
void mod_data_blob_handler_free(struct processing_module *mod, struct comp_data_blob_handler *dbh);
235246
#endif
236247
#if CONFIG_FAST_GET
248+
#if defined(__ZEPHYR__) && defined(CONFIG_SOF_FULL_ZEPHYR_APPLICATION)
237249
__syscall const void *mod_fast_get(struct processing_module *mod, const void * const dram_ptr,
238250
size_t size);
251+
#else
252+
const void *z_impl_mod_fast_get(struct processing_module *mod, const void * const dram_ptr,
253+
size_t size);
254+
#define mod_fast_get z_impl_mod_fast_get
255+
#endif
239256
void mod_fast_put(struct processing_module *mod, const void *sram_ptr);
240257
#endif
241258
void mod_free_all(struct processing_module *mod);
242259
int module_prepare(struct processing_module *mod,
243260
struct sof_source **sources, int num_of_sources,
244261
struct sof_sink **sinks, int num_of_sinks);
245262

246-
#include <zephyr/syscalls/generic.h>
247-
248263
static inline
249264
bool generic_module_is_ready_to_process(struct processing_module *mod,
250265
struct sof_source **sources,
@@ -454,4 +469,8 @@ static inline uint32_t module_get_lpt(struct processing_module *mod)
454469
return mod->dev->period;
455470
}
456471

472+
#if defined(__ZEPHYR__) && defined(CONFIG_SOF_FULL_ZEPHYR_APPLICATION)
473+
#include <zephyr/syscalls/generic.h>
474+
#endif
475+
457476
#endif /* __SOF_AUDIO_MODULE_GENERIC__ */

src/include/sof/lib/fast-get.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
struct k_heap;
1414

15-
#if defined(__ZEPHYR__) && defined(CONFIG_SOF)
15+
#if defined(__ZEPHYR__) && defined(CONFIG_SOF_FULL_ZEPHYR_APPLICATION)
1616
#include <zephyr/toolchain.h>
1717

1818
__syscall const void *fast_get(struct k_heap *heap, const void * const dram_ptr, size_t size);

src/include/sof/schedule/dp_schedule.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,12 +103,18 @@ union scheduler_dp_thread_ipc_param {
103103
} pipeline_state;
104104
};
105105

106+
struct dp_heap_user {
107+
struct k_heap heap;
108+
unsigned int client_count; /* devices and buffers */
109+
// lock; /* protect the counter */
110+
};
111+
106112
#if CONFIG_ZEPHYR_DP_SCHEDULER
107-
int scheduler_dp_thread_ipc(struct processing_module *pmod, enum sof_ipc4_module_type cmd,
113+
int scheduler_dp_thread_ipc(struct processing_module *pmod, unsigned int cmd,
108114
union scheduler_dp_thread_ipc_param *param);
109115
#else
110116
static inline int scheduler_dp_thread_ipc(struct processing_module *pmod,
111-
enum sof_ipc4_module_type cmd,
117+
unsigned int cmd,
112118
union scheduler_dp_thread_ipc_param *param)
113119
{
114120
return 0;

src/ipc/ipc4/helper.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <sof/lib/memory.h>
2424
#include <sof/list.h>
2525
#include <sof/platform.h>
26+
#include <sof/schedule/dp_schedule.h>
2627
#include <sof/schedule/ll_schedule_domain.h>
2728
#include <rtos/symbol.h>
2829
#include <rtos/wait.h>
@@ -600,6 +601,14 @@ __cold int ipc_comp_connect(struct ipc *ipc, ipc_pipe_comp_connect *_connect)
600601
return IPC4_OUT_OF_MEMORY;
601602
}
602603

604+
#if CONFIG_ZEPHYR_DP_SCHEDULER
605+
if (dp_heap) {
606+
struct dp_heap_user *dp_user = container_of(dp_heap, struct dp_heap_user, heap);
607+
608+
dp_user->client_count++;
609+
}
610+
#endif
611+
603612
/*
604613
* set min_free_space and min_available in sink/src api of created buffer.
605614
* buffer is connected like:

0 commit comments

Comments
 (0)