From 68a71101958ef48a955be6fb2a13b95255ca7633 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Fri, 27 Jan 2017 11:43:27 -0600 Subject: [PATCH] sched/modules: Add support for dependencies between modules. --- sched/Kconfig | 15 +++ sched/module/Make.defs | 10 +- sched/module/mod_bind.c | 22 ++-- sched/module/mod_depend.c | 200 ++++++++++++++++++++++++++++++++++++ sched/module/mod_insmod.c | 3 +- sched/module/mod_modsym.c | 1 + sched/module/mod_registry.c | 85 +++++++++++++-- sched/module/mod_rmmod.c | 16 +++ sched/module/mod_symbols.c | 116 +++++++++++++++++++-- sched/module/mod_symtab.c | 4 +- sched/module/module.h | 62 ++++++++++- 11 files changed, 496 insertions(+), 38 deletions(-) create mode 100644 sched/module/mod_depend.c diff --git a/sched/Kconfig b/sched/Kconfig index 9810d3ba62..50ba4f914e 100644 --- a/sched/Kconfig +++ b/sched/Kconfig @@ -1128,6 +1128,21 @@ menuconfig MODULE if MODULE +config MODULE_MAXDEPEND + int "Max dependencies" + default 2 + ---help--- + This setting controls the number of other modules that a new module + may depend on. That is, when a new module in inserted via 'insmod' + it may depend on symbols exported by other, already installed + modules. This is the maximum number of modules that export symbols + to the new module. This maximum is artificial; it is used in the + current design because it uses some very simple, pre-allocated data + structures. + + All dependencies logic my be eliminated by sett CONFIG_MODULE_MAXDEPEND + to zero. + config MODULE_ALIGN_LOG2 int "Log2 Section Alignment" default 2 diff --git a/sched/module/Make.defs b/sched/module/Make.defs index 9aaa1a7e16..03b363c685 100644 --- a/sched/module/Make.defs +++ b/sched/module/Make.defs @@ -37,13 +37,13 @@ ifeq ($(CONFIG_MODULE),y) # OS module interfaces -CSRCS += mod_insmod.c mod_rmmod.c +CSRCS += mod_insmod.c mod_rmmod.c mod_modsym.c mod_symtab.c mod_modhandle.c -# loadable module library +# Loadable module library -CSRCS += mod_bind.c mod_init.c mod_iobuffer.c mod_load.c mod_modhandle.c -CSRCS += mod_modsym.c mod_read.c mod_registry.c mod_sections.c mod_symbols.c -CSRCS += mod_symtab.c mod_uninit.c mod_unload.c mod_verify.c +CSRCS += mod_bind.c mod_depend.c mod_init.c mod_iobuffer.c mod_load.c +CSRCS += mod_read.c mod_registry.c mod_sections.c mod_symbols.c mod_uninit.c +CSRCS += mod_unload.c mod_verify.c # procfs support diff --git a/sched/module/mod_bind.c b/sched/module/mod_bind.c index da905444e9..905b22a64d 100644 --- a/sched/module/mod_bind.c +++ b/sched/module/mod_bind.c @@ -1,7 +1,7 @@ /**************************************************************************** * sched/module/mod_bind.c * - * Copyright (C) 2015 Gregory Nutt. All rights reserved. + * Copyright (C) 2015, 2017 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -98,7 +98,8 @@ static inline int mod_readrel(FAR struct mod_loadinfo_s *loadinfo, * ****************************************************************************/ -static int mod_relocate(FAR struct mod_loadinfo_s *loadinfo, int relidx) +static int mod_relocate(FAR struct module_s *modp, + FAR struct mod_loadinfo_s *loadinfo, int relidx) { FAR Elf32_Shdr *relsec = &loadinfo->shdr[relidx]; @@ -148,7 +149,7 @@ static int mod_relocate(FAR struct mod_loadinfo_s *loadinfo, int relidx) /* Get the value of the symbol (in sym.st_value) */ - ret = mod_symvalue(loadinfo, &sym); + ret = mod_symvalue(modp, loadinfo, &sym); if (ret < 0) { /* The special error -ESRCH is returned only in one condition: The @@ -199,7 +200,8 @@ static int mod_relocate(FAR struct mod_loadinfo_s *loadinfo, int relidx) return OK; } -static int mod_relocateadd(FAR struct mod_loadinfo_s *loadinfo, int relidx) +static int mod_relocateadd(FAR struct module_s *modp, + FAR struct mod_loadinfo_s *loadinfo, int relidx) { serr("ERROR: Not implemented\n"); return -ENOSYS; @@ -216,13 +218,17 @@ static int mod_relocateadd(FAR struct mod_loadinfo_s *loadinfo, int relidx) * Bind the imported symbol names in the loaded module described by * 'loadinfo' using the exported symbol values provided by mod_setsymtab(). * + * Input Parameters: + * modp - Module state information + * loadinfo - Load state information + * * Returned Value: * 0 (OK) is returned on success and a negated errno is returned on * failure. * ****************************************************************************/ -int mod_bind(FAR struct mod_loadinfo_s *loadinfo) +int mod_bind(FAR struct module_s *modp, FAR struct mod_loadinfo_s *loadinfo) { int ret; int i; @@ -258,7 +264,7 @@ int mod_bind(FAR struct mod_loadinfo_s *loadinfo) continue; } - /* Make sure that the section is allocated. We can't relocated + /* Make sure that the section is allocated. We can't relocate * sections that were not loaded into memory. */ @@ -271,11 +277,11 @@ int mod_bind(FAR struct mod_loadinfo_s *loadinfo) if (loadinfo->shdr[i].sh_type == SHT_REL) { - ret = mod_relocate(loadinfo, i); + ret = mod_relocate(modp, loadinfo, i); } else if (loadinfo->shdr[i].sh_type == SHT_RELA) { - ret = mod_relocateadd(loadinfo, i); + ret = mod_relocateadd(modp, loadinfo, i); } if (ret < 0) diff --git a/sched/module/mod_depend.c b/sched/module/mod_depend.c new file mode 100644 index 0000000000..3ead6d5d2e --- /dev/null +++ b/sched/module/mod_depend.c @@ -0,0 +1,200 @@ +/**************************************************************************** + * sched/module/mod_depend.c + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "module.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mod_depend + * + * Description: + * Set up module dependencies between the exporter and the importer of a + * symbol. The happens when the module is installed via insmod and a + * symbol is imported from another module. + * + * Returned Value: + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + * Assumptions: + * Caller holds the registry lock. + * + ****************************************************************************/ + +int mod_depend(FAR struct module_s *importer, FAR struct module_s *exporter) +{ +#if CONFIG_MODULE_MAXDEPEND > 0 + int freendx; + int i; + + DEBUGASSERT(importer != NULL && exporter != NULL); + + /* First checker if the exported is already in our list if dependencies. + * This would happen if we are importing multiple symbols from the same + * exporting module. In that case, the module would already be in the + * list of dependencies. + * + * The list dependency list is a a dumb, upacked array of pointers. This + * should not be too inefficient if the number of CONFIG_MODULE_MAXDEPEND + * is small. Otherwise, a more dynamic data structure would be in order. + */ + + for (i = 0, freendx = -1; i < CONFIG_MODULE_MAXDEPEND; i++) + { + FAR const struct module_s *modp; + + /* Check if this dependency slot is available. */ + + modp = importer->dependencies[i]; + if (modp == NULL) + { + /* Remember this slot for use the module is NOT already in the + * list of dependencies. + */ + + freendx = i; + } + else if (modp == exporter) + { + /* Yes, we are already importing symbols from this module. Nothing + * more needs to be done. + */ + + return OK; + } + } + + /* If we get here, then (1) this is a new exporting module that does not + * already appear in the list of dependencies, and (2) freendx is the + * index to the last free slot in the dependency list. If freendx is + * negative, then the dependency list is full. + */ + + if (freendx >= 0) + { + /* Increment the count of dependencies on the exporter module */ + + DEBUGASSERT(exporter->dependents < UINT8_MAX); + if (exporter->dependents >= UINT8_MAX) + { + return -ENOSPC; + } + + exporter->dependents++; + + /* And remember the exporter so that we can decrement the count of + * dependents if the importer is removed. + */ + + DEBUGASSERT(importer->dependencies[freendx] == NULL); + importer->dependencies[freendx] = exporter; + return OK; + } + + /* If we get there then the list of dependencies is full. */ + + DEBUGPANIC(); + return -ENFILE; + +#else + return OK; +#endif +} + +/**************************************************************************** + * Name: mod_undepend + * + * Description: + * Tear down module dependencies between the exporters and the importer of + * symbols. This happens when the module is removed via rmmod (and on + * error handling cases in insmod). + * + * Returned Value: + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + * Assumptions: + * Caller holds the registry lock. + * + ****************************************************************************/ + +int mod_undepend(FAR struct module_s *importer) +{ +#if CONFIG_MODULE_MAXDEPEND > 0 + FAR struct module_s *exporter; + int i; + + DEBUGASSERT(importer != NULL && importer->dependents == 0); + + /* Decrement the dependency count on each of exporters of symbols used by + * this importer module. This is an upacked array of pointers. This + * should not be too inefficient if the number of CONFIG_MODULE_MAXDEPEND + * is small. Otherwise, a more dynamic data structure would be in order. + */ + + for (i = 0; i < CONFIG_MODULE_MAXDEPEND; i++) + { + exporter = importer->dependencies[i]; + if (exporter != NULL) + { + DEBUGASSERT(exporter->dependents > 0); + if (exporter->dependents > 0) + { + exporter->dependents--; + } + + importer->dependencies[i] = NULL; + } + } +#endif + + return OK; +} diff --git a/sched/module/mod_insmod.c b/sched/module/mod_insmod.c index 9fe5e71e28..8eb60b34e5 100644 --- a/sched/module/mod_insmod.c +++ b/sched/module/mod_insmod.c @@ -244,7 +244,7 @@ FAR void *insmod(FAR const char *filename, FAR const char *modulename) /* Bind the program to the kernel symbol table */ - ret = mod_bind(&loadinfo); + ret = mod_bind(modp, &loadinfo); if (ret != 0) { sinfo("Failed to bind symbols program binary: %d\n", ret); @@ -286,6 +286,7 @@ FAR void *insmod(FAR const char *filename, FAR const char *modulename) errout_with_load: mod_unload(&loadinfo); + (void)mod_undepend(modp); errout_with_registry_entry: kmm_free(modp); errout_with_loadinfo: diff --git a/sched/module/mod_modsym.c b/sched/module/mod_modsym.c index fa27e21692..1f46dc9fd8 100644 --- a/sched/module/mod_modsym.c +++ b/sched/module/mod_modsym.c @@ -89,6 +89,7 @@ FAR const void *modsym(FAR void *handle, FAR const char *name) /* Verify that the module is in the registry */ + mod_registry_lock(); ret = mod_registry_verify(modp); if (ret < 0) { diff --git a/sched/module/mod_registry.c b/sched/module/mod_registry.c index 961addcca7..5d0c1477a9 100644 --- a/sched/module/mod_registry.c +++ b/sched/module/mod_registry.c @@ -48,11 +48,34 @@ #include "module.h" +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define NO_HOLDER ((pid_t)-1) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct mod_registrylock_s +{ + sem_t lock; /* The actual registry lock */ + pid_t holder; /* The PID of the current holder of the lock */ + int16_t count; /* The number of nested calls to mod_registry_lock */ +}; + /**************************************************************************** * Private Data ****************************************************************************/ -static sem_t g_mod_lock = SEM_INITIALIZER(1); +static struct mod_registrylock_s g_modlock = +{ + SEM_INITIALIZER(1), /* lock */ + 0, /* pid */ + 0 /* count */ +}; + static FAR struct module_s *g_mod_registry; /**************************************************************************** @@ -75,9 +98,36 @@ static FAR struct module_s *g_mod_registry; void mod_registry_lock(void) { - while (sem_post(&g_mod_lock) < 0) + pid_t me; + + /* Do we already hold the semaphore? */ + + me = getpid(); + if (me == g_modlock.holder) { - DEBUGASSERT(errno == EINTR); + /* Yes... just increment the count */ + + g_modlock.count++; + DEBUGASSERT(g_modlock.count > 0); + } + + /* Take the semaphore (perhaps waiting) */ + + else + { + while (sem_wait(&g_modlock.lock) != 0) + { + /* The only case that an error should occr here is if + * the wait was awakened by a signal. + */ + + ASSERT(get_errno() == EINTR); + } + + /* No we hold the semaphore */ + + g_modlock.holder = me; + g_modlock.count = 1; } } @@ -97,7 +147,25 @@ void mod_registry_lock(void) void mod_registry_unlock(void) { - sem_post(&g_mod_lock); + DEBUGASSERT(g_modlock.holder == getpid()); + + /* Is this our last count on the semaphore? */ + + if (g_modlock.count > 1) + { + /* No.. just decrement the count */ + + g_modlock.count--; + } + + /* Yes.. then we can really release the semaphore */ + + else + { + g_modlock.holder = NO_HOLDER; + g_modlock.count = 0; + sem_post(&g_modlock.lock); + } } /**************************************************************************** @@ -249,15 +317,12 @@ int mod_registry_verify(FAR struct module_s *modp) * function returns a non-zero value, the traversal will be terminated and * that non-zero value will be returned. * - * Assumptions: - * The caller does *NOT* hold the lock on the module registry. - * ****************************************************************************/ int mod_registry_foreach(mod_callback_t callback, FAR void *arg) { FAR struct module_s *modp; - int ret; + int ret = OK; /* Get exclusive access to the module registry */ @@ -272,10 +337,10 @@ int mod_registry_foreach(mod_callback_t callback, FAR void *arg) ret = callback(modp, arg); if (ret != 0) { - return ret; + break; } } mod_registry_unlock(); - return OK; + return ret; } \ No newline at end of file diff --git a/sched/module/mod_rmmod.c b/sched/module/mod_rmmod.c index 561e9c82f9..17408fd743 100644 --- a/sched/module/mod_rmmod.c +++ b/sched/module/mod_rmmod.c @@ -89,6 +89,17 @@ int rmmod(FAR void *handle) goto errout_with_lock; } +#if CONFIG_MODULE_MAXDEPEND > 0 + /* Refuse to remove any module that other modules may depend upon. */ + + if (modp->dependents > 0) + { + serr("ERROR: Module has dependents: %d\n", modp->dependents); + ret = -EBUSY; + goto errout_with_lock; + } +#endif + /* Is there an uninitializer? */ if (modp->modinfo.uninitializer != NULL) @@ -142,6 +153,11 @@ int rmmod(FAR void *handle) goto errout_with_lock; } +#if CONFIG_MODULE_MAXDEPEND > 0 + /* Eliminate any dependencies that this module has on other modules */ + + (void)mod_undepend(modp); +#endif mod_registry_unlock(); /* And free the registry entry */ diff --git a/sched/module/mod_symbols.c b/sched/module/mod_symbols.c index 3a42f314f3..684db41238 100644 --- a/sched/module/mod_symbols.c +++ b/sched/module/mod_symbols.c @@ -1,7 +1,7 @@ /**************************************************************************** * sched/module/mod_symbols.c * - * Copyright (C) 2015 Gregory Nutt. All rights reserved. + * Copyright (C) 2015, 2017 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -54,10 +54,28 @@ * Pre-processor Definitions ****************************************************************************/ +/* Amount to reallocate buffer when buffer is full */ + #ifndef CONFIG_MODULE_BUFFERINCR # define CONFIG_MODULE_BUFFERINCR 32 #endif +/* Return values search for exported modules */ + +#define SYM_NOT_FOUND 0 +#define SYM_FOUND 1 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct mod_exportinfo_s +{ + FAR const char *name; /* Symbol name to find */ + FAR struct module_s *modp; /* The module that needs the symbol */ + FAR const struct symtab_s *symbol; /* Symbol info returned (if found) */ +}; + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -155,6 +173,56 @@ static int mod_symname(FAR struct mod_loadinfo_s *loadinfo, return OK; } +/**************************************************************************** + * Name: mod_symcallback + * + * Description: + * mod_registry_foreach() callback function. Test if the provided module, + * modp, exports the symbol of interest. If so, return that symbol value + * and setup the module dependency relationship. + * + * Returned Value: + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ****************************************************************************/ + +static int mod_symcallback(FAR struct module_s *modp, FAR void *arg) +{ + FAR struct mod_exportinfo_s *exportinfo = (FAR struct mod_exportinfo_s *)arg; + int ret; + + /* Check if this module exports a symbol of that name */ + +#ifdef CONFIG_SYMTAB_ORDEREDBYNAME + exportinfo->symbol = symtab_findorderedbyname(modp->modinfo.exports, + exportinfo->name, + modp->modinfo.nexports); +#else + exportinfo->symbol = symtab_findbyname(modp->modinfo.exports, + exportinfo->name, + modp->modinfo.nexports); +#endif + + if (exportinfo->symbol != NULL) + { + /* Yes.. save the dependency relationship and return SYM_FOUND to + * stop the traversal. + */ + + ret = mod_depend(exportinfo->modp, modp); + if (ret < 0) + { + serr("ERROR: mod_depend failed: %d\n", ret); + return ret; + } + + return SYM_FOUND; + } + + return SYM_NOT_FOUND; +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -246,6 +314,7 @@ int mod_readsym(FAR struct mod_loadinfo_s *loadinfo, int index, * in the st_value field of the symbol table entry. * * Input Parameters: + * modp - Module state information * loadinfo - Load state information * sym - Symbol table entry (value might be undefined) * @@ -261,9 +330,11 @@ int mod_readsym(FAR struct mod_loadinfo_s *loadinfo, int index, * ****************************************************************************/ -int mod_symvalue(FAR struct mod_loadinfo_s *loadinfo, FAR Elf32_Sym *sym) +int mod_symvalue(FAR struct module_s *modp, + FAR struct mod_loadinfo_s *loadinfo, FAR Elf32_Sym *sym) { FAR const struct symtab_s *symbol; + struct mod_exportinfo_s exportinfo; uintptr_t secbase; int ret; @@ -302,18 +373,43 @@ int mod_symvalue(FAR struct mod_loadinfo_s *loadinfo, FAR Elf32_Sym *sym) return ret; } - /* Check if the base code exports a symbol of this name */ + /* First check if the symbol is exported by an installed module. + * Newest modules are installed at the head of the list. Therefore, + * if the symbol is exported by numerous modules, then the most + * recently installed will take precedence. + */ + exportinfo.name = (FAR const char *)loadinfo->iobuffer; + exportinfo.modp = modp; + exportinfo.symbol = NULL; + + ret = mod_registry_foreach(mod_symcallback, (FAR void *)&exportinfo); + if (ret < 0) + { + serr("ERROR: mod_symcallback failed: \n", ret); + return ret; + } + + symbol = exportinfo.symbol; + + /* If the symbol is not exported by any module, then check if the + * base code exports a symbol of this name. + */ + + if (symbol == NULL) + { #ifdef CONFIG_SYMTAB_ORDEREDBYNAME - symbol = symtab_findorderedbyname(g_mod_symtab, - (FAR char *)loadinfo->iobuffer, - g_mod_nsymbols); + symbol = symtab_findorderedbyname(g_mod_symtab, exportinfo.name, + g_mod_nsymbols); #else - symbol = symtab_findbyname(g_mod_symtab, - (FAR char *)loadinfo->iobuffer, - g_mod_nsymbols); + symbol = symtab_findbyname(g_mod_symtab, exportinfo.name, + g_mod_nsymbols); #endif - if (!symbol) + } + + /* Was the symbol found from any exporter? */ + + if (symbol == NULL) { serr("ERROR: SHN_UNDEF: Exported symbol \"%s\" not found\n", loadinfo->iobuffer); diff --git a/sched/module/mod_symtab.c b/sched/module/mod_symtab.c index 0c0648f294..00df3dc967 100644 --- a/sched/module/mod_symtab.c +++ b/sched/module/mod_symtab.c @@ -81,7 +81,7 @@ void mod_getsymtab(FAR const struct symtab_s **symtab, FAR int *nsymbols) mod_registry_lock(); *symtab = g_mod_symtab; *nsymbols = g_mod_nsymbols; - mod_registry_lock(); + mod_registry_unlock(); } /**************************************************************************** @@ -106,5 +106,5 @@ void mod_setsymtab(FAR const struct symtab_s *symtab, int nsymbols) mod_registry_lock(); g_mod_symtab = symtab; g_mod_nsymbols = nsymbols; - mod_registry_lock(); + mod_registry_unlock(); } diff --git a/sched/module/module.h b/sched/module/module.h index 344acbf43e..ce06b12252 100644 --- a/sched/module/module.h +++ b/sched/module/module.h @@ -68,6 +68,16 @@ struct module_s size_t textsize; /* Size of the kernel .text memory allocation */ size_t datasize; /* Size of the kernel .bss/.data memory allocation */ #endif + +#if CONFIG_MODULE_MAXDEPEND > 0 + uint8_t dependents; /* Number of modules that depend on this module */ + + /* This is an upacked array of pointers to other modules that this module + * depends upon. + */ + + FAR struct module_s *dependencies[CONFIG_MODULE_MAXDEPEND]; +#endif }; /* This struct provides a description of the currently loaded instantiation @@ -168,7 +178,7 @@ int mod_load(FAR struct mod_loadinfo_s *loadinfo); * ****************************************************************************/ -int mod_bind(FAR struct mod_loadinfo_s *loadinfo); +int mod_bind(FAR struct module_s *modp, FAR struct mod_loadinfo_s *loadinfo); /**************************************************************************** * Name: mod_unload @@ -178,6 +188,10 @@ int mod_bind(FAR struct mod_loadinfo_s *loadinfo); * the actions of mod_load. It is called only under certain error * conditions after the module has been loaded but not yet started. * + * Input Parameters: + * modp - Module state information + * loadinfo - Load state information + * * Returned Value: * 0 (OK) is returned on success and a negated errno is returned on * failure. @@ -186,6 +200,48 @@ int mod_bind(FAR struct mod_loadinfo_s *loadinfo); int mod_unload(struct mod_loadinfo_s *loadinfo); +/**************************************************************************** + * Name: mod_depend + * + * Description: + * Set up module dependencies between the exporter and the importer of a + * symbol. The happens when the module is installed via insmod and a + * symbol is imported from another module. + * + * Returned Value: + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + * Assumptions: + * Caller holds the registry lock. + * + ****************************************************************************/ + +#if CONFIG_MODULE_MAXDEPEND > 0 +int mod_depend(FAR struct module_s *importer, FAR struct module_s *exporter); +#endif + +/**************************************************************************** + * Name: mod_undepend + * + * Description: + * Tear down module dependencies between the exporters and the importer of + * symbols. This happens when the module is removed via rmmod (and on + * error handling cases in insmod). + * + * Returned Value: + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + * Assumptions: + * Caller holds the registry lock. + * + ****************************************************************************/ + +#if CONFIG_MODULE_MAXDEPEND > 0 +int mod_undepend(FAR struct module_s *importer); +#endif + /**************************************************************************** * Name: mod_verifyheader * @@ -292,6 +348,7 @@ int mod_readsym(FAR struct mod_loadinfo_s *loadinfo, int index, * in the st_value field of the symbol table entry. * * Input Parameters: + * modp - Module state information * loadinfo - Load state information * sym - Symbol table entry (value might be undefined) * @@ -307,7 +364,8 @@ int mod_readsym(FAR struct mod_loadinfo_s *loadinfo, int index, * ****************************************************************************/ -int mod_symvalue(FAR struct mod_loadinfo_s *loadinfo, FAR Elf32_Sym *sym); +int mod_symvalue(FAR struct module_s *modp, + FAR struct mod_loadinfo_s *loadinfo, FAR Elf32_Sym *sym); /**************************************************************************** * Name: mod_freebuffers