summaryrefslogtreecommitdiff
path: root/main/pbx.c
diff options
context:
space:
mode:
authorSean Bright <sean.bright@gmail.com>2017-04-19 16:08:39 -0400
committerSean Bright <sean.bright@gmail.com>2017-04-19 16:43:55 -0500
commitc47b3e74d232820b79aa53c61a8fca112d128d20 (patch)
tree050a815071dfd8e50ee23c875fcb7f950764c602 /main/pbx.c
parentb84abac1449c56d6c9f781525a533691b326ad8c (diff)
pbx: Use same thread if AST_OUTGOING_WAIT_COMPLETE specified
Both ast_pbx_outgoing_app() and ast_pbx_outgoing_exten() cause the core to spawn a new thread to perform the dial. When AST_OUTGOING_WAIT_COMPLETE is passed to these functions, the calling thread will be blocked until the newly created channel has been hung up. After this patch, we run the dial on the current thread rather than spawning a new one. The only in-tree code that passes AST_OUTGOING_WAIT_COMPLETE is pbx_spool, so you should see reduced thread usage if you are using .call files. Change-Id: I512735d243f0a9da2bcc128f7a96dece71f2d913
Diffstat (limited to 'main/pbx.c')
-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,