diff options
author | rizzo <rizzo@f38db490-d61c-443f-a65b-d21fe96a405b> | 2006-04-14 14:08:19 +0000 |
---|---|---|
committer | rizzo <rizzo@f38db490-d61c-443f-a65b-d21fe96a405b> | 2006-04-14 14:08:19 +0000 |
commit | 3664249356aa4768fcb0b3b8e6cf9365fcbd0c8d (patch) | |
tree | b68f48482e463e9c31126b2e3e24fca1dd2f6c82 /include | |
parent | f9d382fc079246930a99640d7835d6ae3e4149db (diff) |
This rather large commit changes the way modules are loaded.
As partly documented in loader.c and include/asterisk/module.h,
modules are now expected to return all of their methods and flags
into a structure 'mod_data', and are normally loaded with RTLD_NOW
| RTLD_LOCAL, so symbols are resolved immediately and conflicts
should be less likely. Only in a small number of cases (res_*,
typically) modules are loaded RTLD_GLOBAL, so they can export
symbols.
The core of the change is only the two files loader.c and
include/asterisk/module.h, all the rest is simply adaptation of the
existing modules to the new API, a rather mechanical (but believe
me, time and finger-consuming!) process whose detail you can figure
out by svn diff'ing any single module.
Expect some minor compilation issue after this change, please
report it on mantis http://bugs.digium.com/view.php?id=6968
so we collect all the feedback in one place.
I am just sorry that this change missed SVN version number 20000!
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@20003 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'include')
-rw-r--r-- | include/asterisk.h | 24 | ||||
-rw-r--r-- | include/asterisk/file.h | 2 | ||||
-rw-r--r-- | include/asterisk/module.h | 312 | ||||
-rw-r--r-- | include/asterisk/translate.h | 6 |
4 files changed, 91 insertions, 253 deletions
diff --git a/include/asterisk.h b/include/asterisk.h index 7e63f608c..8e8683211 100644 --- a/include/asterisk.h +++ b/include/asterisk.h @@ -74,16 +74,32 @@ void dnsmgr_start_refresh(void); int dnsmgr_reload(void); /*! + * \brief Reload asterisk modules. + * \param name the name of the module to reload + * + * This function reloads the specified module, or if no modules are specified, + * it will reload all loaded modules. + * + * \note Modules are reloaded using their reload() functions, not unloading + * them and loading them again. + * + * \return Zero if the specified module was not found, 1 if the module was + * found but cannot be reloaded, -1 if a reload operation is already in + * progress, and 2 if the specfied module was found and reloaded. + */ +int ast_module_reload(const char *name); + +/*! * \brief Register a function to be executed before Asterisk exits. * \param func The callback function to use. - * + * * \return Zero on success, -1 on error. */ int ast_register_atexit(void (*func)(void)); - -/*! + +/*! * \brief Unregister a function registered with ast_register_atexit(). - * \param func The callback function to unregister. + * \param func The callback function to unregister. */ void ast_unregister_atexit(void (*func)(void)); diff --git a/include/asterisk/file.h b/include/asterisk/file.h index 905ea0a0d..f8ac14b04 100644 --- a/include/asterisk/file.h +++ b/include/asterisk/file.h @@ -106,7 +106,7 @@ struct ast_format { int buf_size; /*! size of frame buffer, if any, aligned to 8 bytes. */ int desc_size; /*! size of private descriptor, if any */ - struct ast_format_lock *lockp; + struct module_symbols *module; }; /* diff --git a/include/asterisk/module.h b/include/asterisk/module.h index dfee1b1a3..1b1e434a6 100644 --- a/include/asterisk/module.h +++ b/include/asterisk/module.h @@ -26,7 +26,11 @@ #ifndef _ASTERISK_MODULE_H #define _ASTERISK_MODULE_H -#include "asterisk/linkedlists.h" /* XXX needed here */ +#ifdef STATIC_MODULE +#error STATIC_MODULE should not be defined +#endif +#define STATIC_MODULE --- this is an error +#define LOCAL_USER_DECL /* --- this is an error --- */ #include "asterisk/utils.h" @@ -34,83 +38,6 @@ extern "C" { #endif -#ifdef STATIC_MODULE /* symbols are static */ -#define _HAVE_STATIC_MODULE -#undef STATIC_MODULE -#define STATIC_MODULE static /* symbols are static */ -#else /* !STATIC_MODULE, symbols are global */ -#define STATIC_MODULE /* empty - symbols are global */ - -/*! \note Every module should provide these functions */ -/*! - * \brief Initialize the module. - * - * This function is called at module load time. Put all code in here - * that needs to set up your module's hardware, software, registrations, - * etc. - * - * \return This function should return 0 on success and non-zero on failure. - * If the module is not loaded successfully, Asterisk will call its - * unload_module() function. - */ -int load_module(void); - -/*! - * \brief Cleanup all module structures, sockets, etc. - * - * This is called at exit. Any registrations and memory allocations need to be - * unregistered and free'd here. Nothing else will do these for you (until - * exit). - * - * \return Zero on success, or non-zero on error. - */ -int unload_module(void); - -/*! - * \brief Provides a usecount. - * - * This function will be called by various parts of asterisk. Basically, all - * it has to do is to return a usecount when called. You will need to maintain - * your usecount within the module somewhere. The usecount should be how many - * channels provided by this module are in use. - * - * \return The module's usecount. - */ -int usecount(void); /* How many channels provided by this module are in use? */ - -/*! \brief Provides a description of the module. - * - * \return a short description of your module - */ -const char *description(void); /* Description of this module */ - -/*! - * \brief Returns the ASTERISK_GPL_KEY - * - * This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of - * the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does - * not return the EXACT message: - * - * \code - * char *key(void) { - * return ASTERISK_GPL_KEY; - * } - * \endcode - * - * \return ASTERISK_GPL_KEY - */ -const char *key(void); /* Return the below mentioned key, unmodified */ - -/*! - * \brief Reload stuff. - * - * This function is where any reload routines take place. Re-read config files, - * change signalling, whatever is appropriate on a reload. - * - * \return The return value is not used. - */ -int reload(void); /* reload configs */ -#endif /* !STATIC_MODULE case */ /*! \brief The text the key() function should return. */ #define ASTERISK_GPL_KEY \ @@ -128,32 +55,12 @@ express written permission of Digium, Inc. is prohibited.\n" #define AST_MODULE_CONFIG "modules.conf" /*!< \brief Module configuration file */ -/*! - * \brief Softly unload a module. - * - * This flag signals ast_unload_resource() to unload a module only if it is not - * in use, according to the module's usecount. - */ -#define AST_FORCE_SOFT 0 - -/*! - * \brief Firmly unload a module. - * - * This flag signals ast_unload_resource() to attempt to unload a module even - * if it is in use. It will attempt to use the module's unload_module - * function. - */ -#define AST_FORCE_FIRM 1 - -/*! - * \brief Unconditionally unload a module. - * - * This flag signals ast_unload_resource() to first attempt to unload a module - * using the module's unload_module function, then if that fails to unload the - * module using dlclose. The module will be unloaded even if it is still in - * use. Use of this flag is not recommended. - */ -#define AST_FORCE_HARD 2 +enum unload_mode { + AST_FORCE_SOFT = 0, /*! Softly unload a module, only if not in use */ + AST_FORCE_FIRM = 1, /*! Firmly unload a module, even if in use */ + AST_FORCE_HARD = 2, /*! as FIRM, plus dlclose() on the module. Not recommended + as it may cause crashes */ +}; /*! * \brief Load a module. @@ -180,7 +87,7 @@ int ast_load_resource(const char *resource_name); * * \return Zero on success, -1 on error. */ -int ast_unload_resource(const char *resource_name, int force); +int ast_unload_resource(const char *resource_name, enum unload_mode); /*! * \brief Notify when usecount has been changed. @@ -227,22 +134,6 @@ int ast_loader_register(int (*updater)(void)); int ast_loader_unregister(int (*updater)(void)); /*! - * \brief Reload asterisk modules. - * \param name the name of the module to reload - * - * This function reloads the specified module, or if no modules are specified, - * it will reload all loaded modules. - * - * \note Modules are reloaded using their reload() functions, not unloading - * them and loading them again. - * - * \return Zero if the specified module was not found, 1 if the module was - * found but cannot be reloaded, -1 if a reload operation is already in - * progress, and 2 if the specfied module was found and reloaded. - */ -int ast_module_reload(const char *name); - -/*! * \brief Match modules names for the Asterisk cli. * \param line Unused by this function, but this should be the line we are * matching. @@ -265,114 +156,19 @@ char *ast_module_helper(const char *line, const char *word, int pos, int state, they're in use at the time they have been requested to be removed */ struct localuser { + struct localuser *next; struct ast_channel *chan; - AST_LIST_ENTRY(localuser) next; -}; - -/*! \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. - */ -struct ast_module_lock { - ast_mutex_t lock; - AST_LIST_HEAD_NOLOCK(localuser_head, localuser) u; - int usecnt; /* number of active clients */ }; -struct localuser *ast_localuser_add(struct ast_module_lock *m, struct ast_channel *chan); -void ast_localuser_remove(struct ast_module_lock *m, struct localuser *u); -void ast_hangup_localusers(struct ast_module_lock *m); - -/*! - * \brief create a localuser mutex and several other variables used for keeping the - * use count. - * - * <b>Sample Usage:</b> - * \code - * LOCAL_USER_DECL; - * \endcode - */ -#define LOCAL_USER_DECL \ - static struct ast_module_lock me = { \ - .u = AST_LIST_HEAD_NOLOCK_INIT_VALUE, \ - .usecnt = 0, \ - .lock = AST_MUTEX_INIT_VALUE } - -#define STANDARD_USECOUNT_DECL LOCAL_USER_DECL /* XXX lock remains unused */ - -/*! \brief run 'x' protected by lock, then call ast_update_use_count() */ -#define __MOD_PROTECT(x) do { \ - ast_mutex_lock(&me.lock); \ - x; \ - ast_mutex_unlock(&me.lock); \ - ast_update_use_count(); \ - } while (0) - -#define STANDARD_INCREMENT_USECOUNT __MOD_PROTECT(me.usecnt++) -#define STANDARD_DECREMENT_USECOUNT __MOD_PROTECT(me.usecnt--) - -/*! - * \brief Add a localuser. - * \param u a pointer to a localuser struct - * - * This macro adds a localuser to the list of users and increments the - * usecount. It expects a variable named \p chan of type \p ast_channel in the - * current scope. - * - * \note This function dynamically allocates memory. If this operation fails - * it will cause your function to return -1 to the caller. - */ -#define LOCAL_USER_ADD(u) do { \ - u = ast_localuser_add(&me, chan); \ - if (!u) \ - return -1; \ - } while (0) - -/*! - * \brief Remove a localuser. - * \param u the user to add, should be of type struct localuser - * - * This macro removes a localuser from the list of users and decrements the - * usecount. - */ -#define LOCAL_USER_REMOVE(u) ast_localuser_remove(&me, u) - -/*! - * \brief Hangup all localusers. - * - * This macro hangs up on all current localusers and sets the usecount to zero - * when finished. - */ -#define STANDARD_HANGUP_LOCALUSERS ast_hangup_localusers(&me) +struct module_symbols; /* forward declaration */ +struct localuser *ast_localuser_add(struct module_symbols *, struct ast_channel *); +void ast_localuser_remove(struct module_symbols *, struct localuser *); +void ast_hangup_localusers(struct module_symbols *); -/*! - * \brief Set the specfied integer to the current usecount. - * \param res the integer variable to set. - * - * This macro sets the specfied integer variable to the local usecount. - * - * <b>Sample Usage:</b> - * \code - * int usecount(void) - * { - * int res; - * STANDARD_USECOUNT(res); - * return res; - * } - * \endcode - */ -#define STANDARD_USECOUNT(res) do { res = me.usecnt; } while (0) - -/*! \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 - * are updated to use the standard mechanism. - */ -#define OLD_STANDARD_USECOUNT(res) do { res = localusecnt; } while (0) +/* XXX deprecated macros, only for backward compatibility */ +#define LOCAL_USER_ADD(u) do { u = ast_localuser_add(__mod_desc, chan); } while (0) +#define LOCAL_USER_REMOVE(u) ast_localuser_remove(__mod_desc, u) +#define STANDARD_HANGUP_LOCALUSERS ast_hangup_localusers(__mod_desc) /*! \page ModMngmnt The Asterisk Module management interface * \par The following is part of the new module management code. @@ -388,7 +184,7 @@ void ast_hangup_localusers(struct ast_module_lock *m); * * Functions should be added with MOD_FUNC(name), * data structures with MOD_DATA(_name). - * The array in turn is referenced by struct module_symbol. + * The array in turn is referenced by struct module_symbols. * (Typically, a module will export only a single symbol, which points * 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. @@ -403,7 +199,7 @@ void ast_hangup_localusers(struct ast_module_lock *m); * to figure out if there is a mismatch (not terribly useful because most * objects are a single word, but still... ) * The symbol can be added to the array with MOD_WANT(symbol) macro. - * required_symbols is also pointed by through struct module_symbol. + * required_symbols is also pointed by through struct module_symbols. * * Typically, the whole interface exported by a module should be * in a single structure named after the module, as follows. @@ -501,25 +297,50 @@ struct ast_registry { }; struct module_symbols { - int (*load_module)(void); - int (*unload_module)(void); - int (*usecount)(void); - const char *(*description)(void); - const char *(*key)(void); - int (*reload)(void); - enum module_type { - MOD_0, /* old module style */ - MOD_1, /* old style, but symbols here */ - MOD_2, /* new style, exported symbols */ - } type; - struct ast_registry *reg; + /* load, reload and unload receive as argument a pointer to a module descriptor + * to be stored locally and used for local calls and so on. + * They all return 0 on success, non zero (-1) on failure. + */ + + int (*load_module)(void *); /* register stuff etc. Optional. */ + + int (*reload)(void *); /* reload config etc. Optional. */ + + int (*unload_module)(void *); /* unload. called with the module locked */ + + const char *(*description)(void); /* textual id of the module. */ + + /*! + * This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of + * the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does + * not return the EXACT message: + */ + const char *(*key)(void); /*! the asterisk key */ + + enum module_flags { + MOD_0 = 0x0, /* old module style */ + MOD_1 = 0x1, /* old style, but symbols here */ + MOD_2 = 0x2, /* new style, exported symbols */ + MOD_MASK = 0xf, /* mask for module types */ + NO_USECOUNT = 0x10, /* do not track usecount */ + NO_UNLOAD = 0x20, /* only forced unload allowed */ + DO_LOCALUSERS = 0x40, /* track localusers */ + } flags; + /* the following two fields should go in the astobj. */ + ast_mutex_t lock; + int usecnt; /* number of active clients */ + + /* list of clients */ + struct localuser *lu_head; + struct ast_registry *reg; /* list of things to register. */ struct symbol_entry *exported_symbols; struct symbol_entry *required_symbols; }; -#ifndef _HAVE_STATIC_MODULE -#define STD_MOD(t, reload_fn, exp, req) -#else +#ifndef MOD_LOADER /* the loader does not use these */ +struct module_symbols mod_data; /* forward declaration */ +static struct module_symbols *__mod_desc __attribute__ ((__unused__)) = &mod_data; /* used by localuser */ + #define STD_MOD(t, reload_fn, exp, req) \ struct module_symbols mod_data = { \ .load_module = load_module, \ @@ -527,12 +348,13 @@ struct module_symbols mod_data = { \ .description = description, \ .key = key, \ .reload = reload_fn, \ - .usecount = usecount, \ - .type = t, \ + .flags = t, \ .exported_symbols = exp, \ .required_symbols = req \ }; -#endif /* _HAVE_STATIC_MODULE */ + +#define STD_MOD1 STD_MOD(MOD_1, NULL, NULL, NULL) +#endif #if defined(__cplusplus) || defined(c_plusplus) } diff --git a/include/asterisk/translate.h b/include/asterisk/translate.h index 8f1a86759..a83cfa41e 100644 --- a/include/asterisk/translate.h +++ b/include/asterisk/translate.h @@ -33,7 +33,7 @@ extern "C" { #include "asterisk/frame.h" #include "asterisk/plc.h" #include "asterisk/linkedlists.h" -#include "asterisk/module.h" +// XXX #include "asterisk/module.h" #endif struct ast_trans_pvt; /* declared below */ @@ -98,7 +98,7 @@ struct ast_translator { int plc_samples; /* set to the plc block size if used, 0 otherwise */ int useplc; /* current status of plc, changed at runtime */ - struct ast_module_lock *lockp; + void *module; /* opaque reference to the parent module */ int cost; /*! Cost in milliseconds for encoding/decoding 1 second of sound */ AST_LIST_ENTRY(ast_translator) list; /*! link field */ @@ -147,7 +147,7 @@ struct ast_trans_pvt; * This registers a codec translator with asterisk * Returns 0 on success, -1 on failure */ -int ast_register_translator(struct ast_translator *t); +int ast_register_translator(struct ast_translator *t, void *module); /*! * \brief Unregister a translator |