Some code optimizations.
[asterisk/asterisk.git] / channels / sig_pri.c
index 887f4c4..dce5cac 100644 (file)
@@ -895,37 +895,85 @@ static int pri_find_dchan(struct sig_pri_pri *pri)
        return 0;
 }
 
        return 0;
 }
 
-static void pri_queue_frame(struct sig_pri_chan *p, struct ast_frame *f, struct sig_pri_pri *pri)
+/*!
+ * \internal
+ * \brief Obtain the sig_pri owner channel lock if the owner exists.
+ * \since 1.8
+ *
+ * \param pri sig_pri PRI control structure.
+ * \param chanpos Channel position in the span.
+ *
+ * \note Assumes the pri->lock is already obtained.
+ * \note Assumes the sig_pri_lock_private(pri->pvts[chanpos]) is already obtained.
+ *
+ * \return Nothing
+ */
+static void sig_pri_lock_owner(struct sig_pri_pri *pri, int chanpos)
 {
 {
-       /* We must unlock the PRI to avoid the possibility of a deadlock */
-       if (pri)
-               ast_mutex_unlock(&pri->lock);
        for (;;) {
        for (;;) {
-               if (p->owner) {
-                       if (ast_channel_trylock(p->owner)) {
-                               PRI_DEADLOCK_AVOIDANCE(p);
-                       } else {
-                               ast_queue_frame(p->owner, f);
-                               ast_channel_unlock(p->owner);
-                               break;
-                       }
-               } else
+               if (!pri->pvts[chanpos]->owner) {
+                       /* There is no owner lock to get. */
                        break;
                        break;
-       }
-       if (pri)
+               }
+               if (!ast_channel_trylock(pri->pvts[chanpos]->owner)) {
+                       /* We got the lock */
+                       break;
+               }
+               /* We must unlock the PRI to avoid the possibility of a deadlock */
+               ast_mutex_unlock(&pri->lock);
+               PRI_DEADLOCK_AVOIDANCE(pri->pvts[chanpos]);
                ast_mutex_lock(&pri->lock);
                ast_mutex_lock(&pri->lock);
+       }
 }
 
 }
 
-static void pri_queue_control(struct sig_pri_chan *p, int subclass, struct sig_pri_pri *pri)
+/*!
+ * \internal
+ * \brief Queue the given frame onto the owner channel.
+ * \since 1.8
+ *
+ * \param pri sig_pri PRI control structure.
+ * \param chanpos Channel position in the span.
+ * \param frame Frame to queue onto the owner channel.
+ *
+ * \note Assumes the pri->lock is already obtained.
+ * \note Assumes the sig_pri_lock_private(pri->pvts[chanpos]) is already obtained.
+ *
+ * \return Nothing
+ */
+static void pri_queue_frame(struct sig_pri_pri *pri, int chanpos, struct ast_frame *frame)
+{
+       sig_pri_lock_owner(pri, chanpos);
+       if (pri->pvts[chanpos]->owner) {
+               ast_queue_frame(pri->pvts[chanpos]->owner, frame);
+               ast_channel_unlock(pri->pvts[chanpos]->owner);
+       }
+}
+
+/*!
+ * \internal
+ * \brief Queue a control frame of the specified subclass onto the owner channel.
+ * \since 1.8
+ *
+ * \param pri sig_pri PRI control structure.
+ * \param chanpos Channel position in the span.
+ * \param subclass Control frame subclass to queue onto the owner channel.
+ *
+ * \note Assumes the pri->lock is already obtained.
+ * \note Assumes the sig_pri_lock_private(pri->pvts[chanpos]) is already obtained.
+ *
+ * \return Nothing
+ */
+static void pri_queue_control(struct sig_pri_pri *pri, int chanpos, int subclass)
 {
        struct ast_frame f = {AST_FRAME_CONTROL, };
 {
        struct ast_frame f = {AST_FRAME_CONTROL, };
+       struct sig_pri_chan *p = pri->pvts[chanpos];
 
        if (p->calls->queue_control) {
                p->calls->queue_control(p->chan_pvt, subclass);
        }
 
        f.subclass.integer = subclass;
 
        if (p->calls->queue_control) {
                p->calls->queue_control(p->chan_pvt, subclass);
        }
 
        f.subclass.integer = subclass;
-       pri_queue_frame(p, &f, pri);
+       pri_queue_frame(pri, chanpos, &f);
 }
 
 static int pri_find_principle(struct sig_pri_pri *pri, int channel, q931_call *call)
 }
 
 static int pri_find_principle(struct sig_pri_pri *pri, int channel, q931_call *call)
@@ -1521,37 +1569,6 @@ static int sig_pri_msn_match(const char *msn_patterns, const char *exten)
        return 0;
 }
 
        return 0;
 }
 
-/*!
- * \internal
- * \brief Obtain the sig_pri owner channel lock if the owner exists.
- * \since 1.8
- *
- * \param pri sig_pri PRI control structure.
- * \param chanpos Channel position in the span.
- *
- * \note Assumes the pri->lock is already obtained.
- * \note Assumes the sig_pri_lock_private(pri->pvts[chanpos]) is already obtained.
- *
- * \return Nothing
- */
-static void sig_pri_lock_owner(struct sig_pri_pri *pri, int chanpos)
-{
-       for (;;) {
-               if (!pri->pvts[chanpos]->owner) {
-                       /* There is no owner lock to get. */
-                       break;
-               }
-               if (!ast_channel_trylock(pri->pvts[chanpos]->owner)) {
-                       /* We got the lock */
-                       break;
-               }
-               /* We must unlock the PRI to avoid the possibility of a deadlock */
-               ast_mutex_unlock(&pri->lock);
-               PRI_DEADLOCK_AVOIDANCE(pri->pvts[chanpos]);
-               ast_mutex_lock(&pri->lock);
-       }
-}
-
 #if defined(HAVE_PRI_CCSS)
 /*!
  * \internal
 #if defined(HAVE_PRI_CCSS)
 /*!
  * \internal
@@ -2533,8 +2550,13 @@ static int sig_pri_handle_hold(struct sig_pri_pri *pri, pri_event *ev)
        } else {
                struct ast_frame f = { AST_FRAME_CONTROL, };
 
        } else {
                struct ast_frame f = { AST_FRAME_CONTROL, };
 
+               /*
+                * Things are in an odd state here so we cannot use pri_queue_control().
+                * However, we already have the owner lock so we can simply queue the frame.
+                */
                f.subclass.integer = AST_CONTROL_HOLD;
                ast_queue_frame(owner, &f);
                f.subclass.integer = AST_CONTROL_HOLD;
                ast_queue_frame(owner, &f);
+
                sig_pri_span_devstate_changed(pri);
                retval = 0;
        }
                sig_pri_span_devstate_changed(pri);
                retval = 0;
        }
@@ -2602,12 +2624,7 @@ static void sig_pri_handle_retrieve(struct sig_pri_pri *pri, pri_event *ev)
        sig_pri_lock_private(pri->pvts[chanpos]);
        sig_pri_handle_subcmds(pri, chanpos, ev->e, ev->retrieve.channel,
                ev->retrieve.subcmds, ev->retrieve.call);
        sig_pri_lock_private(pri->pvts[chanpos]);
        sig_pri_handle_subcmds(pri, chanpos, ev->e, ev->retrieve.channel,
                ev->retrieve.subcmds, ev->retrieve.call);
-       {
-               struct ast_frame f = { AST_FRAME_CONTROL, };
-
-               f.subclass.integer = AST_CONTROL_UNHOLD;
-               pri_queue_frame(pri->pvts[chanpos], &f, pri);
-       }
+       pri_queue_control(pri, chanpos, AST_CONTROL_UNHOLD);
        sig_pri_unlock_private(pri->pvts[chanpos]);
        sig_pri_span_devstate_changed(pri);
        pri_retrieve_ack(pri->pri, ev->retrieve.call,
        sig_pri_unlock_private(pri->pvts[chanpos]);
        sig_pri_span_devstate_changed(pri);
        pri_retrieve_ack(pri->pri, ev->retrieve.call,
@@ -2953,7 +2970,7 @@ static void *pri_dchannel(void *vpri)
                                                        for (i = 0; i < digitlen; i++) {
                                                                struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = e->digit.digits[i], };
 
                                                        for (i = 0; i < digitlen; i++) {
                                                                struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = e->digit.digits[i], };
 
-                                                               pri_queue_frame(pri->pvts[chanpos], &f, pri);
+                                                               pri_queue_frame(pri, chanpos, &f);
                                                        }
                                                }
                                                sig_pri_unlock_private(pri->pvts[chanpos]);
                                                        }
                                                }
                                                sig_pri_unlock_private(pri->pvts[chanpos]);
@@ -2988,7 +3005,7 @@ static void *pri_dchannel(void *vpri)
                                                        for (i = 0; i < digitlen; i++) {
                                                                struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = e->ring.callednum[i], };
 
                                                        for (i = 0; i < digitlen; i++) {
                                                                struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = e->ring.callednum[i], };
 
-                                                               pri_queue_frame(pri->pvts[chanpos], &f, pri);
+                                                               pri_queue_frame(pri, chanpos, &f);
                                                        }
                                                }
                                                sig_pri_unlock_private(pri->pvts[chanpos]);
                                                        }
                                                }
                                                sig_pri_unlock_private(pri->pvts[chanpos]);
@@ -3430,7 +3447,7 @@ static void *pri_dchannel(void *vpri)
                                                        e->ringing.subcmds, e->ringing.call);
                                                sig_pri_cc_generic_check(pri, chanpos, AST_CC_CCNR);
                                                sig_pri_set_echocanceller(pri->pvts[chanpos], 1);
                                                        e->ringing.subcmds, e->ringing.call);
                                                sig_pri_cc_generic_check(pri, chanpos, AST_CC_CCNR);
                                                sig_pri_set_echocanceller(pri->pvts[chanpos], 1);
-                                               pri_queue_control(pri->pvts[chanpos], AST_CONTROL_RINGING, pri);
+                                               pri_queue_control(pri, chanpos, AST_CONTROL_RINGING);
                                                pri->pvts[chanpos]->alerting = 1;
 
 #ifdef SUPPORT_USERUSER
                                                pri->pvts[chanpos]->alerting = 1;
 
 #ifdef SUPPORT_USERUSER
@@ -3469,8 +3486,9 @@ static void *pri_dchannel(void *vpri)
                                                || (e->proceeding.progress == 8)
 #endif
                                                ) {
                                                || (e->proceeding.progress == 8)
 #endif
                                                ) {
-                                               struct ast_frame f = { AST_FRAME_CONTROL, .subclass.integer = AST_CONTROL_PROGRESS, };
+                                               int subclass;
 
 
+                                               subclass = AST_CONTROL_PROGRESS;
                                                if (e->proceeding.cause > -1) {
                                                        ast_verb(3, "PROGRESS with cause code %d received\n", e->proceeding.cause);
 
                                                if (e->proceeding.cause > -1) {
                                                        ast_verb(3, "PROGRESS with cause code %d received\n", e->proceeding.cause);
 
@@ -3480,14 +3498,14 @@ static void *pri_dchannel(void *vpri)
                                                                        ast_verb(3, "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
 
                                                                        pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
                                                                        ast_verb(3, "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
 
                                                                        pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
-                                                                       f.subclass.integer = AST_CONTROL_BUSY;
+                                                                       subclass = AST_CONTROL_BUSY;
                                                                }
                                                        }
                                                }
 
                                                ast_debug(1, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
                                                        pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
                                                                }
                                                        }
                                                }
 
                                                ast_debug(1, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
                                                        pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
-                                               pri_queue_frame(pri->pvts[chanpos], &f, pri);
+                                               pri_queue_control(pri, chanpos, subclass);
                                                if (
 #ifdef PRI_PROGRESS_MASK
                                                        e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
                                                if (
 #ifdef PRI_PROGRESS_MASK
                                                        e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
@@ -3496,8 +3514,7 @@ static void *pri_dchannel(void *vpri)
 #endif
                                                        ) {
                                                        /* Bring voice path up */
 #endif
                                                        ) {
                                                        /* Bring voice path up */
-                                                       f.subclass.integer = AST_CONTROL_PROGRESS;
-                                                       pri_queue_frame(pri->pvts[chanpos], &f, pri);
+                                                       pri_queue_control(pri, chanpos, AST_CONTROL_PROGRESS);
                                                }
                                                pri->pvts[chanpos]->progress = 1;
                                                sig_pri_set_dialing(pri->pvts[chanpos], 0);
                                                }
                                                pri->pvts[chanpos]->progress = 1;
                                                sig_pri_set_dialing(pri->pvts[chanpos], 0);
@@ -3517,11 +3534,9 @@ static void *pri_dchannel(void *vpri)
                                        sig_pri_handle_subcmds(pri, chanpos, e->e, e->proceeding.channel,
                                                e->proceeding.subcmds, e->proceeding.call);
                                        if (!pri->pvts[chanpos]->proceeding) {
                                        sig_pri_handle_subcmds(pri, chanpos, e->e, e->proceeding.channel,
                                                e->proceeding.subcmds, e->proceeding.call);
                                        if (!pri->pvts[chanpos]->proceeding) {
-                                               struct ast_frame f = { AST_FRAME_CONTROL, .subclass.integer = AST_CONTROL_PROCEEDING, };
-
                                                ast_debug(1, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
                                                        pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
                                                ast_debug(1, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
                                                        pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
-                                               pri_queue_frame(pri->pvts[chanpos], &f, pri);
+                                               pri_queue_control(pri, chanpos, AST_CONTROL_PROCEEDING);
                                                if (
 #ifdef PRI_PROGRESS_MASK
                                                        e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
                                                if (
 #ifdef PRI_PROGRESS_MASK
                                                        e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
@@ -3530,8 +3545,7 @@ static void *pri_dchannel(void *vpri)
 #endif
                                                        ) {
                                                        /* Bring voice path up */
 #endif
                                                        ) {
                                                        /* Bring voice path up */
-                                                       f.subclass.integer = AST_CONTROL_PROGRESS;
-                                                       pri_queue_frame(pri->pvts[chanpos], &f, pri);
+                                                       pri_queue_control(pri, chanpos, AST_CONTROL_PROGRESS);
                                                }
                                                pri->pvts[chanpos]->proceeding = 1;
                                                sig_pri_set_dialing(pri->pvts[chanpos], 0);
                                                }
                                                pri->pvts[chanpos]->proceeding = 1;
                                                sig_pri_set_dialing(pri->pvts[chanpos], 0);
@@ -3593,7 +3607,7 @@ static void *pri_dchannel(void *vpri)
 
                                                sig_pri_handle_subcmds(pri, chanpos, e->e, e->answer.channel,
                                                        e->answer.subcmds, e->answer.call);
 
                                                sig_pri_handle_subcmds(pri, chanpos, e->e, e->answer.channel,
                                                        e->answer.subcmds, e->answer.call);
-                                               pri_queue_control(pri->pvts[chanpos], AST_CONTROL_ANSWER, pri);
+                                               pri_queue_control(pri, chanpos, AST_CONTROL_ANSWER);
                                                /* Enable echo cancellation if it's not on already */
                                                sig_pri_set_dialing(pri->pvts[chanpos], 0);
                                                sig_pri_set_echocanceller(pri->pvts[chanpos], 1);
                                                /* Enable echo cancellation if it's not on already */
                                                sig_pri_set_dialing(pri->pvts[chanpos], 0);
                                                sig_pri_set_echocanceller(pri->pvts[chanpos], 1);
@@ -3655,7 +3669,7 @@ static void *pri_dchannel(void *vpri)
                                                                default:
                                                                        switch (e->hangup.cause) {
                                                                        case PRI_CAUSE_USER_BUSY:
                                                                default:
                                                                        switch (e->hangup.cause) {
                                                                        case PRI_CAUSE_USER_BUSY:
-                                                                               pri_queue_control(pri->pvts[chanpos], AST_CONTROL_BUSY, pri);
+                                                                               pri_queue_control(pri, chanpos, AST_CONTROL_BUSY);
                                                                                break;
                                                                        case PRI_CAUSE_CALL_REJECTED:
                                                                        case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
                                                                                break;
                                                                        case PRI_CAUSE_CALL_REJECTED:
                                                                        case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
@@ -3663,7 +3677,7 @@ static void *pri_dchannel(void *vpri)
                                                                        case PRI_CAUSE_SWITCH_CONGESTION:
                                                                        case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
                                                                        case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
                                                                        case PRI_CAUSE_SWITCH_CONGESTION:
                                                                        case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
                                                                        case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
-                                                                               pri_queue_control(pri->pvts[chanpos], AST_CONTROL_CONGESTION, pri);
+                                                                               pri_queue_control(pri, chanpos, AST_CONTROL_CONGESTION);
                                                                                break;
                                                                        default:
                                                                                ast_softhangup_nolock(pri->pvts[chanpos]->owner, AST_SOFTHANGUP_DEV);
                                                                                break;
                                                                        default:
                                                                                ast_softhangup_nolock(pri->pvts[chanpos]->owner, AST_SOFTHANGUP_DEV);
@@ -3756,7 +3770,7 @@ static void *pri_dchannel(void *vpri)
                                                        default:
                                                                switch (e->hangup.cause) {
                                                                case PRI_CAUSE_USER_BUSY:
                                                        default:
                                                                switch (e->hangup.cause) {
                                                                case PRI_CAUSE_USER_BUSY:
-                                                                       pri_queue_control(pri->pvts[chanpos], AST_CONTROL_BUSY, pri);
+                                                                       pri_queue_control(pri, chanpos, AST_CONTROL_BUSY);
                                                                        break;
                                                                case PRI_CAUSE_CALL_REJECTED:
                                                                case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
                                                                        break;
                                                                case PRI_CAUSE_CALL_REJECTED:
                                                                case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
@@ -3764,7 +3778,7 @@ static void *pri_dchannel(void *vpri)
                                                                case PRI_CAUSE_SWITCH_CONGESTION:
                                                                case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
                                                                case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
                                                                case PRI_CAUSE_SWITCH_CONGESTION:
                                                                case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
                                                                case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
-                                                                       pri_queue_control(pri->pvts[chanpos], AST_CONTROL_CONGESTION, pri);
+                                                                       pri_queue_control(pri, chanpos, AST_CONTROL_CONGESTION);
                                                                        break;
                                                                default:
                                                                        ast_softhangup_nolock(pri->pvts[chanpos]->owner, AST_SOFTHANGUP_DEV);
                                                                        break;
                                                                default:
                                                                        ast_softhangup_nolock(pri->pvts[chanpos]->owner, AST_SOFTHANGUP_DEV);
@@ -3953,18 +3967,12 @@ static void *pri_dchannel(void *vpri)
                                        switch (e->notify.info) {
                                        case PRI_NOTIFY_REMOTE_HOLD:
                                                if (!pri->discardremoteholdretrieval) {
                                        switch (e->notify.info) {
                                        case PRI_NOTIFY_REMOTE_HOLD:
                                                if (!pri->discardremoteholdretrieval) {
-                                                       struct ast_frame f = { AST_FRAME_CONTROL, };
-
-                                                       f.subclass.integer = AST_CONTROL_HOLD;
-                                                       pri_queue_frame(pri->pvts[chanpos], &f, pri);
+                                                       pri_queue_control(pri, chanpos, AST_CONTROL_HOLD);
                                                }
                                                break;
                                        case PRI_NOTIFY_REMOTE_RETRIEVAL:
                                                if (!pri->discardremoteholdretrieval) {
                                                }
                                                break;
                                        case PRI_NOTIFY_REMOTE_RETRIEVAL:
                                                if (!pri->discardremoteholdretrieval) {
-                                                       struct ast_frame f = { AST_FRAME_CONTROL, };
-
-                                                       f.subclass.integer = AST_CONTROL_UNHOLD;
-                                                       pri_queue_frame(pri->pvts[chanpos], &f, pri);
+                                                       pri_queue_control(pri, chanpos, AST_CONTROL_UNHOLD);
                                                }
                                                break;
                                        }
                                                }
                                                break;
                                        }