summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorge Joseph <gjoseph@digium.com>2017-04-21 15:47:36 -0500
committerGerrit Code Review <gerrit2@gerrit.digium.api>2017-04-21 15:47:36 -0500
commitdc6654d969224129bdd7b4080eda6e027c6454b9 (patch)
treeaba3b89f6f5f7e5c6445efb6d2bec27e8a428859
parentcebfe85affb9fe660bd68cfd0a875a79efd46a98 (diff)
parentc47b3e74d232820b79aa53c61a8fca112d128d20 (diff)
Merge "pbx: Use same thread if AST_OUTGOING_WAIT_COMPLETE specified"
-rw-r--r--main/pbx.c76
1 files changed, 42 insertions, 34 deletions
diff --git a/main/pbx.c b/main/pbx.c
index dc4b91f08..28027c06b 100644
--- a/main/pbx.c
+++ b/main/pbx.c
@@ -7529,8 +7529,8 @@ struct pbx_outgoing {
int dial_res;
/*! \brief Set when dialing is completed */
unsigned int dialed:1;
- /*! \brief Set when execution is completed */
- unsigned int executed:1;
+ /*! \brief Set if we've spawned a thread to do our work */
+ unsigned int in_separate_thread:1;
};
/*! \brief Destructor for outgoing structure */
@@ -7553,13 +7553,19 @@ static void *pbx_outgoing_exec(void *data)
RAII_VAR(struct pbx_outgoing *, outgoing, data, ao2_cleanup);
enum ast_dial_result res;
- /* Notify anyone interested that dialing is complete */
res = ast_dial_run(outgoing->dial, NULL, 0);
- ao2_lock(outgoing);
- outgoing->dial_res = res;
- outgoing->dialed = 1;
- ast_cond_signal(&outgoing->cond);
- ao2_unlock(outgoing);
+
+ if (outgoing->in_separate_thread) {
+ /* Notify anyone interested that dialing is complete */
+ ao2_lock(outgoing);
+ outgoing->dial_res = res;
+ outgoing->dialed = 1;
+ ast_cond_signal(&outgoing->cond);
+ ao2_unlock(outgoing);
+ } else {
+ /* We still need the dial result, but we don't need to lock */
+ outgoing->dial_res = res;
+ }
/* If the outgoing leg was not answered we can immediately return and go no further */
if (res != AST_DIAL_RESULT_ANSWERED) {
@@ -7599,12 +7605,6 @@ static void *pbx_outgoing_exec(void *data)
}
}
- /* Notify anyone else again that may be interested that execution is complete */
- ao2_lock(outgoing);
- outgoing->executed = 1;
- ast_cond_signal(&outgoing->cond);
- ao2_unlock(outgoing);
-
return NULL;
}
@@ -7810,34 +7810,42 @@ static int pbx_outgoing_attempt(const char *type, struct ast_format_cap *cap,
}
}
+ /* This extra reference is dereferenced by pbx_outgoing_exec */
ao2_ref(outgoing, +1);
- if (ast_pthread_create_detached(&thread, NULL, pbx_outgoing_exec, outgoing)) {
- ast_log(LOG_WARNING, "Unable to spawn dialing thread for '%s/%s'\n", type, addr);
- ao2_ref(outgoing, -1);
- if (locked_channel) {
- if (!synchronous) {
- ast_channel_unlock(dialed);
+
+ if (synchronous == AST_OUTGOING_WAIT_COMPLETE) {
+ /*
+ * Because we are waiting until this is complete anyway, there is no
+ * sense in creating another thread that we will just need to wait
+ * for, so instead we commandeer the current thread.
+ */
+ pbx_outgoing_exec(outgoing);
+ } else {
+ outgoing->in_separate_thread = 1;
+
+ if (ast_pthread_create_detached(&thread, NULL, pbx_outgoing_exec, outgoing)) {
+ ast_log(LOG_WARNING, "Unable to spawn dialing thread for '%s/%s'\n", type, addr);
+ ao2_ref(outgoing, -1);
+ if (locked_channel) {
+ if (!synchronous) {
+ ast_channel_unlock(dialed);
+ }
+ ast_channel_unref(dialed);
}
- ast_channel_unref(dialed);
+ return -1;
}
- return -1;
- }
- if (synchronous) {
- ao2_lock(outgoing);
- /* Wait for dialing to complete */
- while (!outgoing->dialed) {
- ast_cond_wait(&outgoing->cond, ao2_object_get_lockaddr(outgoing));
- }
- if (1 < synchronous
- && outgoing->dial_res == AST_DIAL_RESULT_ANSWERED) {
- /* Wait for execution to complete */
- while (!outgoing->executed) {
+ if (synchronous) {
+ ao2_lock(outgoing);
+ /* Wait for dialing to complete */
+ while (!outgoing->dialed) {
ast_cond_wait(&outgoing->cond, ao2_object_get_lockaddr(outgoing));
}
+ ao2_unlock(outgoing);
}
- ao2_unlock(outgoing);
+ }
+ if (synchronous) {
/* Determine the outcome of the dialing attempt up to it being answered. */
if (reason) {
*reason = pbx_dial_reason(outgoing->dial_res,