Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 8 additions & 0 deletions posix/include/rtos/alloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,14 @@ void rfree(void *ptr);
*/
void *rzalloc_core_sys(int core, size_t bytes);

struct k_heap;
static inline void k_heap_init(struct k_heap *heap, void *mem, size_t bytes)
{
}
void *sof_heap_alloc(struct k_heap *heap, uint32_t flags, size_t bytes,
size_t alignment);
void sof_heap_free(struct k_heap *heap, void *addr);

/**
* Calculates length of the null-terminated string.
* @param s String.
Expand Down
4 changes: 4 additions & 0 deletions posix/include/rtos/kernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,8 @@ static inline void k_usleep(int32_t us)
wait_delay_us(us);
}

struct k_heap {
int unused;
};

#endif /* __POSIX_RTOS_KERNEL_H__ */
27 changes: 15 additions & 12 deletions src/audio/module_adapter/module/generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,17 +137,20 @@ struct container_chunk {
static struct module_resource *container_get(struct processing_module *mod)
{
struct module_resources *res = &mod->priv.resources;
struct k_heap *mod_heap = res->heap;
struct module_resource *container;

if (list_is_empty(&res->free_cont_list)) {
struct container_chunk *chunk = rzalloc(SOF_MEM_FLAG_USER, sizeof(*chunk));
struct container_chunk *chunk = sof_heap_alloc(mod_heap, 0, sizeof(*chunk), 0);
int i;

if (!chunk) {
comp_err(mod->dev, "allocating more containers failed");
return NULL;
}

memset(chunk, 0, sizeof(*chunk));

list_item_append(&chunk->chunk_list, &res->cont_chunk_list);
for (i = 0; i < ARRAY_SIZE(chunk->containers); i++)
list_item_append(&chunk->containers[i].list, &res->free_cont_list);
Expand All @@ -167,7 +170,7 @@ static void container_put(struct processing_module *mod, struct module_resource

/**
* Allocates aligned buffer memory block for module.
* @param mod Pointer to the module this memory block is allocatd for.
* @param mod Pointer to the module this memory block is allocated for.
* @param bytes Size in bytes.
* @param alignment Alignment in bytes.
* @return Pointer to the allocated memory or NULL if failed.
Expand Down Expand Up @@ -218,15 +221,16 @@ void *mod_balloc_align(struct processing_module *mod, size_t size, size_t alignm
EXPORT_SYMBOL(mod_balloc_align);

/**
* Allocates aligned memory block for module.
* @param mod Pointer to the module this memory block is allocatd for.
* Allocates aligned memory block with flags for module.
* @param mod Pointer to the module this memory block is allocated for.
* @param flags Allocator flags.
* @param bytes Size in bytes.
* @param alignment Alignment in bytes.
* @return Pointer to the allocated memory or NULL if failed.
*
* The allocated memory is automatically freed when the module is unloaded.
*/
void *mod_alloc_align(struct processing_module *mod, size_t size, size_t alignment)
void *mod_alloc_ext(struct processing_module *mod, uint32_t flags, size_t size, size_t alignment)
{
struct module_resources *res = &mod->priv.resources;
struct module_resource *container;
Expand All @@ -245,8 +249,7 @@ void *mod_alloc_align(struct processing_module *mod, size_t size, size_t alignme
}

/* Allocate memory for module */
ptr = rmalloc_align(SOF_MEM_FLAG_USER, size, alignment);

ptr = sof_heap_alloc(res->heap, flags, size, alignment);
if (!ptr) {
comp_err(mod->dev, "Failed to alloc %zu bytes %zu alignment for comp %#x.",
size, alignment, dev_comp_id(mod->dev));
Expand All @@ -265,7 +268,7 @@ void *mod_alloc_align(struct processing_module *mod, size_t size, size_t alignme

return ptr;
}
EXPORT_SYMBOL(mod_alloc_align);
EXPORT_SYMBOL(mod_alloc_ext);

/**
* Creates a blob handler and releases it when the module is unloaded
Expand All @@ -275,8 +278,7 @@ EXPORT_SYMBOL(mod_alloc_align);
* Like comp_data_blob_handler_new() but the handler is automatically freed.
*/
#if CONFIG_COMP_BLOB
struct comp_data_blob_handler *
mod_data_blob_handler_new(struct processing_module *mod)
struct comp_data_blob_handler *mod_data_blob_handler_new(struct processing_module *mod)
{
struct module_resources *res = &mod->priv.resources;
struct comp_data_blob_handler *bhp;
Expand Down Expand Up @@ -346,7 +348,7 @@ static int free_contents(struct processing_module *mod, struct module_resource *

switch (container->type) {
case MOD_RES_HEAP:
rfree(container->ptr);
sof_heap_free(res->heap, container->ptr);
res->heap_usage -= container->size;
return 0;
#if CONFIG_COMP_BLOB
Expand Down Expand Up @@ -587,6 +589,7 @@ int module_reset(struct processing_module *mod)
void mod_free_all(struct processing_module *mod)
{
struct module_resources *res = &mod->priv.resources;
struct k_heap *mod_heap = res->heap;
struct list_item *list;
struct list_item *_list;

Expand All @@ -612,7 +615,7 @@ void mod_free_all(struct processing_module *mod)
container_of(list, struct container_chunk, chunk_list);

list_item_del(&chunk->chunk_list);
rfree(chunk);
sof_heap_free(mod_heap, chunk);
}

/* Make sure resource lists and accounting are reset */
Expand Down
198 changes: 157 additions & 41 deletions src/audio/module_adapter/module_adapter.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <sof/platform.h>
#include <sof/ut.h>
#include <rtos/interrupt.h>
#include <rtos/kernel.h>
#include <rtos/symbol.h>
#include <limits.h>
#include <stdint.h>
Expand All @@ -44,6 +45,148 @@ struct comp_dev *module_adapter_new(const struct comp_driver *drv,
return module_adapter_new_ext(drv, config, spec, NULL);
}

#if CONFIG_SOF_USERSPACE_USE_DRIVER_HEAP
static struct processing_module *module_adapter_mem_alloc(const struct comp_driver *drv,
const struct comp_ipc_config *config)
{
struct comp_dev *dev = comp_alloc(drv, sizeof(*dev));

if (!dev) {
comp_cl_err(drv, "failed to allocate memory for comp_dev");
return NULL;
}

/* allocate module information.
* for DP shared modules this struct must be accessible from all cores
* Unfortunately at this point there's no information of components the module
* will be bound to. So we need to allocate shared memory for each DP module
* To be removed when pipeline 2.0 is ready
*/
int flags = config->proc_domain == COMP_PROCESSING_DOMAIN_DP ?
SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT : SOF_MEM_FLAG_USER;

struct processing_module *mod = module_driver_heap_rzalloc(drv->user_heap, flags,
sizeof(*mod));

if (!mod) {
comp_err(dev, "failed to allocate memory for module");
goto err;
}

mod->dev = dev;

return mod;

err:
module_driver_heap_free(drv->user_heap, dev);

return NULL;
}

static void module_adapter_mem_free(struct processing_module *mod)
{
const struct comp_driver *drv = mod->dev->drv;

#if CONFIG_IPC_MAJOR_4
module_driver_heap_free(drv->user_heap, mod->priv.cfg.input_pins);
#endif
module_driver_heap_free(drv->user_heap, mod->dev);
module_driver_heap_free(drv->user_heap, mod);
}
#else

#if CONFIG_MM_DRV
#define PAGE_SZ CONFIG_MM_DRV_PAGE_SIZE
#else
#include <platform/platform.h>
#define PAGE_SZ HOST_PAGE_SIZE
#endif
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This bit looks ugly in middle of module_adapter.c How about set HOST_PAGE_SIZE to CONFIG_MM_DRV_PAGE_SIZE if it is used, remove this bit and use HOST_PAGE_SIZE?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kv2019i HOST_PAGE_SIZE is host's page size, we should use DSP's page size - as long as available. And HOST_PAGE_SIZE is always defined, so I wouldn't redefine it.


static struct processing_module *module_adapter_mem_alloc(const struct comp_driver *drv,
const struct comp_ipc_config *config)
{
uint8_t *mod_heap_mem;
struct k_heap *mod_heap;
int flags;

if (config->proc_domain == COMP_PROCESSING_DOMAIN_DP) {
/* src-lite with 8 channels has been seen allocating 14k in one go */
/* FIXME: the size will be derived from configuration */
const size_t heap_size = 20 * 1024;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apparently this value is meant to be passed via IPC and come from topology. Until that’s implemented, it would make more sense to move it to configuration rather than hardcoding it.


/* Keep uncached to match the default SOF heap! */
mod_heap_mem = rballoc_align(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"wow... heap on heap... I guess, why not" :)

heap_size, PAGE_SZ);
if (!mod_heap_mem)
return NULL;

const size_t heap_prefix_size = ALIGN_UP(sizeof(*mod_heap), 8);
void *mod_heap_buf = mod_heap_mem + heap_prefix_size;

mod_heap = (struct k_heap *)mod_heap_mem;
k_heap_init(mod_heap, mod_heap_buf, heap_size - heap_prefix_size);

flags = SOF_MEM_FLAG_COHERENT;
} else {
mod_heap_mem = NULL;
mod_heap = NULL;

flags = 0;
}

struct processing_module *mod = sof_heap_alloc(mod_heap, flags, sizeof(*mod), 0);

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

memset(mod, 0, sizeof(*mod));
mod->priv.resources.heap = mod_heap;
mod->priv.resources.heap_mem = mod_heap_mem;

/*
* comp_alloc() always allocated dev uncached. Would be difficult to optimize. Only
* if the whole currently active topology is running on the primary core, then it
* can be cached. Effectively it can be only cached in single-core configurations.
*/
struct comp_dev *dev = sof_heap_alloc(mod_heap, SOF_MEM_FLAG_COHERENT, sizeof(*dev), 0);

if (!dev) {
comp_cl_err(drv, "failed to allocate memory for comp_dev");
goto err;
}

memset(dev, 0, sizeof(*dev));
comp_init(drv, dev, sizeof(*dev));
dev->ipc_config = *config;

mod->dev = dev;

return mod;

err:
sof_heap_free(mod_heap, mod);
emod:
rfree(mod_heap_mem);

return NULL;
}

static void module_adapter_mem_free(struct processing_module *mod)
{
struct k_heap *mod_heap = mod->priv.resources.heap;
void *mem = mod->priv.resources.heap_mem;

#if CONFIG_IPC_MAJOR_4
sof_heap_free(mod_heap, mod->priv.cfg.input_pins);
#endif
sof_heap_free(mod_heap, mod->dev);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we assume mod can be null and that's why it's checked earlier, then this line should also be inside that if to avoid a potential null pointer dereference.

sof_heap_free(mod_heap, mod);
rfree(mem);
}
#endif
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After this much code, it's good to add a comment explaining what this block depends on, especially since there are more #ifdefs inside.
#endif /* CONFIG_SOF_USERSPACE_USE_DRIVER_HEAP */


/*
* \brief Create a module adapter component.
* \param[in] drv - component driver pointer.
Expand All @@ -61,8 +204,6 @@ struct comp_dev *module_adapter_new_ext(const struct comp_driver *drv,
void *mod_priv)
{
int ret;
struct comp_dev *dev;
struct processing_module *mod;
struct module_config *dst;
const struct module_interface *const interface = drv->adapter_ops;

Expand All @@ -74,32 +215,17 @@ struct comp_dev *module_adapter_new_ext(const struct comp_driver *drv,
return NULL;
}

dev = comp_alloc(drv, sizeof(*dev));
if (!dev) {
comp_cl_err(drv, "failed to allocate memory for comp_dev");
return NULL;
}
dev->ipc_config = *config;

/* allocate module information.
* for DP shared modules this struct must be accessible from all cores
* Unfortunately at this point there's no information of components the module
* will be bound to. So we need to allocate shared memory for each DP module
* To be removed when pipeline 2.0 is ready
*/
int flags = config->proc_domain == COMP_PROCESSING_DOMAIN_DP ?
SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT : SOF_MEM_FLAG_USER;
struct processing_module *mod = module_adapter_mem_alloc(drv, config);

mod = module_driver_heap_rzalloc(drv->user_heap, flags, sizeof(*mod));
if (!mod) {
comp_err(dev, "failed to allocate memory for module");
goto err;
}
if (!mod)
return NULL;

dst = &mod->priv.cfg;

module_set_private_data(mod, mod_priv);
mod->dev = dev;

struct comp_dev *dev = mod->dev;

dev->mod = mod;

list_init(&mod->raw_data_buffers_list);
Expand Down Expand Up @@ -178,13 +304,10 @@ struct comp_dev *module_adapter_new_ext(const struct comp_driver *drv,

comp_dbg(dev, "done");
return dev;

err:
#if CONFIG_IPC_MAJOR_4
if (mod)
rfree(mod->priv.cfg.input_pins);
#endif
rfree(mod);
rfree(dev);
module_adapter_mem_free(mod);

return NULL;
}
EXPORT_SYMBOL(module_adapter_new);
Expand Down Expand Up @@ -542,11 +665,9 @@ int module_adapter_params(struct comp_dev *dev, struct sof_ipc_stream_params *pa
#endif

/* allocate stream_params each time */
if (mod->stream_params)
rfree(mod->stream_params);
mod_free(mod, mod->stream_params);

mod->stream_params = rzalloc(SOF_MEM_FLAG_USER,
sizeof(*mod->stream_params) + params->ext_data_length);
mod->stream_params = mod_alloc(mod, sizeof(*mod->stream_params) + params->ext_data_length);
if (!mod->stream_params)
return -ENOMEM;

Expand Down Expand Up @@ -1248,7 +1369,7 @@ int module_adapter_reset(struct comp_dev *dev)
buffer_zero(buffer);
}

rfree(mod->stream_params);
mod_free(mod, mod->stream_params);
mod->stream_params = NULL;

comp_dbg(dev, "done");
Expand Down Expand Up @@ -1280,15 +1401,10 @@ void module_adapter_free(struct comp_dev *dev)
buffer_free(buffer);
}

mod_free(mod, mod->stream_params);
mod_free_all(mod);

#if CONFIG_IPC_MAJOR_4
rfree(mod->priv.cfg.input_pins);
#endif

rfree(mod->stream_params);
rfree(mod);
rfree(dev);
module_adapter_mem_free(mod);
}
EXPORT_SYMBOL(module_adapter_free);

Expand Down
Loading
Loading