diff options
Diffstat (limited to 'main/loader.c')
-rw-r--r-- | main/loader.c | 425 |
1 files changed, 244 insertions, 181 deletions
diff --git a/main/loader.c b/main/loader.c index 7d792b08e..b9baf3e93 100644 --- a/main/loader.c +++ b/main/loader.c @@ -54,7 +54,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/features_config.h" #include "asterisk/dsp.h" #include "asterisk/udptl.h" -#include "asterisk/heap.h" +#include "asterisk/vector.h" #include "asterisk/app.h" #include "asterisk/test.h" #include "asterisk/sounds_index.h" @@ -112,6 +112,8 @@ static const unsigned char expected_key[] = static char buildopt_sum[33] = AST_BUILDOPT_SUM; +AST_VECTOR(module_vector, struct ast_module *); + /*! * \brief Internal flag to indicate all modules have been initially loaded. */ @@ -137,13 +139,34 @@ struct ast_module { /*! This module is being held open until it's time to shutdown. */ unsigned int keepuntilshutdown:1; } flags; - AST_LIST_ENTRY(ast_module) list_entry; AST_DLLIST_ENTRY(ast_module) entry; char resource[0]; }; static AST_DLLIST_HEAD_STATIC(module_list, ast_module); +static int module_vector_strcasecmp(struct ast_module *a, struct ast_module *b) +{ + return strcasecmp(a->resource, b->resource); +} + +static int module_vector_cmp(struct ast_module *a, struct ast_module *b) +{ + /* if load_pri is not set, default is 128. Lower is better */ + int a_pri = ast_test_flag(a->info, AST_MODFLAG_LOAD_ORDER) + ? a->info->load_pri : AST_MODPRI_DEFAULT; + int b_pri = ast_test_flag(b->info, AST_MODFLAG_LOAD_ORDER) + ? b->info->load_pri : AST_MODPRI_DEFAULT; + + /* + * Returns comparison values for a vector sorted by priority. + * <0 a_pri < b_pri + * =0 a_pri == b_pri + * >0 a_pri > b_pri + */ + return a_pri - b_pri; +} + const char *ast_module_name(const struct ast_module *mod) { if (!mod || !mod->info) { @@ -171,38 +194,51 @@ static int do_full_reload = 0; static AST_DLLIST_HEAD_STATIC(reload_queue, reload_queue_item); -/* when dynamic modules are being loaded, ast_module_register() will - need to know what filename the module was loaded from while it - is being registered -*/ -static struct ast_module *resource_being_loaded; - -/* XXX: should we check for duplicate resource names here? */ +/*! + * \internal + * + * This variable is set by load_dynamic_module so ast_module_register + * can know what pointer is being registered. + * + * This is protected by the module_list lock. + */ +static struct ast_module * volatile resource_being_loaded; +/*! + * \internal + * \brief Used by AST_MODULE_INFO to register with the module loader. + * + * This function is automatically called when each module is opened. + * It must never be used from outside AST_MODULE_INFO. + */ void ast_module_register(const struct ast_module_info *info) { - struct ast_module *mod = resource_being_loaded; + struct ast_module *mod; + + /* + * This lock protects resource_being_loaded as well as the module + * list. Normally we already have a lock on module_list when we + * begin the load but locking again from here prevents corruption + * if an asterisk module is dlopen'ed from outside the module loader. + */ + AST_DLLIST_LOCK(&module_list); + mod = resource_being_loaded; + if (!mod) { + AST_DLLIST_UNLOCK(&module_list); + return; + } ast_debug(5, "Registering module %s\n", info->name); + /* This tells load_dynamic_module that we're registered. */ + resource_being_loaded = NULL; + mod->info = info; #ifdef REF_DEBUG mod->ref_debug = ao2_t_alloc(0, NULL, info->name); #endif AST_LIST_HEAD_INIT(&mod->users); - /* during startup, before the loader has been initialized, - there are no threads, so there is no need to take the lock - on this list to manipulate it. it is also possible that it - might be unsafe to use the list lock at that point... so - let's avoid it altogether - */ - AST_DLLIST_LOCK(&module_list); - /* it is paramount that the new entry be placed at the tail of - the list, otherwise the code that uses dlopen() to load - dynamic modules won't be able to find out if the module it - just opened was registered or failed to load - */ AST_DLLIST_INSERT_TAIL(&module_list, mod, entry); AST_DLLIST_UNLOCK(&module_list); @@ -210,6 +246,15 @@ void ast_module_register(const struct ast_module_info *info) *((struct ast_module **) &(info->self)) = mod; } +static void module_destroy(struct ast_module *mod) +{ + AST_LIST_HEAD_DESTROY(&mod->users); +#ifdef REF_DEBUG + ao2_cleanup(mod->ref_debug); +#endif + ast_free(mod); +} + void ast_module_unregister(const struct ast_module_info *info) { struct ast_module *mod = NULL; @@ -230,11 +275,7 @@ void ast_module_unregister(const struct ast_module_info *info) if (mod) { ast_debug(5, "Unregistering module %s\n", info->name); - AST_LIST_HEAD_DESTROY(&mod->users); -#ifdef REF_DEBUG - ao2_cleanup(mod->ref_debug); -#endif - ast_free(mod); + module_destroy(mod); } } @@ -382,35 +423,39 @@ static int verify_key(const unsigned char *key) return -1; } -static int resource_name_match(const char *name1_in, const char *name2_in) +static size_t resource_name_baselen(const char *name) { - char *name1 = (char *) name1_in; - char *name2 = (char *) name2_in; + size_t len = strlen(name); - /* trim off any .so extensions */ - if (!strcasecmp(name1 + strlen(name1) - 3, ".so")) { - name1 = ast_strdupa(name1); - name1[strlen(name1) - 3] = '\0'; + if (len > 3 && !strcasecmp(name + len - 3, ".so")) { + return len - 3; } - if (!strcasecmp(name2 + strlen(name2) - 3, ".so")) { - name2 = ast_strdupa(name2); - name2[strlen(name2) - 3] = '\0'; + + return len; +} + +static int resource_name_match(const char *name1, size_t baselen1, const char *name2) +{ + if (baselen1 != resource_name_baselen(name2)) { + return -1; } - return strcasecmp(name1, name2); + return strncasecmp(name1, name2, baselen1); } static struct ast_module *find_resource(const char *resource, int do_lock) { struct ast_module *cur; + size_t resource_baselen = resource_name_baselen(resource); if (do_lock) { AST_DLLIST_LOCK(&module_list); } AST_DLLIST_TRAVERSE(&module_list, cur, entry) { - if (!resource_name_match(resource, cur->resource)) + if (!resource_name_match(resource, resource_baselen, cur->resource)) { break; + } } if (do_lock) { @@ -500,96 +545,93 @@ static void unload_dynamic_module(struct ast_module *mod) #endif } -static enum ast_module_load_result load_resource(const char *resource_name, unsigned int global_symbols_only, unsigned int suppress_logging, struct ast_heap *resource_heap, int required); - #define MODULE_LOCAL_ONLY (void *)-1 -static struct ast_module *load_dynamic_module(const char *resource_in, unsigned int global_symbols_only, unsigned int suppress_logging, struct ast_heap *resource_heap) +/*! + * \internal + * \brief Attempt to dlopen a module. + * + * \param resource_in The module name to load. + * \param so_ext ".so" or blank if ".so" is already part of resource_in. + * \param filename Passed directly to dlopen. + * \param flags Passed directly to dlopen. + * \param suppress_logging Do not log any error from dlopen. + * + * \return Pointer to opened module, NULL on error. + * + * \warning module_list must be locked before calling this function. + */ +static struct ast_module *load_dlopen(const char *resource_in, const char *so_ext, + const char *filename, int flags, unsigned int suppress_logging) { - char fn[PATH_MAX] = ""; - void *lib = NULL; struct ast_module *mod; - unsigned int wants_global; - int space; /* room needed for the descriptor */ - int missing_so = 0; - space = sizeof(*resource_being_loaded) + strlen(resource_in) + 1; - if (strcasecmp(resource_in + strlen(resource_in) - 3, ".so")) { - missing_so = 1; - space += 3; /* room for the extra ".so" */ - } - - snprintf(fn, sizeof(fn), "%s/%s%s", ast_config_AST_MODULE_DIR, resource_in, missing_so ? ".so" : ""); + ast_assert(!resource_being_loaded); - /* make a first load of the module in 'quiet' mode... don't try to resolve - any symbols, and don't export any symbols. this will allow us to peek into - the module's info block (if available) to see what flags it has set */ - - resource_being_loaded = ast_calloc(1, space); - if (!resource_being_loaded) + mod = ast_calloc(1, sizeof(*mod) + strlen(resource_in) + strlen(so_ext) + 1); + if (!mod) { return NULL; - strcpy(resource_being_loaded->resource, resource_in); - if (missing_so) - strcat(resource_being_loaded->resource, ".so"); + } + + sprintf(mod->resource, "%s%s", resource_in, so_ext); /* safe */ - if (!(lib = dlopen(fn, RTLD_LAZY | RTLD_GLOBAL))) { - if (!suppress_logging) { + resource_being_loaded = mod; + mod->lib = dlopen(filename, flags); + if (resource_being_loaded) { + resource_being_loaded = NULL; + if (mod->lib) { + ast_log(LOG_ERROR, "Module '%s' did not register itself during load\n", resource_in); + logged_dlclose(resource_in, mod->lib); + } else if (!suppress_logging) { ast_log(LOG_WARNING, "Error loading module '%s': %s\n", resource_in, dlerror()); } - ast_free(resource_being_loaded); - return NULL; - } + ast_free(mod); - /* the dlopen() succeeded, let's find out if the module - registered itself */ - /* note that this will only work properly as long as - ast_module_register() (which is called by the module's - constructor) places the new module at the tail of the - module_list - */ - if (resource_being_loaded != (mod = AST_DLLIST_LAST(&module_list))) { - ast_log(LOG_WARNING, "Module '%s' did not register itself during load\n", resource_in); - /* no, it did not, so close it and return */ - logged_dlclose(resource_in, lib); - /* note that the module's destructor will call ast_module_unregister(), - which will free the structure we allocated in resource_being_loaded */ return NULL; } - wants_global = ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS); + return mod; +} + +static struct ast_module *load_dynamic_module(const char *resource_in, unsigned int global_symbols_only, unsigned int suppress_logging) +{ + char fn[PATH_MAX]; + struct ast_module *mod; + size_t resource_in_len = strlen(resource_in); + int exports_globals; + const char *so_ext = ""; - /* if we are being asked only to load modules that provide global symbols, - and this one does not, then close it and return */ - if (global_symbols_only && !wants_global) { - logged_dlclose(resource_in, lib); - return MODULE_LOCAL_ONLY; + if (resource_in_len < 4 || strcasecmp(resource_in + resource_in_len - 3, ".so")) { + so_ext = ".so"; } - logged_dlclose(resource_in, lib); - resource_being_loaded = NULL; + snprintf(fn, sizeof(fn), "%s/%s%s", ast_config_AST_MODULE_DIR, resource_in, so_ext); - /* start the load process again */ - resource_being_loaded = ast_calloc(1, space); - if (!resource_being_loaded) - return NULL; - strcpy(resource_being_loaded->resource, resource_in); - if (missing_so) - strcat(resource_being_loaded->resource, ".so"); + /* Try loading in quiet mode first with flags to export global symbols. + * If the module does not want to export globals we will close and reopen. */ + mod = load_dlopen(resource_in, so_ext, fn, + global_symbols_only ? RTLD_LAZY | RTLD_GLOBAL : RTLD_NOW | RTLD_LOCAL, + suppress_logging); - if (!(lib = dlopen(fn, wants_global ? RTLD_LAZY | RTLD_GLOBAL : RTLD_NOW | RTLD_LOCAL))) { - ast_log(LOG_WARNING, "Error loading module '%s': %s\n", resource_in, dlerror()); - ast_free(resource_being_loaded); + if (!mod) { return NULL; } - /* since the module was successfully opened, and it registered itself - the previous time we did that, we're going to assume it worked this - time too :) */ + exports_globals = ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS); + if ((global_symbols_only && exports_globals) || (!global_symbols_only && !exports_globals)) { + /* The first dlopen had the correct flags. */ + return mod; + } - AST_DLLIST_LAST(&module_list)->lib = lib; - resource_being_loaded = NULL; + /* Close the module so we can reopen with correct flags. */ + logged_dlclose(resource_in, mod->lib); + if (global_symbols_only) { + return MODULE_LOCAL_ONLY; + } - return AST_DLLIST_LAST(&module_list); + return load_dlopen(resource_in, so_ext, fn, + exports_globals ? RTLD_LAZY | RTLD_GLOBAL : RTLD_NOW | RTLD_LOCAL, + 0); } int modules_shutdown(void) @@ -623,11 +665,7 @@ int modules_shutdown(void) ast_verb(1, "Unloading %s\n", mod->resource); mod->info->unload(); } - AST_LIST_HEAD_DESTROY(&mod->users); -#ifdef REF_DEBUG - ao2_cleanup(mod->ref_debug); -#endif - free(mod); + module_destroy(mod); somethingchanged = 1; } AST_DLLIST_TRAVERSE_BACKWARDS_SAFE_END; @@ -947,6 +985,7 @@ enum ast_module_reload_result ast_module_reload(const char *name) struct ast_module *cur; enum ast_module_reload_result res = AST_MODULE_RELOAD_NOT_FOUND; int i; + size_t name_baselen = name ? resource_name_baselen(name) : 0; /* If we aren't fully booted, we just pretend we reloaded but we queue this up to run once we are booted up. */ @@ -1000,8 +1039,9 @@ enum ast_module_reload_result ast_module_reload(const char *name) AST_DLLIST_TRAVERSE(&module_list, cur, entry) { const struct ast_module_info *info = cur->info; - if (name && resource_name_match(name, cur->resource)) + if (name && resource_name_match(name, name_baselen, cur->resource)) { continue; + } if (!cur->flags.running || cur->flags.declined) { if (res == AST_MODULE_RELOAD_NOT_FOUND) { @@ -1122,13 +1162,13 @@ static enum ast_module_load_result start_resource(struct ast_module *mod) /*! loads a resource based upon resource_name. If global_symbols_only is set * only modules with global symbols will be loaded. * - * If the ast_heap is provided (not NULL) the module is found and added to the - * heap without running the module's load() function. By doing this, modules - * added to the resource_heap can be initialized later in order by priority. + * If the module_vector is provided (not NULL) the module is found and added to the + * vector without running the module's load() function. By doing this, modules + * can be initialized later in order by priority and dependencies. * - * If the ast_heap is not provided, the module's load function will be executed + * If the module_vector is not provided, the module's load function will be executed * immediately */ -static enum ast_module_load_result load_resource(const char *resource_name, unsigned int global_symbols_only, unsigned int suppress_logging, struct ast_heap *resource_heap, int required) +static enum ast_module_load_result load_resource(const char *resource_name, unsigned int global_symbols_only, unsigned int suppress_logging, struct module_vector *resource_heap, int required) { struct ast_module *mod; enum ast_module_load_result res = AST_MODULE_LOAD_SUCCESS; @@ -1141,7 +1181,7 @@ static enum ast_module_load_result load_resource(const char *resource_name, unsi if (global_symbols_only && !ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS)) return AST_MODULE_LOAD_SKIP; } else { - mod = load_dynamic_module(resource_name, global_symbols_only, suppress_logging, resource_heap); + mod = load_dynamic_module(resource_name, global_symbols_only, suppress_logging); if (mod == MODULE_LOCAL_ONLY) { return AST_MODULE_LOAD_SKIP; } @@ -1154,21 +1194,26 @@ static enum ast_module_load_result load_resource(const char *resource_name, unsi } if (inspect_module(mod)) { - ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name); - unload_dynamic_module(mod); - return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE; + goto prestart_error; } mod->flags.declined = 0; if (resource_heap) { - ast_heap_push(resource_heap, mod); + if (AST_VECTOR_ADD_SORTED(resource_heap, mod, module_vector_cmp)) { + goto prestart_error; + } res = AST_MODULE_LOAD_PRIORITY; } else { res = start_resource(mod); } return res; + +prestart_error: + ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name); + unload_dynamic_module(mod); + return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE; } int ast_load_resource(const char *resource_name) @@ -1195,9 +1240,10 @@ AST_LIST_HEAD_NOLOCK(load_order, load_order_entry); static struct load_order_entry *add_to_load_order(const char *resource, struct load_order *load_order, int required) { struct load_order_entry *order; + size_t resource_baselen = resource_name_baselen(resource); AST_LIST_TRAVERSE(load_order, order, entry) { - if (!resource_name_match(order->resource, resource)) { + if (!resource_name_match(resource, resource_baselen, order->resource)) { /* Make sure we have the proper setting for the required field (we might have both load= and required= lines in modules.conf) */ order->required |= required; @@ -1215,23 +1261,6 @@ static struct load_order_entry *add_to_load_order(const char *resource, struct l return order; } -static int mod_load_cmp(void *a, void *b) -{ - struct ast_module *a_mod = (struct ast_module *) a; - struct ast_module *b_mod = (struct ast_module *) b; - /* if load_pri is not set, default is 128. Lower is better */ - int a_pri = ast_test_flag(a_mod->info, AST_MODFLAG_LOAD_ORDER) ? a_mod->info->load_pri : 128; - int b_pri = ast_test_flag(b_mod->info, AST_MODFLAG_LOAD_ORDER) ? b_mod->info->load_pri : 128; - - /* - * Returns comparison values for a min-heap - * <0 a_pri > b_pri - * =0 a_pri == b_pri - * >0 a_pri < b_pri - */ - return b_pri - a_pri; -} - AST_LIST_HEAD_NOLOCK(load_retries, load_order_entry); /*! loads modules in order by load_pri, updates mod_count @@ -1239,9 +1268,8 @@ AST_LIST_HEAD_NOLOCK(load_retries, load_order_entry); */ static int load_resource_list(struct load_order *load_order, unsigned int global_symbols, int *mod_count) { - struct ast_heap *resource_heap; + struct module_vector resource_heap; struct load_order_entry *order; - struct ast_module *mod; struct load_retries load_retries; int count = 0; int res = 0; @@ -1250,7 +1278,9 @@ static int load_resource_list(struct load_order *load_order, unsigned int global AST_LIST_HEAD_INIT_NOLOCK(&load_retries); - if(!(resource_heap = ast_heap_create(8, mod_load_cmp, -1))) { + if (AST_VECTOR_INIT(&resource_heap, 500)) { + ast_log(LOG_ERROR, "Failed to initialize module loader.\n"); + return -1; } @@ -1259,7 +1289,7 @@ static int load_resource_list(struct load_order *load_order, unsigned int global enum ast_module_load_result lres; /* Suppress log messages unless this is the last pass */ - lres = load_resource(order->resource, global_symbols, 1, resource_heap, order->required); + lres = load_resource(order->resource, global_symbols, 1, &resource_heap, order->required); ast_debug(3, "PASS 0: %-46s %d %d\n", order->resource, lres, global_symbols); switch (lres) { case AST_MODULE_LOAD_SUCCESS: @@ -1283,7 +1313,7 @@ static int load_resource_list(struct load_order *load_order, unsigned int global */ break; case AST_MODULE_LOAD_PRIORITY: - /* load_resource worked and the module was added to the priority heap */ + /* load_resource worked and the module was added to the priority vector */ AST_LIST_REMOVE_CURRENT(entry); ast_free(order->resource); ast_free(order); @@ -1298,7 +1328,7 @@ static int load_resource_list(struct load_order *load_order, unsigned int global enum ast_module_load_result lres; /* Suppress log messages unless this is the last pass */ - lres = load_resource(order->resource, global_symbols, (i < LOAD_RETRIES - 1), resource_heap, order->required); + lres = load_resource(order->resource, global_symbols, (i < LOAD_RETRIES - 1), &resource_heap, order->required); ast_debug(3, "PASS %d %-46s %d %d\n", i + 1, order->resource, lres, global_symbols); switch (lres) { /* These are all retryable. */ @@ -1336,7 +1366,8 @@ static int load_resource_list(struct load_order *load_order, unsigned int global } /* second remove modules from heap sorted by priority */ - while ((mod = ast_heap_pop(resource_heap))) { + for (i = 0; i < AST_VECTOR_SIZE(&resource_heap); i++) { + struct ast_module *mod = AST_VECTOR_GET(&resource_heap, i); enum ast_module_load_result lres; lres = start_resource(mod); @@ -1366,7 +1397,7 @@ done: if (mod_count) { *mod_count += count; } - ast_heap_destroy(resource_heap); + AST_VECTOR_FREE(&resource_heap); return res; } @@ -1444,11 +1475,15 @@ int load_modules(unsigned int preload_only) /* now scan the config for any modules we are prohibited from loading and remove them from the load order */ for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) { - if (strcasecmp(v->name, "noload")) + size_t baselen; + + if (strcasecmp(v->name, "noload")) { continue; + } + baselen = resource_name_baselen(v->value); AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) { - if (!resource_name_match(order->resource, v->value)) { + if (!resource_name_match(v->value, baselen, order->resource)) { AST_LIST_REMOVE_CURRENT(entry); ast_free(order->resource); ast_free(order); @@ -1500,33 +1535,57 @@ void ast_update_use_count(void) AST_LIST_UNLOCK(&updaters); } +/*! + * \internal + * \brief Build an alpha sorted list of modules. + * + * \param alpha_module_list Pointer to uninitialized module_vector. + * + * This function always initializes alpha_module_list. + * + * \pre module_list must be locked. + */ +static int alpha_module_list_create(struct module_vector *alpha_module_list) +{ + struct ast_module *cur; + + if (AST_VECTOR_INIT(alpha_module_list, 32)) { + return -1; + } + + AST_DLLIST_TRAVERSE(&module_list, cur, entry) { + if (AST_VECTOR_ADD_SORTED(alpha_module_list, cur, module_vector_strcasecmp)) { + return -1; + } + } + + return 0; +} + int ast_update_module_list(int (*modentry)(const char *module, const char *description, int usecnt, const char *status, const char *like, enum ast_module_support_level support_level), const char *like) { - struct ast_module *cur; - int unlock = -1; int total_mod_loaded = 0; - AST_LIST_HEAD_NOLOCK(, ast_module) alpha_module_list = AST_LIST_HEAD_NOLOCK_INIT_VALUE; + struct module_vector alpha_module_list; - if (AST_DLLIST_TRYLOCK(&module_list)) { - unlock = 0; - } + AST_DLLIST_LOCK(&module_list); - AST_DLLIST_TRAVERSE(&module_list, cur, entry) { - AST_LIST_INSERT_SORTALPHA(&alpha_module_list, cur, list_entry, resource); - } + if (!alpha_module_list_create(&alpha_module_list)) { + int idx; - while ((cur = AST_LIST_REMOVE_HEAD(&alpha_module_list, list_entry))) { - total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount, - cur->flags.running ? "Running" : "Not Running", like, cur->info->support_level); - } + for (idx = 0; idx < AST_VECTOR_SIZE(&alpha_module_list); idx++) { + struct ast_module *cur = AST_VECTOR_GET(&alpha_module_list, idx); - if (unlock) { - AST_DLLIST_UNLOCK(&module_list); + total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount, + cur->flags.running ? "Running" : "Not Running", like, cur->info->support_level); + } } + AST_DLLIST_UNLOCK(&module_list); + AST_VECTOR_FREE(&alpha_module_list); + return total_mod_loaded; } @@ -1536,22 +1595,24 @@ int ast_update_module_list_data(int (*modentry)(const char *module, const char * void *data), const char *like, void *data) { - struct ast_module *cur; int total_mod_loaded = 0; - AST_LIST_HEAD_NOLOCK(, ast_module) alpha_module_list = AST_LIST_HEAD_NOLOCK_INIT_VALUE; + struct module_vector alpha_module_list; AST_DLLIST_LOCK(&module_list); - AST_DLLIST_TRAVERSE(&module_list, cur, entry) { - AST_LIST_INSERT_SORTALPHA(&alpha_module_list, cur, list_entry, resource); - } + if (!alpha_module_list_create(&alpha_module_list)) { + int idx; - while ((cur = AST_LIST_REMOVE_HEAD(&alpha_module_list, list_entry))) { - total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount, - cur->flags.running? "Running" : "Not Running", like, cur->info->support_level, data); + for (idx = 0; idx < AST_VECTOR_SIZE(&alpha_module_list); idx++) { + struct ast_module *cur = AST_VECTOR_GET(&alpha_module_list, idx); + + total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount, + cur->flags.running? "Running" : "Not Running", like, cur->info->support_level, data); + } } AST_DLLIST_UNLOCK(&module_list); + AST_VECTOR_FREE(&alpha_module_list); return total_mod_loaded; } @@ -1563,23 +1624,25 @@ int ast_update_module_list_condition(int (*modentry)(const char *module, const c void *data, const char *condition), const char *like, void *data, const char *condition) { - struct ast_module *cur; int conditions_met = 0; - AST_LIST_HEAD_NOLOCK(, ast_module) alpha_module_list = AST_LIST_HEAD_NOLOCK_INIT_VALUE; + struct module_vector alpha_module_list; AST_DLLIST_LOCK(&module_list); - AST_DLLIST_TRAVERSE(&module_list, cur, entry) { - AST_LIST_INSERT_SORTALPHA(&alpha_module_list, cur, list_entry, resource); - } + if (!alpha_module_list_create(&alpha_module_list)) { + int idx; - while ((cur = AST_LIST_REMOVE_HEAD(&alpha_module_list, list_entry))) { - conditions_met += modentry(cur->resource, cur->info->description, cur->usecount, - cur->flags.running? "Running" : "Not Running", like, cur->info->support_level, data, - condition); + for (idx = 0; idx < AST_VECTOR_SIZE(&alpha_module_list); idx++) { + struct ast_module *cur = AST_VECTOR_GET(&alpha_module_list, idx); + + conditions_met += modentry(cur->resource, cur->info->description, cur->usecount, + cur->flags.running? "Running" : "Not Running", like, cur->info->support_level, data, + condition); + } } AST_DLLIST_UNLOCK(&module_list); + AST_VECTOR_FREE(&alpha_module_list); return conditions_met; } |