diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c index 04105ad596..de2d0f4cad 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 1b40a9f585..92eb19144e 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 e76db86ace..308fa5dc8e 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 148397fc64..0c9a5e1730 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 68ebc5a10a..ebc5ca8587 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 15b4a2a896..73839b1b3d 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);