[asterisk-commits] dvossel: trunk r199743 - in /trunk: include/asterisk/ main/ res/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Jun 9 11:22:09 CDT 2009


Author: dvossel
Date: Tue Jun  9 11:22:04 2009
New Revision: 199743

URL: http://svn.asterisk.org/svn-view/asterisk?view=rev&rev=199743
Log:
module load priority

This patch adds the option to give a module a load priority. The value represents the order in which a module's load() function is initialized.  The lower the value, the higher the priority.  The value is only checked if the AST_MODFLAG_LOAD_ORDER flag is set.  If the AST_MODFLAG_LOAD_ORDER flag is not set, the value will never be read and the module will be given the lowest possible priority
on load.  Since some modules are reliant on a timing interface, the timing modules have been given a high load priorty.

(closes issue #15191)
Reported by: alecdavis
Tested by: dvossel

Review: https://reviewboard.asterisk.org/r/262/

Modified:
    trunk/include/asterisk/module.h
    trunk/main/loader.c
    trunk/res/res_timing_dahdi.c
    trunk/res/res_timing_pthread.c
    trunk/res/res_timing_timerfd.c

Modified: trunk/include/asterisk/module.h
URL: http://svn.asterisk.org/svn-view/asterisk/trunk/include/asterisk/module.h?view=diff&rev=199743&r1=199742&r2=199743
==============================================================================
--- trunk/include/asterisk/module.h (original)
+++ trunk/include/asterisk/module.h Tue Jun  9 11:22:04 2009
@@ -189,6 +189,7 @@
 enum ast_module_flags {
 	AST_MODFLAG_DEFAULT = 0,
 	AST_MODFLAG_GLOBAL_SYMBOLS = (1 << 0),
+	AST_MODFLAG_LOAD_ORDER = (1 << 1),
 };
 
 struct ast_module_info {
@@ -219,6 +220,13 @@
 
 	/*! The value of AST_BUILDOPT_SUM when this module was compiled */
 	const char buildopt_sum[33];
+
+	/*! This value represents the order in which a module's load() function is initialized.
+	 *  The lower this value, the higher the priority.  The value is only checked if the
+	 *  AST_MODFLAG_LOAD_ORDER flag is set.  If the AST_MODFLAG_LOAD_ORDER flag is not set,
+	 *  this value will never be read and the module will be given the lowest possible priority
+	 *  on load. */
+	unsigned char load_pri;
 };
 
 void ast_module_register(const struct ast_module_info *);

Modified: trunk/main/loader.c
URL: http://svn.asterisk.org/svn-view/asterisk/trunk/main/loader.c?view=diff&rev=199743&r1=199742&r2=199743
==============================================================================
--- trunk/main/loader.c (original)
+++ trunk/main/loader.c Tue Jun  9 11:22:04 2009
@@ -48,6 +48,7 @@
 #include "asterisk/features.h"
 #include "asterisk/dsp.h"
 #include "asterisk/udptl.h"
+#include "asterisk/heap.h"
 
 #include <dlfcn.h>
 
@@ -712,11 +713,57 @@
 	return 0;
 }
 
-static enum ast_module_load_result load_resource(const char *resource_name, unsigned int global_symbols_only)
+static enum ast_module_load_result start_resource(struct ast_module *mod)
+{
+	char tmp[256];
+	enum ast_module_load_result res;
+
+	if (!mod->info->load) {
+		return AST_MODULE_LOAD_FAILURE;
+	}
+
+	res = mod->info->load();
+
+	switch (res) {
+	case AST_MODULE_LOAD_SUCCESS:
+		if (!ast_fully_booted) {
+			ast_verb(1, "%s => (%s)\n", mod->resource, term_color(tmp, mod->info->description, COLOR_BROWN, COLOR_BLACK, sizeof(tmp)));
+			if (ast_opt_console && !option_verbose)
+				ast_verbose( ".");
+		} else {
+			ast_verb(1, "Loaded %s => (%s)\n", mod->resource, mod->info->description);
+		}
+
+		mod->flags.running = 1;
+
+		ast_update_use_count();
+		break;
+	case AST_MODULE_LOAD_DECLINE:
+		mod->flags.declined = 1;
+		break;
+	case AST_MODULE_LOAD_FAILURE:
+		break;
+	case AST_MODULE_LOAD_SKIP:
+		/* modules should never return this value */
+		break;
+	}
+
+	return res;
+}
+
+/*! 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 initilized later in order by priority. 
+ *
+ *  If the ast_heap 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, struct ast_heap *resource_heap)
 {
 	struct ast_module *mod;
 	enum ast_module_load_result res = AST_MODULE_LOAD_SUCCESS;
-	char tmp[256];
 
 	if ((mod = find_resource(resource_name, 0))) {
 		if (mod->flags.running) {
@@ -757,31 +804,11 @@
 
 	mod->flags.declined = 0;
 
-	if (mod->info->load)
-		res = mod->info->load();
-
-	switch (res) {
-	case AST_MODULE_LOAD_SUCCESS:
-		if (!ast_fully_booted) {
-			ast_verb(1, "%s => (%s)\n", resource_name, term_color(tmp, mod->info->description, COLOR_BROWN, COLOR_BLACK, sizeof(tmp)));
-			if (ast_opt_console && !option_verbose)
-				ast_verbose( ".");
-		} else {
-			ast_verb(1, "Loaded %s => (%s)\n", resource_name, mod->info->description);
-		}
-
-		mod->flags.running = 1;
-
-		ast_update_use_count();
-		break;
-	case AST_MODULE_LOAD_DECLINE:
-		mod->flags.declined = 1;
-		break;
-	case AST_MODULE_LOAD_FAILURE:
-		break;
-	case AST_MODULE_LOAD_SKIP:
-		/* modules should never return this value */
-		break;
+	if (resource_heap) {
+		ast_heap_push(resource_heap, mod);
+		res = AST_MODULE_LOAD_SKIP;
+	} else {
+		res = start_resource(mod);
 	}
 
 	return res;
@@ -791,7 +818,7 @@
 {
 	int res;
 	AST_LIST_LOCK(&module_list);
-	res = load_resource(resource_name, 0);
+	res = load_resource(resource_name, 0, NULL);
 	AST_LIST_UNLOCK(&module_list);
 
 	return res;
@@ -820,6 +847,77 @@
 	AST_LIST_INSERT_TAIL(load_order, order, entry);
 
 	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;
+	int res = -1;
+	/* if load_pri is not set, default is 255.  Lower is better*/
+	unsigned char a_pri = ast_test_flag(a_mod->info, AST_MODFLAG_LOAD_ORDER) ? a_mod->info->load_pri : 255;
+	unsigned char b_pri = ast_test_flag(a_mod->info, AST_MODFLAG_LOAD_ORDER) ? b_mod->info->load_pri : 255;
+	if (a_pri == b_pri) {
+		res = 0;
+	} else if (a_pri < b_pri) {
+		res = 1;
+	}
+	return res;
+}
+
+/*! loads modules in order by load_pri, updates mod_count */
+static int load_resource_list(struct load_order *load_order, unsigned int global_symbols, int *mod_count)
+{
+	struct ast_heap *resource_heap;
+	struct load_order_entry *order;
+	struct ast_module *mod;
+	int count = 0;
+	int res = 0;
+
+	if(!(resource_heap = ast_heap_create(8, mod_load_cmp, -1))) {
+		return -1;
+	}
+
+	/* first, add find and add modules to heap */
+	AST_LIST_TRAVERSE_SAFE_BEGIN(load_order, order, entry) {
+		switch (load_resource(order->resource, global_symbols, resource_heap)) {
+		case AST_MODULE_LOAD_SUCCESS:
+		case AST_MODULE_LOAD_DECLINE:
+			AST_LIST_REMOVE_CURRENT(entry);
+			ast_free(order->resource);
+			ast_free(order);
+			break;
+		case AST_MODULE_LOAD_FAILURE:
+			res = -1;
+			goto done;
+		case AST_MODULE_LOAD_SKIP:
+			break;
+		}
+	}
+	AST_LIST_TRAVERSE_SAFE_END;
+
+	/* second remove modules from heap sorted by priority */
+	while ((mod = ast_heap_pop(resource_heap))) {
+		switch (start_resource(mod)) {
+		case AST_MODULE_LOAD_SUCCESS:
+			count++;
+		case AST_MODULE_LOAD_DECLINE:
+			break;
+		case AST_MODULE_LOAD_FAILURE:
+			res = -1;
+			goto done;
+		case AST_MODULE_LOAD_SKIP:
+			break;
+		}
+	}
+
+done:
+	if (mod_count) {
+		*mod_count += count;
+	}
+	ast_heap_destroy(resource_heap);
+
+	return res;
 }
 
 int load_modules(unsigned int preload_only)
@@ -941,44 +1039,14 @@
 		ast_log(LOG_NOTICE, "%d modules will be loaded.\n", load_count);
 
 	/* first, load only modules that provide global symbols */
-	AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) {
-		switch (load_resource(order->resource, 1)) {
-		case AST_MODULE_LOAD_SUCCESS:
-			modulecount++;
-		case AST_MODULE_LOAD_DECLINE:
-			AST_LIST_REMOVE_CURRENT(entry);
-			ast_free(order->resource);
-			ast_free(order);
-			break;
-		case AST_MODULE_LOAD_FAILURE:
-			res = -1;
-			goto done;
-		case AST_MODULE_LOAD_SKIP:
-			/* try again later */
-			break;
-		}
-	}
-	AST_LIST_TRAVERSE_SAFE_END;
+	if ((res = load_resource_list(&load_order, 1, &modulecount)) < 0) {
+		goto done;
+	}
 
 	/* now load everything else */
-	AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) {
-		switch (load_resource(order->resource, 0)) {
-		case AST_MODULE_LOAD_SUCCESS:
-			modulecount++;
-		case AST_MODULE_LOAD_DECLINE:
-			AST_LIST_REMOVE_CURRENT(entry);
-			ast_free(order->resource);
-			ast_free(order);
-			break;
-		case AST_MODULE_LOAD_FAILURE:
-			res = -1;
-			goto done;
-		case AST_MODULE_LOAD_SKIP:
-			/* should not happen */
-			break;
-		}
-	}
-	AST_LIST_TRAVERSE_SAFE_END;
+	if ((res = load_resource_list(&load_order, 0, &modulecount)) < 0) {
+		goto done;
+	}
 
 done:
 	while ((order = AST_LIST_REMOVE_HEAD(&load_order, entry))) {

Modified: trunk/res/res_timing_dahdi.c
URL: http://svn.asterisk.org/svn-view/asterisk/trunk/res/res_timing_dahdi.c?view=diff&rev=199743&r1=199742&r2=199743
==============================================================================
--- trunk/res/res_timing_dahdi.c (original)
+++ trunk/res/res_timing_dahdi.c Tue Jun  9 11:22:04 2009
@@ -199,4 +199,8 @@
 	return 0;
 }
 
-AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "DAHDI Timing Interface");
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "DAHDI Timing Interface",
+		.load = load_module,
+		.unload = unload_module,
+		.load_pri = 10,
+		);

Modified: trunk/res/res_timing_pthread.c
URL: http://svn.asterisk.org/svn-view/asterisk/trunk/res/res_timing_pthread.c?view=diff&rev=199743&r1=199742&r2=199743
==============================================================================
--- trunk/res/res_timing_pthread.c (original)
+++ trunk/res/res_timing_pthread.c Tue Jun  9 11:22:04 2009
@@ -521,5 +521,8 @@
 
 	return res;
 }
-
-AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "pthread Timing Interface");
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "pthread Timing Interface",
+		.load = load_module,
+		.unload = unload_module,
+		.load_pri = 10,
+		);

Modified: trunk/res/res_timing_timerfd.c
URL: http://svn.asterisk.org/svn-view/asterisk/trunk/res/res_timing_timerfd.c?view=diff&rev=199743&r1=199742&r2=199743
==============================================================================
--- trunk/res/res_timing_timerfd.c (original)
+++ trunk/res/res_timing_timerfd.c Tue Jun  9 11:22:04 2009
@@ -286,4 +286,8 @@
 	return res;
 }
 
-AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Timerfd Timing Interface");
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Timerfd Timing Interface",
+		.load = load_module,
+		.unload = unload_module,
+		.load_pri = 10,
+		);




More information about the asterisk-commits mailing list