Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions posix/include/rtos/alloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,56 @@ void sof_heap_free(struct k_heap *heap, void *addr);
struct k_heap *sof_sys_heap_get(void);
struct k_heap *sof_sys_user_heap_get(void);

/* Posix version of struct mod_alloc_ctx without vregion support */
struct vregion;

struct mod_alloc_ctx {
struct k_heap *heap;
struct vregion *vreg;
};

/**
* Allocate memory from a mod_alloc_ctx context.
* Dummy version, only heap allocation is supported
*/
static inline void *sof_ctx_alloc(struct mod_alloc_ctx *ctx, uint32_t flags,
size_t size, size_t alignment)
{
return sof_heap_alloc(ctx ? ctx->heap : NULL, flags, size, alignment);
}

/**
* Allocate zero-initialized memory from a mod_alloc_ctx context.
* @param ctx Allocation context.
* @param flags Allocation flags (SOF_MEM_FLAG_*).
* @param size Size in bytes.
* @param alignment Required alignment in bytes.
* @return Pointer to allocated memory or NULL on failure.
*/
static inline void *sof_ctx_zalloc(struct mod_alloc_ctx *ctx, uint32_t flags,
size_t size, size_t alignment)
{
void *ptr = sof_ctx_alloc(ctx, flags, size, alignment);

if (ptr)
memset(ptr, 0, size);

return ptr;
}

/**
* Free memory allocated from a mod_alloc_ctx context.
* @param ctx Allocation context.
* @param ptr Pointer to free.
*/
static inline void sof_ctx_free(struct mod_alloc_ctx *ctx, void *ptr)
{
if (!ptr)
return;

sof_heap_free(ctx ? ctx->heap : NULL, ptr);
}

/**
* Calculates length of the null-terminated string.
* @param s String.
Expand Down
1 change: 0 additions & 1 deletion src/audio/buffers/comp_buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
#include <rtos/alloc.h>
#include <rtos/cache.h>
#include <sof/lib/vregion.h>
#include <sof/ctx_alloc.h>
#include <sof/list.h>
#include <sof/schedule/dp_schedule.h>
#include <rtos/spinlock.h>
Expand Down
1 change: 0 additions & 1 deletion src/audio/buffers/ring_buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
#include <sof/trace/trace.h>
#include <sof/lib/uuid.h>
#include <sof/lib/vregion.h>
#include <sof/ctx_alloc.h>

#include <sof/audio/module_adapter/module/generic.h>
#include <sof/audio/ring_buffer.h>
Expand Down
6 changes: 3 additions & 3 deletions src/audio/module_adapter/module/generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
#include <sof/audio/data_blob.h>
#include <sof/lib/fast-get.h>
#include <sof/lib/vregion.h>
#include <sof/ctx_alloc.h>
#include <sof/schedule/dp_schedule.h>
#if CONFIG_IPC_MAJOR_4
#include <ipc4/header.h>
Expand All @@ -29,8 +28,9 @@
/* The __ZEPHYR__ condition is to keep cmocka tests working */
#if CONFIG_MODULE_MEMORY_API_DEBUG && defined(__ZEPHYR__)
#define MEM_API_CHECK_THREAD(res) do { \
if ((res)->rsrc_mngr != k_current_get()) \
LOG_WRN("mngr %p != cur %p", (res)->rsrc_mngr, k_current_get()); \
k_tid_t tid = k_current_get(); \
if ((res)->rsrc_mngr != tid && (res)->dp_thread != tid) \
LOG_WRN("cur %p != mngr %p or dp %p", tid, (res)->rsrc_mngr, (res)->dp_thread); \
} while (0)
#else
#define MEM_API_CHECK_THREAD(res)
Expand Down
171 changes: 116 additions & 55 deletions src/audio/module_adapter/module_adapter.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,23 +59,37 @@ struct comp_dev *module_adapter_new(const struct comp_driver *drv,
#endif

static struct vregion *module_adapter_dp_heap_new(const struct comp_ipc_config *config,
const struct module_ext_init_data *ext_init,
size_t *heap_size)
{
/* src-lite with 8 channels has been seen allocating 14k in one go */
/* FIXME: the size will be derived from configuration */
const size_t buf_size = 28 * 1024;
size_t buf_size = CONFIG_SOF_USERSPACE_DP_DEFAULT_HEAP_SIZE;

/*
* A 1-to-1 replacement of the original heap implementation would be to
* have "lifetime size" equal to 0. But (1) this is invalid for
* vregion_create() and (2) we gradually move objects, that are simple
* to move to the lifetime buffer. Make it 4k for the beginning.
*/
return vregion_create(4096, buf_size - 4096);
#if CONFIG_IPC_MAJOR_4
if (config->ipc_extended_init && ext_init && ext_init->dp_data &&
ext_init->dp_data->heap_bytes > 0) {
if (ext_init->dp_data->heap_bytes > 64*1024*1024) {
LOG_ERR("Bad heap size %u bytes for %#x",
ext_init->dp_data->heap_bytes, config->id);
return NULL;
}

buf_size = ext_init->dp_data->heap_bytes;

LOG_INF("%zu byte heap size requested in IPC for %#x", buf_size, config->id);
}
#endif

*heap_size = buf_size;

return vregion_create(buf_size);
}

static struct processing_module *module_adapter_mem_alloc(const struct comp_driver *drv,
const struct comp_ipc_config *config)
static
struct processing_module *module_adapter_mem_alloc(const struct comp_driver *drv,
const struct comp_ipc_config *config,
const struct module_ext_init_data *ext_init,
struct mod_alloc_ctx *ppl_alloc)
{
struct k_heap *mod_heap;
struct vregion *mod_vreg;
Expand All @@ -91,41 +105,58 @@ static struct processing_module *module_adapter_mem_alloc(const struct comp_driv
uint32_t flags = config->proc_domain == COMP_PROCESSING_DOMAIN_DP ?
SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT : SOF_MEM_FLAG_USER;
size_t heap_size;
bool use_ppl_alloc = ppl_alloc &&
config->proc_domain == COMP_PROCESSING_DOMAIN_LL;

if (config->proc_domain == COMP_PROCESSING_DOMAIN_DP && IS_ENABLED(CONFIG_USERSPACE) &&
!IS_ENABLED(CONFIG_SOF_USERSPACE_USE_DRIVER_HEAP)) {
mod_vreg = module_adapter_dp_heap_new(config, &heap_size);
if (config->proc_domain == COMP_PROCESSING_DOMAIN_DP && IS_ENABLED(CONFIG_SOF_VREGIONS) &&
IS_ENABLED(CONFIG_USERSPACE) && !IS_ENABLED(CONFIG_SOF_USERSPACE_USE_DRIVER_HEAP)) {
mod_vreg = module_adapter_dp_heap_new(config, ext_init, &heap_size);
if (!mod_vreg) {
comp_cl_err(drv, "Failed to allocate DP module heap / vregion");
return NULL;
}
mod_heap = NULL;
} else if (use_ppl_alloc) {
mod_vreg = ppl_alloc->vreg ? vregion_get(ppl_alloc->vreg) : NULL;
mod_heap = ppl_alloc->heap;
heap_size = 0;
} else {
mod_heap = drv->user_heap;
heap_size = 0;
mod_vreg = NULL;
}

if (!mod_vreg)
if (use_ppl_alloc) {
/* LL modules use the pipeline's alloc context */
mod = sof_ctx_alloc(ppl_alloc, flags, sizeof(*mod), 0);
} else if (!mod_vreg) {
Comment thread
jsarha marked this conversation as resolved.
mod = sof_heap_alloc(mod_heap, flags, sizeof(*mod), 0);
else if (flags & SOF_MEM_FLAG_COHERENT)
mod = vregion_alloc_coherent(mod_vreg, VREGION_MEM_TYPE_LIFETIME, sizeof(*mod));
else
mod = vregion_alloc(mod_vreg, VREGION_MEM_TYPE_LIFETIME, sizeof(*mod));
} else if (flags & SOF_MEM_FLAG_COHERENT) {
mod = vregion_alloc_coherent(mod_vreg, sizeof(*mod));
} else {
mod = vregion_alloc(mod_vreg, sizeof(*mod));
}

if (!mod) {
comp_cl_err(drv, "failed to allocate memory for module");
goto emod;
}

struct mod_alloc_ctx *alloc = rmalloc(flags, sizeof(*alloc));
struct mod_alloc_ctx *alloc;

if (!alloc)
goto ealloc;
if (use_ppl_alloc) {
/* LL modules share the pipeline's alloc context */
alloc = ppl_alloc;
} else {
alloc = rzalloc(flags, sizeof(*alloc));
if (!alloc)
goto ealloc;

alloc->heap = mod_heap;
alloc->vreg = mod_vreg;
}

memset(mod, 0, sizeof(*mod));
alloc->heap = mod_heap;
alloc->vreg = mod_vreg;
mod->priv.resources.alloc = alloc;
mod_resource_init(mod);

Expand All @@ -135,8 +166,10 @@ static struct processing_module *module_adapter_mem_alloc(const struct comp_driv
* then it can be cached. Effectively it can be only cached in
* single-core configurations.
*/
if (mod_vreg)
dev = vregion_alloc_coherent(mod_vreg, VREGION_MEM_TYPE_LIFETIME, sizeof(*dev));
if (use_ppl_alloc)
dev = sof_ctx_alloc(ppl_alloc, SOF_MEM_FLAG_COHERENT, sizeof(*dev), 0);
else if (mod_vreg)
dev = vregion_alloc_coherent(mod_vreg, sizeof(*dev));
else
dev = sof_heap_alloc(mod_heap, SOF_MEM_FLAG_COHERENT, sizeof(*dev), 0);

Expand All @@ -154,40 +187,47 @@ static struct processing_module *module_adapter_mem_alloc(const struct comp_driv
return mod;

edev:
rfree(alloc);
if (!use_ppl_alloc)
rfree(alloc);
ealloc:
if (mod_vreg)
if (use_ppl_alloc)
sof_ctx_free(ppl_alloc, mod);
else if (mod_vreg)
vregion_free(mod_vreg, mod);
else
sof_heap_free(mod_heap, mod);
emod:
vregion_put(mod_vreg);
if (use_ppl_alloc)
vregion_put(ppl_alloc->vreg);
else
vregion_put(mod_vreg);

return NULL;
}

static void module_adapter_mem_free(struct processing_module *mod)
{
struct mod_alloc_ctx *alloc = mod->priv.resources.alloc;
struct k_heap *mod_heap = alloc->heap;
bool ppl_alloc = mod->dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_LL &&
mod->dev->pipeline && mod->dev->pipeline->alloc == alloc;

/*
* In principle it shouldn't even be needed to free individual objects
* on the module heap since we're freeing the heap itself too
*/
#if CONFIG_IPC_MAJOR_4
sof_heap_free(mod_heap, mod->priv.cfg.input_pins);
sof_heap_free(alloc->heap, mod->priv.cfg.input_pins);
#endif
if (alloc->vreg) {
struct vregion *mod_vreg = alloc->vreg;

vregion_free(mod_vreg, mod->dev);
vregion_free(mod_vreg, mod);
if (!vregion_put(mod_vreg))
sof_ctx_free(alloc, mod->dev);
sof_ctx_free(alloc, mod);

if (ppl_alloc) {
/* alloc belongs to pipeline, just release vregion reference */
vregion_put(alloc->vreg);
} else if (alloc->vreg) {
if (!vregion_put(alloc->vreg))
rfree(alloc);
} else {
sof_heap_free(mod_heap, mod->dev);
sof_heap_free(mod_heap, mod);
rfree(alloc);
}
}
Expand Down Expand Up @@ -231,8 +271,32 @@ struct comp_dev *module_adapter_new_ext(const struct comp_driver *drv,
return NULL;
}
#endif
const struct module_ext_init_data *ext_init =
#if CONFIG_IPC_MAJOR_4
&ext_data;
#else
NULL;
#endif

struct processing_module *mod = module_adapter_mem_alloc(drv, config);
#if CONFIG_IPC_MAJOR_4
struct ipc_comp_dev *ipc_pipe;
struct ipc *ipc = ipc_get();
struct mod_alloc_ctx *ppl_alloc = NULL;

/* resolve the pipeline pointer early to pass its alloc to mem_alloc */
ipc_pipe = ipc_get_comp_by_ppl_id(ipc, COMP_TYPE_PIPELINE, config->pipeline_id,
IPC_COMP_IGNORE_REMOTE);
if (ipc_pipe && ipc_pipe->pipeline)
ppl_alloc = ipc_pipe->pipeline->alloc;
#endif

struct processing_module *mod = module_adapter_mem_alloc(drv, config, ext_init,
#if CONFIG_IPC_MAJOR_4
ppl_alloc
#else
NULL
#endif
);

if (!mod)
return NULL;
Expand All @@ -245,6 +309,18 @@ struct comp_dev *module_adapter_new_ext(const struct comp_driver *drv,

struct comp_dev *dev = mod->dev;

dst = &mod->priv.cfg;
/*
* NOTE: dst->ext_data points to stack variable and contains
* pointers to IPC payload mailbox, so its only valid in
* functions that are called from this function. This is
* why the pointer is set to NULL before this function
* exits.
*/
#if CONFIG_IPC_MAJOR_4
dst->ext_data = &ext_data;
#endif

#if CONFIG_ZEPHYR_DP_SCHEDULER
/* create a task for DP processing */
if (config->proc_domain == COMP_PROCESSING_DOMAIN_DP) {
Expand All @@ -257,16 +333,6 @@ struct comp_dev *module_adapter_new_ext(const struct comp_driver *drv,
}
#endif /* CONFIG_ZEPHYR_DP_SCHEDULER */

dst = &mod->priv.cfg;
/*
* NOTE: dst->ext_data points to stack variable and contains
* pointers to IPC payload mailbox, so its only valid in
* functions that called from this function. This why
* the pointer is set NULL before this function exits.
*/
#if CONFIG_IPC_MAJOR_4
dst->ext_data = &ext_data;
#endif
ret = module_adapter_init_data(dev, dst, config, &spec);
if (ret) {
comp_err(dev, "%d: module init data failed",
Expand All @@ -289,12 +355,7 @@ struct comp_dev *module_adapter_new_ext(const struct comp_driver *drv,
goto err;

#if CONFIG_IPC_MAJOR_4
struct ipc_comp_dev *ipc_pipe;
struct ipc *ipc = ipc_get();

/* set the pipeline pointer if ipc_pipe is valid */
ipc_pipe = ipc_get_comp_by_ppl_id(ipc, COMP_TYPE_PIPELINE, config->pipeline_id,
IPC_COMP_IGNORE_REMOTE);
if (ipc_pipe) {
dev->pipeline = ipc_pipe->pipeline;

Expand Down
5 changes: 2 additions & 3 deletions src/audio/module_adapter/module_adapter_ipc4.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,9 @@ int module_ext_init_decode(const struct comp_driver *drv, struct module_ext_init
}
ext_data->dp_data = dp_data;
comp_cl_info(drv,
"init_ext_obj_dp_data domain %u stack %u interim %u lifetime %u shared %u",
"init_ext_obj_dp_data domain %u stack %u heap %u",
dp_data->domain_id, dp_data->stack_bytes,
dp_data->interim_heap_bytes, dp_data->lifetime_heap_bytes,
dp_data->shared_bytes);
dp_data->heap_bytes);
break;
}
case IPC4_MOD_INIT_DATA_ID_MODULE_DATA:
Expand Down
Loading