diff --git a/asterisk.8.gz b/asterisk.8.gz
index abbd0c45312bcbb54d0220a7c64661cf50b7f7b3..d05b828286821f76e2b02f98eac700d760fae784 100755
Binary files a/asterisk.8.gz and b/asterisk.8.gz differ
diff --git a/asterisk.c b/asterisk.c
index f42193fe3006af355f022e3d3d058ba4c8724552..308519ba27768a2ae19fa080a4c1b8bb1ee8eecb 100755
--- a/asterisk.c
+++ b/asterisk.c
@@ -87,6 +87,7 @@ int option_timestamp = 0;
 int option_overrideconfig = 0;
 int option_reconnect = 0;
 int option_transcode_slin = 1;
+int option_maxcalls = 0;
 int fully_booted = 0;
 char record_cache_dir[AST_CACHE_DIR_LEN] = AST_TMP_DIR;
 char debug_filename[AST_FILENAME_MAX] = "";
@@ -1658,6 +1659,11 @@ static void ast_readconfig(void) {
 		/* Build transcode paths via SLINEAR, instead of directly */
 		} else if (!strcasecmp(v->name, "transcode_via_sln")) {
 			option_transcode_slin = ast_true(v->value);
+		} else if (!strcasecmp(v->name, "maxcalls")) {
+			if ((sscanf(v->value, "%d", &option_maxcalls) != 1) ||
+			    (option_maxcalls < 0)) {
+				option_maxcalls = 0;
+			}
 		}
 		v = v->next;
 	}
@@ -1711,7 +1717,7 @@ int main(int argc, char *argv[])
 	}
 	*/
 	/* Check for options */
-	while((c=getopt(argc, argv, "tThfdvVqprRgcinx:U:G:C:")) != -1) {
+	while((c=getopt(argc, argv, "tThfdvVqprRgcinx:U:G:C:M:")) != -1) {
 		switch(c) {
 		case 'd':
 			option_debug++;
@@ -1743,6 +1749,10 @@ int main(int argc, char *argv[])
 			option_verbose++;
 			option_nofork++;
 			break;
+		case 'M':
+			if ((sscanf(optarg, "%d", &option_maxcalls) != 1) || (option_maxcalls < 0))
+				option_maxcalls = 0;
+			break;
 		case 'q':
 			option_quiet++;
 			break;
diff --git a/asterisk.sgml b/asterisk.sgml
index b84ad0020a55fc1c898584efab482c973d362fee..abee2e678709f9d9381e31f660a8ad7e17181752 100755
--- a/asterisk.sgml
+++ b/asterisk.sgml
@@ -26,6 +26,7 @@
 <arg><option>-U </option><replaceable class="parameter">user</replaceable></arg>
 <arg><option>-G </option><replaceable class="parameter">group</replaceable></arg>
 <arg><option>-x </option><replaceable class="parameter">command</replaceable></arg>
+<arg><option>-M </option><replaceable class="parameter">value</replaceable></arg>
 	</cmdsynopsis>
 	<cmdsynopsis>
 
@@ -141,6 +142,16 @@
 			</para>
 		</listitem>
 	</varlistentry>
+	<varlistentry>
+		<term>-M <replaceable class="parameter">value</replaceable></term>
+		<listitem>
+			<para>
+			Limits the maximum number of calls to the specified value.  This can
+			be useful to prevent a system from being brought down by terminating
+			too many simultaneous calls.
+			</para>
+		</listitem>
+	</varlistentry>
 	<varlistentry>
 		<term>-n</term>
 		<listitem>
diff --git a/cli.c b/cli.c
index 141ac09ae7bf15197ee221f781979d1528758051..80150eefed88ccac89f0bbb0b63506f48ea1c545 100755
--- a/cli.c
+++ b/cli.c
@@ -429,8 +429,13 @@ static int handle_chanlist(int fd, int argc, char *argv[])
 		ast_mutex_unlock(&c->lock);
 		c = ast_channel_walk_locked(c);
 	}
-	if(!concise)
+	if(!concise) {
 		ast_cli(fd, "%d active channel(s)\n", numchans);
+		if (option_maxcalls)
+			ast_cli(fd, "%d of %d max active call(s) (%5.2f%% of capacity)\n", ast_active_calls(), option_maxcalls, ((float)ast_active_calls() / (float)option_maxcalls) * 100.0);
+		else
+			ast_cli(fd, "%d active call(s)\n", ast_active_calls());
+	}
 	return RESULT_SUCCESS;
 }
 
diff --git a/include/asterisk/options.h b/include/asterisk/options.h
index 598ea31db0139b019ee16ba7ac019d930ddd74e1..9d962bbe5a2f76a2edeec148713ec6724dd7bf13 100755
--- a/include/asterisk/options.h
+++ b/include/asterisk/options.h
@@ -33,6 +33,7 @@ extern int option_exec_includes;
 extern int option_cache_record_files;
 extern int option_timestamp;
 extern int option_transcode_slin;
+extern int option_maxcalls;
 extern char defaultlanguage[];
 extern time_t ast_startuptime;
 extern time_t ast_lastreloadtime;
diff --git a/include/asterisk/pbx.h b/include/asterisk/pbx.h
index 19331acff36ab72eba95007e38d95db46662a37d..b0f92b60a597040e19234cd538674eada21e7aa3 100755
--- a/include/asterisk/pbx.h
+++ b/include/asterisk/pbx.h
@@ -602,6 +602,9 @@ int ast_async_goto_if_exists(struct ast_channel *chan, char* context, char *exte
 struct ast_custom_function* ast_custom_function_find(char *name);
 int ast_custom_function_unregister(struct ast_custom_function *acf);
 int ast_custom_function_register(struct ast_custom_function *acf);
+
+/* Number of active calls */
+int ast_active_calls(void);
 	
 /*! executes a read operation on a function */
 /*!
diff --git a/pbx.c b/pbx.c
index ebadafd3614046a45e96a5e970e3a0ba9adb64b4..803c3fca47bc599bebb9c188f64b668a097de602 100755
--- a/pbx.c
+++ b/pbx.c
@@ -213,6 +213,9 @@ static struct varshead globals;
 
 static int autofallthrough = 0;
 
+AST_MUTEX_DEFINE_STATIC(maxcalllock);
+static int countcalls = 0;
+
 AST_MUTEX_DEFINE_STATIC(acflock); 		/* Lock for the custom function list */
 static struct ast_custom_function *acf_root = NULL;
 
@@ -2232,7 +2235,7 @@ int ast_exec_extension(struct ast_channel *c, const char *context, const char *e
 	return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, HELPER_EXEC);
 }
 
-int ast_pbx_run(struct ast_channel *c)
+static int __ast_pbx_run(struct ast_channel *c)
 {
 	int firstpass = 1;
 	char digit;
@@ -2497,6 +2500,34 @@ int ast_pbx_start(struct ast_channel *c)
 	return 0;
 }
 
+int ast_pbx_run(struct ast_channel *c)
+{
+	int res = 0;
+	ast_mutex_lock(&maxcalllock);
+	if (option_maxcalls) {
+		if (countcalls >= option_maxcalls) {
+			ast_log(LOG_NOTICE, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name);
+			res = -1;
+		}
+	}
+	if (!res)
+		countcalls++;	
+	ast_mutex_unlock(&maxcalllock);
+	if (!res) {
+		res = __ast_pbx_run(c);
+		ast_mutex_lock(&maxcalllock);
+		if (countcalls > 0)
+			countcalls--;
+		ast_mutex_unlock(&maxcalllock);
+	}
+	return res;
+}
+
+int ast_active_calls(void)
+{
+	return countcalls;
+}
+
 int pbx_set_autofallthrough(int newval)
 {
 	int oldval;