aboutsummaryrefslogtreecommitdiffstats
path: root/include/asterisk/module.h
diff options
context:
space:
mode:
authorrizzo <rizzo@f38db490-d61c-443f-a65b-d21fe96a405b>2006-04-14 14:08:19 +0000
committerrizzo <rizzo@f38db490-d61c-443f-a65b-d21fe96a405b>2006-04-14 14:08:19 +0000
commit3664249356aa4768fcb0b3b8e6cf9365fcbd0c8d (patch)
treeb68f48482e463e9c31126b2e3e24fca1dd2f6c82 /include/asterisk/module.h
parentf9d382fc079246930a99640d7835d6ae3e4149db (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/asterisk/module.h')
-rw-r--r--include/asterisk/module.h312
1 files changed, 67 insertions, 245 deletions
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)
}