Skip to content
Merged
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
1 change: 1 addition & 0 deletions src/include/sof/lib_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ struct lib_manager_module {
const struct sof_man_module_manifest *mod_manifest;
struct llext *llext; /* Zephyr loadable extension context */
struct llext_buf_loader *ebl; /* Zephyr loadable extension buffer loader */
unsigned int n_dependent; /* For auxiliary modules: number of dependents */
bool mapped;
struct lib_manager_segment_desc segment[LIB_MANAGER_N_SEGMENTS];
};
Expand Down
41 changes: 25 additions & 16 deletions src/library_manager/llext_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,8 @@ static int llext_manager_unload_module(struct lib_manager_module *mctx)
/* Writable data (.data, .bss, etc.) */
void __sparse_cache *va_base_data = (void __sparse_cache *)
mctx->segment[LIB_MANAGER_DATA].addr;
size_t data_size = mctx->segment[LIB_MANAGER_DATA].size;
size_t data_size = mctx->segment[LIB_MANAGER_DATA].size +
mctx->segment[LIB_MANAGER_BSS].size;
int err = 0, ret;

llext_manager_unmap_detached_sections(ldr, ext, LLEXT_MEM_TEXT,
Expand Down Expand Up @@ -443,6 +444,7 @@ static int llext_manager_mod_init(struct lib_manager_mod_ctx *ctx,
ctx->mod[n_mod].mapped = false;
ctx->mod[n_mod].llext = NULL;
ctx->mod[n_mod].ebl = NULL;
ctx->mod[n_mod].n_dependent = 0;
ctx->mod[n_mod++].start_idx = i;
}

Expand Down Expand Up @@ -588,10 +590,13 @@ static int llext_lib_find(const struct llext *llext, struct lib_manager_module *
return -ENOENT;
}

/* n can be -1 */
static void llext_manager_depend_unlink_rollback(struct lib_manager_module *dep_ctx[], int n)
{
for (; n >= 0; n--)
if (dep_ctx[n] && dep_ctx[n]->llext->use_count == 1)
if (!dep_ctx[n])
tr_err(&lib_manager_tr, "dependency %d NULL", n);
else if (!--dep_ctx[n]->n_dependent)
llext_manager_unload_module(dep_ctx[n]);
}

Expand Down Expand Up @@ -642,22 +647,13 @@ uintptr_t llext_manager_allocate_module(const struct comp_ipc_config *ipc_config
struct lib_manager_module *dep_ctx[LLEXT_MAX_DEPENDENCIES] = {};

for (i = 0; i < ARRAY_SIZE(mctx->llext->dependency); i++) {
struct lib_manager_module *dep;

/* Dependencies are filled from the beginning of the array upwards */
if (!mctx->llext->dependency[i])
break;

/*
* Protected by the IPC serialization, but maybe we should protect the
* use-count explicitly too. Currently the use-count is first incremented
* when an auxiliary library is loaded, it was then additionally incremented
* when the current dependent module was mapped. If it's higher than two,
* then some other modules also depend on it and have already mapped it.
*/
if (mctx->llext->dependency[i]->use_count > 2)
continue;

/* First user of this dependency, load it into SRAM */
ret = llext_lib_find(mctx->llext->dependency[i], &dep_ctx[i]);
ret = llext_lib_find(mctx->llext->dependency[i], &dep);
if (ret < 0) {
tr_err(&lib_manager_tr,
"Unmet dependency: cannot find dependency %u", i);
Expand All @@ -666,13 +662,26 @@ uintptr_t llext_manager_allocate_module(const struct comp_ipc_config *ipc_config

tr_dbg(&lib_manager_tr, "%s depending on %s index %u, %u users",
mctx->llext->name, mctx->llext->dependency[i]->name,
dep_ctx[i]->start_idx, mctx->llext->dependency[i]->use_count);
dep->start_idx, dep->n_dependent);

ret = llext_manager_load_module(dep_ctx[i]);
/*
* Protected by the IPC serialization, but maybe we should protect the
* dependent-count explicitly too. It is incremented when a new dependent
* is identified. If it's non-zero, then some other modules also depend
* on it and have already mapped it.
*/
if (dep->n_dependent++)
continue;

/* First user of this dependency, load it into SRAM */
ret = llext_manager_load_module(dep);
Copy link
Member

Choose a reason for hiding this comment

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

do we need to decrement n_dependent on loading failure ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

rrright, good catch! Updated.

if (ret < 0) {
dep->n_dependent--;
llext_manager_depend_unlink_rollback(dep_ctx, i - 1);
return 0;
}

dep_ctx[i] = dep;
}

/* Map executable code and data */
Expand Down
Loading