diff options
-rw-r--r-- | include/asterisk/module.h | 53 | ||||
-rw-r--r-- | loader.c | 49 |
2 files changed, 68 insertions, 34 deletions
diff --git a/include/asterisk/module.h b/include/asterisk/module.h index f2065efc5..b00ec488d 100644 --- a/include/asterisk/module.h +++ b/include/asterisk/module.h @@ -41,7 +41,7 @@ extern "C" { #define STATIC_MODULE static /* symbols are static */ #endif -/* Every module should provide these functions */ +/*! \note Every module should provide these functions */ /*! * \brief Initialize the module. * @@ -285,8 +285,8 @@ struct localuser { AST_LIST_ENTRY(localuser) next; }; -/*! structure used for lock and refcount of module users. - * The mutex protects the usecnt field and whatever needs to be +/*! \brief structure used for lock and refcount of module users. + * \note The mutex protects the usecnt field and whatever needs to be * protected (typically, a list of struct localuser). * As a trick, if usecnt is initialized with -1, * ast_format_register will init the mutex for you. @@ -318,7 +318,7 @@ void ast_hangup_localusers(struct ast_module_lock *m); #define STANDARD_USECOUNT_DECL LOCAL_USER_DECL /* XXX lock remains unused */ -/*! run 'x' protected by lock, then call ast_update_use_count() */ +/*! \brief run 'x' protected by lock, then call ast_update_use_count() */ #define __MOD_PROTECT(x) do { \ ast_mutex_lock(&me.lock); \ x; \ @@ -381,8 +381,8 @@ void ast_hangup_localusers(struct ast_module_lock *m); */ #define STANDARD_USECOUNT(res) do { res = me.usecnt; } while (0) -/* - * XXX The following macro is deprecated, and only used by modules +/*! \brief Old usecount macro + * \note XXX The following macro is deprecated, and only used by modules * in codecs/ and a few other places which do their own manipulation * of the usecount variable. * Its use is supposed to be gradually phased away as those modules @@ -390,16 +390,18 @@ void ast_hangup_localusers(struct ast_module_lock *m); */ #define OLD_STANDARD_USECOUNT(res) do { res = localusecnt; } while (0) -/*! - * \brief The following is part of the new module management code. +/*! \page ModMngmnt The Asterisk Module management interface + * \par The following is part of the new module management code. * * All modules must implement the module API (load, unload...) * whose functions are exported through fields of a "struct module_symbol"; * * Modules exporting extra symbols (data or functions), should list - * them into an array of struct symbol_entry: + * them into an array of struct symbol_entry: \r * struct symbol_entry exported_symbols[] + * \r * of symbols, with a NULL name on the last entry + * * Functions should be added with MOD_FUNC(name), * data structures with MOD_DATA(_name). * The array in turn is referenced by struct module_symbol. @@ -407,6 +409,7 @@ void ast_hangup_localusers(struct ast_module_lock *m); * to a record containing all the methods. This is the API of the module, * and should be known to the module's clients as well. * + * \par Connections to symbols in other modules * Modules that require symbols supplied by other modules should * provide an array * struct symbol_entry required_symbols[] @@ -438,7 +441,7 @@ void ast_hangup_localusers(struct ast_module_lock *m); * .buf = buf, * } * - * NOTE: symbol names are 'global' in this module namespace, so it + * \note NOTE: symbol names are 'global' in this module namespace, so it * will be wiser to name exported symbols with a prefix indicating the module * supplying it, e.g. foo_f, foo_g, foo_buf. Internally to the module, * symbols are still static so they can keep short and meaningful names. @@ -451,6 +454,36 @@ void ast_hangup_localusers(struct ast_module_lock *m); * * Note that the loader requires that no fields of exported_symbols * are NULL, because that is used as an indication of the end of the array. + * + * \par Module states + * Modules can be in a number of different states, as below: + * - \b MS_FAILED attempt to load failed. This is final. + * - \b MS_NEW just added to the list, symbols unresolved. + * - \b MS_RESOLVED all symbols resolved, but supplier modules not active yet. + * - \b MS_CANLOAD all symbols resolved and suppliers are all active + * (or we are in a cyclic dependency and we are breaking a loop) + * - \b MS_ACTIVE load() returned successfully. + * + * + * \par Module Types + * For backward compatibility, we have 3 types of loadable modules: + * + * - \b MOD_0 these are the 'old style' modules, which export a number + * of callbacks, and their full interface, as globally visible + * symbols. The module needs to be loaded with RTLD_LAZY and + * RTLD_GLOBAL to make symbols visible to other modules, and + * to avoid load failures due to cross dependencies. + * + * - \b MOD_1 almost as above, but the generic callbacks are all into a + * a structure, mod_data. Same load requirements as above. + * + * - \b MOD_2 this is the 'new style' format for modules. The module must + * explictly declare which simbols are exported and which + * symbols from other modules are used, and the code in this + * loader will implement appropriate checks to load the modules + * in the correct order. Also this allows to load modules + * with RTLD_NOW and RTLD_LOCAL so there is no chance of run-time + * bugs due to unresolved symbols or name conflicts. */ struct symbol_entry { @@ -21,6 +21,7 @@ * \brief Module Loader * * \author Mark Spencer <markster@digium.com> + * - See ModMngMnt */ #include <stdio.h> @@ -74,14 +75,14 @@ static unsigned char expected_key[] = * MS_ACTIVE load() returned successfully. */ enum st_t { /* possible states of a module */ - MS_FAILED = 0, /* cannot load */ - MS_NEW = 1, /* nothing known */ - MS_RESOLVED = 2, /* all required resolved */ - MS_CANLOAD = 3, /* as above, plus cyclic depend.*/ - MS_ACTIVE = 4, /* all done */ + MS_FAILED = 0, /*!< cannot load */ + MS_NEW = 1, /*!< nothing known */ + MS_RESOLVED = 2, /*!< all required resolved */ + MS_CANLOAD = 3, /*!< as above, plus cyclic depend.*/ + MS_ACTIVE = 4, /*!< all done */ }; -/* +/*! \note * All module symbols are in module_symbols. * Modules are then linked in a list of struct module, * whereas updaters are in a list of struct loadupdate. @@ -115,7 +116,7 @@ static AST_LIST_HEAD_STATIC(module_list, module); static AST_LIST_HEAD_STATIC(updaters, loadupdate); AST_MUTEX_DEFINE_STATIC(reloadlock); -/* +/*! \note * helper localuser routines. * All of these routines are extremely expensive, so the use of * macros is totally unnecessary from the point of view of performance: @@ -209,8 +210,8 @@ static const char *st_name(enum st_t state) /*! \brief * Fetch/release an exported symbol - modify export_refcount by delta * \param delta 1 to fetch a symbol, -1 to release it. - * on success, return symbol value. - * Note, modules in MS_FAIL will never match in a 'get' request. + * \return on success, return symbol value. + * \note Note, modules in MS_FAIL will never match in a 'get' request. * If src is non-NULL, on exit *src points to the source module. * * Must be called with the lock held. @@ -297,8 +298,8 @@ static int check_exported(struct module *m) /*! * \brief Resolve symbols and change state accordingly. - * Return 1 if state changed, 0 otherwise. - * If MS_FAILED, MS_ACTIVE or MS_CANLOAD there is nothing to do. + * \return Return 1 if state changed, 0 otherwise. + * \note If MS_FAILED, MS_ACTIVE or MS_CANLOAD there is nothing to do. * If a symbol cannot be resolved (no supplier or supplier in MS_FAIL), * move to MS_FAIL and release all symbols; * If all suppliers are MS_ACTIVE, move to MS_CANLOAD @@ -333,8 +334,8 @@ static int resolve(struct module *m) return 1; } -/* - * Fixup references and load modules according to their dependency order. +/*! + * \brief Fixup references and load modules according to their dependency order. * Called when new modules are added to the list. * The algorithm is as follows: * - all modules MS_FAILED are changed to MS_NEW, in case something @@ -342,19 +343,19 @@ static int resolve(struct module *m) * - first try to resolve symbols. If successful, change the * module's state to MS_RESOLVED otherwise to MS_FAILED * - repeat on all modules until there is progress: - * . if it is MS_ACTIVE or MS_FAILED, continue (no progress) - * . if one has all required modules in MS_ACTIVE, try to load it. + * - if it is MS_ACTIVE or MS_FAILED, continue (no progress) + * - if one has all required modules in MS_ACTIVE, try to load it. * If successful it becomes MS_ACTIVE itself, otherwise * MS_FAILED and releases all symbols. * In any case, we have progress. - * . if one of the dependencies is MS_FAILED, release and set to + * - if one of the dependencies is MS_FAILED, release and set to * MS_FAILED here too. We have progress. * - if we have no progress there is a cyclic dependency. * Take first and change to MS_CANLOAD, i.e. as if all required are * MS_ACTIVE. we have progress, so repeat. - * NOTE: - * must be called with lock held - * recursive calls simply return success. + * \par NOTE: + * - must be called with lock held + * - recursive calls simply return success. */ static int fixup(const char *caller) { @@ -449,7 +450,7 @@ static void check_symbols(void) } /*--- end new-style routines ---*/ -/* +/*! \note * In addition to modules, the reload command handles some extra keywords * which are listed here together with the corresponding handlers. * This table is also used by the command completion code. @@ -812,10 +813,10 @@ static struct module * __load_resource(const char *resource_name, return cur; } -/* - * load a single module (API call). +/*! + * \brief load a single module (API call). * (recursive calls from load_module() succeed. - * Returns 0 on success, -1 on error. + * \return Returns 0 on success, -1 on error. */ int ast_load_resource(const char *resource_name) { @@ -851,7 +852,7 @@ int ast_load_resource(const char *resource_name) +} #endif -/* if enabled, log and output on console the module's name, and try load it */ +/*! \brief if enabled, log and output on console the module's name, and try load it */ static int print_and_load(const char *s, struct ast_config *cfg) { char tmp[80]; |