diff --git a/include/asterisk/pbx.h b/include/asterisk/pbx.h
index 9828aa6bbc83bb50ea9f8e17fa7b0000aa16769d..f49eee16bdd9e614be1c792af908b42d19058a5d 100755
--- a/include/asterisk/pbx.h
+++ b/include/asterisk/pbx.h
@@ -206,21 +206,27 @@ void ast_context_destroy(struct ast_context *con, const char *registrar);
  */
 struct ast_context *ast_context_find(const char *name);
 
+enum ast_pbx_result {
+	AST_PBX_SUCCESS = 0,
+	AST_PBX_FAILED = -1,
+	AST_PBX_CALL_LIMIT = -2,
+};
+
 /*! Create a new thread and start the PBX (or whatever) */
 /*!
  * \param c channel to start the pbx on
- * Starts a pbx thread on a given channel
- * It returns -1 on failure, and 0 on success
+ * \return Zero on success, non-zero on failure
  */
-int ast_pbx_start(struct ast_channel *c);
+enum ast_pbx_result ast_pbx_start(struct ast_channel *c);
 
 /*! Execute the PBX in the current thread */
 /*!
  * \param c channel to run the pbx on
- * This executes the PBX on a given channel.  It allocates a new
+ * \return Zero on success, non-zero on failure
+ * This executes the PBX on a given channel. It allocates a new
  * PBX structure for the channel, and provides all PBX functionality.
  */
-int ast_pbx_run(struct ast_channel *c);
+enum ast_pbx_result ast_pbx_run(struct ast_channel *c);
 
 /*! 
  * \param context context to add the extension to
diff --git a/pbx.c b/pbx.c
index a1eb07b99fec1b19358b8c195b0a1ae6fd10775b..6bae090ac8345a456e31853276c46c0c6ff1d98f 100755
--- a/pbx.c
+++ b/pbx.c
@@ -2407,56 +2407,87 @@ out:
 	return 0;
 }
 
+/* Returns 0 on success, non-zero if call limit was reached */
+static int increase_call_count(const struct ast_channel *c)
+{
+	int failed = 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);
+			failed = -1;
+		}
+	}
+	if (!failed)
+		countcalls++;	
+	ast_mutex_unlock(&maxcalllock);
+
+	return failed;
+}
+
+static void decrease_call_count(void)
+{
+	ast_mutex_lock(&maxcalllock);
+	if (countcalls > 0)
+		countcalls--;
+	ast_mutex_unlock(&maxcalllock);
+}
+
 static void *pbx_thread(void *data)
 {
 	/* Oh joyeous kernel, we're a new thread, with nothing to do but
 	   answer this channel and get it going.
 	*/
+	/* NOTE:
+	   The launcher of this function _MUST_ increment 'countcalls'
+	   before invoking the function; it will be decremented when the
+	   PBX has finished running on the channel
+	 */
 	struct ast_channel *c = data;
-	ast_pbx_run(c);
+
+	__ast_pbx_run(c);
+	decrease_call_count();
+
 	pthread_exit(NULL);
+
 	return NULL;
 }
 
-int ast_pbx_start(struct ast_channel *c)
+enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
 {
 	pthread_t t;
 	pthread_attr_t attr;
+
 	if (!c) {
 		ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
-		return -1;
+		return AST_PBX_FAILED;
 	}
 	   
+	if (increase_call_count(c))
+		return AST_PBX_CALL_LIMIT;
+
 	/* Start a new thread, and get something handling this channel. */
 	pthread_attr_init(&attr);
 	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 	if (ast_pthread_create(&t, &attr, pbx_thread, c)) {
 		ast_log(LOG_WARNING, "Failed to create new channel thread\n");
-		return -1;
+		return AST_PBX_FAILED;
 	}
-	return 0;
+
+	return AST_PBX_SUCCESS;
 }
 
-int ast_pbx_run(struct ast_channel *c)
+enum ast_pbx_result 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);
-	}
+	enum ast_pbx_result res = AST_PBX_SUCCESS;
+
+	if (increase_call_count(c))
+		return AST_PBX_CALL_LIMIT;
+
+	res = __ast_pbx_run(c);
+	decrease_call_count();
+
 	return res;
 }