aboutsummaryrefslogtreecommitdiffstats
path: root/channels
diff options
context:
space:
mode:
Diffstat (limited to 'channels')
-rw-r--r--channels/chan_dahdi.c2
-rw-r--r--channels/sig_analog.c23
-rw-r--r--channels/sig_pri.c14
-rw-r--r--channels/sig_pri.h2
-rw-r--r--channels/sig_ss7.c14
-rw-r--r--channels/sig_ss7.h2
6 files changed, 43 insertions, 14 deletions
diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c
index 04105ad59..de2d0f4ca 100644
--- a/channels/chan_dahdi.c
+++ b/channels/chan_dahdi.c
@@ -3320,6 +3320,7 @@ static struct sig_pri_callback dahdi_pri_callbacks =
.dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
.lock_private = my_lock_private,
.unlock_private = my_unlock_private,
+ .deadlock_avoidance_private = my_deadlock_avoidance_private,
.new_ast_channel = my_new_pri_ast_channel,
.fixup_chans = my_pri_fixup_chans,
.set_alarm = my_set_alarm,
@@ -3483,6 +3484,7 @@ static struct sig_ss7_callback dahdi_ss7_callbacks =
{
.lock_private = my_lock_private,
.unlock_private = my_unlock_private,
+ .deadlock_avoidance_private = my_deadlock_avoidance_private,
.set_echocanceller = my_set_echocanceller,
.set_loopback = my_ss7_set_loopback,
diff --git a/channels/sig_analog.c b/channels/sig_analog.c
index 1b40a9f58..92eb19144 100644
--- a/channels/sig_analog.c
+++ b/channels/sig_analog.c
@@ -518,23 +518,31 @@ static void analog_all_subchannels_hungup(struct analog_pvt *p)
}
}
-#if 0
static void analog_unlock_private(struct analog_pvt *p)
{
if (p->calls->unlock_private) {
p->calls->unlock_private(p->chan_pvt);
}
}
-#endif
-#if 0
static void analog_lock_private(struct analog_pvt *p)
{
if (p->calls->lock_private) {
p->calls->lock_private(p->chan_pvt);
}
}
-#endif
+
+static void analog_deadlock_avoidance_private(struct analog_pvt *p)
+{
+ if (p->calls->deadlock_avoidance_private) {
+ p->calls->deadlock_avoidance_private(p->chan_pvt);
+ } else {
+ /* Fallback to manual avoidance if callback not present. */
+ analog_unlock_private(p);
+ usleep(1);
+ analog_lock_private(p);
+ }
+}
/*!
* \internal
@@ -563,12 +571,7 @@ static void analog_lock_sub_owner(struct analog_pvt *pvt, enum analog_sub sub_id
break;
}
/* We must unlock the private to avoid the possibility of a deadlock */
- if (pvt->calls->deadlock_avoidance_private) {
- pvt->calls->deadlock_avoidance_private(pvt->chan_pvt);
- } else {
- /* Don't use 100% CPU if required callback not present. */
- usleep(1);
- }
+ analog_deadlock_avoidance_private(pvt);
}
}
diff --git a/channels/sig_pri.c b/channels/sig_pri.c
index e76db86ac..308fa5dc8 100644
--- a/channels/sig_pri.c
+++ b/channels/sig_pri.c
@@ -321,6 +321,16 @@ static void sig_pri_lock_private(struct sig_pri_chan *p)
p->calls->lock_private(p->chan_pvt);
}
+static void sig_pri_deadlock_avoidance_private(struct sig_pri_chan *p)
+{
+ if (p->calls->deadlock_avoidance_private) {
+ p->calls->deadlock_avoidance_private(p->chan_pvt);
+ } else {
+ /* Fallback to the old way if callback not present. */
+ PRI_DEADLOCK_AVOIDANCE(p);
+ }
+}
+
static inline int pri_grab(struct sig_pri_chan *p, struct sig_pri_span *pri)
{
int res;
@@ -328,7 +338,7 @@ static inline int pri_grab(struct sig_pri_chan *p, struct sig_pri_span *pri)
do {
res = ast_mutex_trylock(&pri->lock);
if (res) {
- PRI_DEADLOCK_AVOIDANCE(p);
+ sig_pri_deadlock_avoidance_private(p);
}
} while (res);
/* Then break the poll */
@@ -1123,7 +1133,7 @@ static void sig_pri_lock_owner(struct sig_pri_span *pri, int chanpos)
}
/* We must unlock the PRI to avoid the possibility of a deadlock */
ast_mutex_unlock(&pri->lock);
- PRI_DEADLOCK_AVOIDANCE(pri->pvts[chanpos]);
+ sig_pri_deadlock_avoidance_private(pri->pvts[chanpos]);
ast_mutex_lock(&pri->lock);
}
}
diff --git a/channels/sig_pri.h b/channels/sig_pri.h
index 148397fc6..0c9a5e173 100644
--- a/channels/sig_pri.h
+++ b/channels/sig_pri.h
@@ -167,6 +167,8 @@ struct sig_pri_callback {
void (* const unlock_private)(void *pvt);
/* Lock the private in the signalling private structure. ... */
void (* const lock_private)(void *pvt);
+ /* Do deadlock avoidance for the private signaling structure lock. */
+ void (* const deadlock_avoidance_private)(void *pvt);
/* Function which is called back to handle any other DTMF events that are received. Called by analog_handle_event. Why is this
* important to use, instead of just directly using events received before they are passed into the library? Because sometimes,
* (CWCID) the library absorbs DTMF events received. */
diff --git a/channels/sig_ss7.c b/channels/sig_ss7.c
index 68ebc5a10..ebc5ca858 100644
--- a/channels/sig_ss7.c
+++ b/channels/sig_ss7.c
@@ -64,6 +64,16 @@ static void sig_ss7_lock_private(struct sig_ss7_chan *p)
}
}
+static void sig_ss7_deadlock_avoidance_private(struct sig_ss7_chan *p)
+{
+ if (p->calls->deadlock_avoidance_private) {
+ p->calls->deadlock_avoidance_private(p->chan_pvt);
+ } else {
+ /* Fallback to the old way if callback not present. */
+ SIG_SS7_DEADLOCK_AVOIDANCE(p);
+ }
+}
+
void sig_ss7_set_alarm(struct sig_ss7_chan *p, int in_alarm)
{
p->inalarm = in_alarm;
@@ -255,7 +265,7 @@ static void sig_ss7_lock_owner(struct sig_ss7_linkset *ss7, int chanpos)
}
/* We must unlock the SS7 to avoid the possibility of a deadlock */
ast_mutex_unlock(&ss7->lock);
- SIG_SS7_DEADLOCK_AVOIDANCE(ss7->pvts[chanpos]);
+ sig_ss7_deadlock_avoidance_private(ss7->pvts[chanpos]);
ast_mutex_lock(&ss7->lock);
}
}
@@ -1109,7 +1119,7 @@ static inline int ss7_grab(struct sig_ss7_chan *pvt, struct sig_ss7_linkset *ss7
do {
res = ast_mutex_trylock(&ss7->lock);
if (res) {
- SIG_SS7_DEADLOCK_AVOIDANCE(pvt);
+ sig_ss7_deadlock_avoidance_private(pvt);
}
} while (res);
/* Then break the poll */
diff --git a/channels/sig_ss7.h b/channels/sig_ss7.h
index 15b4a2a89..73839b1b3 100644
--- a/channels/sig_ss7.h
+++ b/channels/sig_ss7.h
@@ -105,6 +105,8 @@ struct sig_ss7_callback {
void (* const unlock_private)(void *pvt);
/* Lock the private in the signaling private structure. */
void (* const lock_private)(void *pvt);
+ /* Do deadlock avoidance for the private signaling structure lock. */
+ void (* const deadlock_avoidance_private)(void *pvt);
int (* const set_echocanceller)(void *pvt, int enable);
void (* const set_loopback)(void *pvt, int enable);