[asterisk-commits] murf: branch murf/mtxprof r125137 - in /team/murf/mtxprof: channels/ funcs/ i...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Wed Jun 25 17:46:23 CDT 2008
Author: murf
Date: Wed Jun 25 17:46:22 2008
New Revision: 125137
URL: http://svn.digium.com/view/asterisk?view=rev&rev=125137
Log:
OK, A LOT of debug added to try and understand why the lock in __ast_answer() is taking so long to get. Unfortunately, it's because call to ast_pbx_start() in the handle_request_invite() func takes an avg of 50 million cpu ticks to complete. By the time it returns, the new thread has already started, and __ast_answer is waiting for its parent to release the channel lock. The amount of time that ast_pbx_start() takes would seem to me a limiting factor in how many calls/sec the sip channel driver can accept. If you don't want to see all the ast_log calls concerning locks, then remove them from the macros in lock.h at lines 1714-1723. A lot of blood, sweat, and tears went into showing all the lock calls.
Modified:
team/murf/mtxprof/channels/chan_agent.c
team/murf/mtxprof/channels/chan_dahdi.c
team/murf/mtxprof/channels/chan_iax2.c
team/murf/mtxprof/channels/chan_local.c
team/murf/mtxprof/channels/chan_mgcp.c
team/murf/mtxprof/channels/chan_sip.c
team/murf/mtxprof/channels/console_video.c
team/murf/mtxprof/funcs/func_channel.c
team/murf/mtxprof/funcs/func_global.c
team/murf/mtxprof/include/asterisk/lock.h
team/murf/mtxprof/main/channel.c
team/murf/mtxprof/main/features.c
team/murf/mtxprof/main/pbx.c
team/murf/mtxprof/main/rtp.c
team/murf/mtxprof/main/udptl.c
team/murf/mtxprof/main/utils.c
team/murf/mtxprof/res/res_agi.c
team/murf/mtxprof/res/res_monitor.c
Modified: team/murf/mtxprof/channels/chan_agent.c
URL: http://svn.digium.com/view/asterisk/team/murf/mtxprof/channels/chan_agent.c?view=diff&rev=125137&r1=125136&r2=125137
==============================================================================
--- team/murf/mtxprof/channels/chan_agent.c (original)
+++ team/murf/mtxprof/channels/chan_agent.c Wed Jun 25 17:46:22 2008
@@ -1529,7 +1529,10 @@
if (!soft) {
ast_mutex_lock(&p->lock);
- while (p->owner && ast_channel_trylock(p->owner)) {
+ while (p->owner) {
+ int ret;
+ ast_channel_trylock_assign(p->owner,ret);
+ if (!ret) break;
DEADLOCK_AVOIDANCE(&p->lock);
}
if (p->owner) {
@@ -1537,7 +1540,10 @@
ast_channel_unlock(p->owner);
}
- while (p->chan && ast_channel_trylock(p->chan)) {
+ while (p->chan) {
+ int ret;
+ ast_channel_trylock_assign(p->owner,ret);
+ if (!ret) break;
DEADLOCK_AVOIDANCE(&p->lock);
}
if (p->chan) {
Modified: team/murf/mtxprof/channels/chan_dahdi.c
URL: http://svn.digium.com/view/asterisk/team/murf/mtxprof/channels/chan_dahdi.c?view=diff&rev=125137&r1=125136&r2=125137
==============================================================================
--- team/murf/mtxprof/channels/chan_dahdi.c (original)
+++ team/murf/mtxprof/channels/chan_dahdi.c Wed Jun 25 17:46:22 2008
@@ -966,7 +966,9 @@
#endif
for (;;) {
if (p->subs[a].owner) {
- if (ast_channel_trylock(p->subs[a].owner)) {
+ int ret;
+ ast_channel_trylock_assign(p->subs[a].owner,ret);
+ if (ret) {
DEADLOCK_AVOIDANCE(&p->lock);
} else {
ast_queue_frame(p->subs[a].owner, &ast_null_frame);
@@ -1013,7 +1015,9 @@
#endif
for (;;) {
if (p->owner) {
- if (ast_channel_trylock(p->owner)) {
+ int ret;
+ ast_channel_trylock_assign(p->owner,ret);
+ if (ret) {
DEADLOCK_AVOIDANCE(&p->lock);
} else {
ast_queue_frame(p->owner, f);
@@ -3728,6 +3732,7 @@
struct dahdi_pvt *p0, *p1, *op0, *op1;
struct dahdi_pvt *master = NULL, *slave = NULL;
struct ast_frame *f;
+ int ret;
int inconf = 0;
int nothingok = 1;
int ofd0, ofd1;
@@ -3751,8 +3756,10 @@
return AST_BRIDGE_FAILED_NOWARN;
ast_channel_lock(c0);
- while (ast_channel_trylock(c1)) {
+ ast_channel_trylock_assign(c1,ret);
+ while (ret) {
CHANNEL_DEADLOCK_AVOIDANCE(c0);
+ ast_channel_trylock_assign(c1,ret);
}
p0 = c0->tech_pvt;
@@ -3921,8 +3928,10 @@
and then balking if anything is wrong */
ast_channel_lock(c0);
- while (ast_channel_trylock(c1)) {
+ ast_channel_trylock_assign(c1,ret);
+ while (ret) {
CHANNEL_DEADLOCK_AVOIDANCE(c0);
+ ast_channel_trylock_assign(c1,ret);
}
p0 = c0->tech_pvt;
@@ -4458,9 +4467,11 @@
dahdi_ring_phone(p);
} else if (p->subs[SUB_THREEWAY].owner) {
unsigned int mssinceflash;
+ int lockret;
/* Here we have to retain the lock on both the main channel, the 3-way channel, and
the private structure -- not especially easy or clean */
- while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
+ ast_channel_trylock_assign(p->subs[SUB_THREEWAY].owner,lockret);
+ while (p->subs[SUB_THREEWAY].owner && lockret) {
/* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
DLA_UNLOCK(&p->lock);
CHANNEL_DEADLOCK_AVOIDANCE(ast);
@@ -4472,6 +4483,7 @@
ast_log(LOG_WARNING, "This isn't good...\n");
return NULL;
}
+ ast_channel_trylock_assign(p->subs[SUB_THREEWAY].owner,lockret);
}
if (!p->subs[SUB_THREEWAY].owner) {
ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
@@ -4503,19 +4515,22 @@
} else {
if ((res = attempt_transfer(p)) < 0) {
p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
- if (p->subs[SUB_THREEWAY].owner)
+ if (p->subs[SUB_THREEWAY].owner) {
ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
+ }
} else if (res) {
/* Don't actually hang up at this point */
- if (p->subs[SUB_THREEWAY].owner)
+ if (p->subs[SUB_THREEWAY].owner) {
ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
+ }
break;
}
}
} else {
p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
- if (p->subs[SUB_THREEWAY].owner)
+ if (p->subs[SUB_THREEWAY].owner) {
ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
+ }
}
} else {
ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
@@ -10258,9 +10273,14 @@
do {
redo = 0;
for (x = 0; x < 3; x++) {
- while (p->subs[x].owner && ast_channel_trylock(p->subs[x].owner)) {
+ int lockret;
+ if (!p->subs[x].owner)
+ continue;
+ ast_channel_trylock_assign(p->subs[x].owner,lockret);
+ while (p->subs[x].owner && lockret) {
redo++;
DEADLOCK_AVOIDANCE(&p->lock);
+ ast_channel_trylock_assign(p->subs[x].owner,lockret);
}
if (p->subs[x].owner) {
ast_queue_hangup_with_cause(p->subs[x].owner, AST_CAUSE_PRE_EMPTED);
Modified: team/murf/mtxprof/channels/chan_iax2.c
URL: http://svn.digium.com/view/asterisk/team/murf/mtxprof/channels/chan_iax2.c?view=diff&rev=125137&r1=125136&r2=125137
==============================================================================
--- team/murf/mtxprof/channels/chan_iax2.c (original)
+++ team/murf/mtxprof/channels/chan_iax2.c Wed Jun 25 17:46:22 2008
@@ -1772,7 +1772,9 @@
{
for (;;) {
if (iaxs[callno] && iaxs[callno]->owner) {
- if (ast_channel_trylock(iaxs[callno]->owner)) {
+ int lockret;
+ ast_channel_trylock_assign(iaxs[callno]->owner,lockret);
+ if (lockret) {
/* Avoid deadlock by pausing and trying again */
DEADLOCK_AVOIDANCE(&iaxsl[callno]);
} else {
@@ -1803,7 +1805,9 @@
{
for (;;) {
if (iaxs[callno] && iaxs[callno]->owner) {
- if (ast_channel_trylock(iaxs[callno]->owner)) {
+ int lockret;
+ ast_channel_trylock_assign(iaxs[callno]->owner,lockret);
+ if (lockret) {
/* Avoid deadlock by pausing and trying again */
DEADLOCK_AVOIDANCE(&iaxsl[callno]);
} else {
@@ -1835,7 +1839,9 @@
{
for (;;) {
if (iaxs[callno] && iaxs[callno]->owner) {
- if (ast_channel_trylock(iaxs[callno]->owner)) {
+ int lockret;
+ ast_channel_trylock_assign(iaxs[callno]->owner,lockret);
+ if (lockret) {
/* Avoid deadlock by pausing and trying again */
DEADLOCK_AVOIDANCE(&iaxsl[callno]);
} else {
@@ -2246,7 +2252,9 @@
owner = pvt ? pvt->owner : NULL;
if (owner) {
- if (ast_channel_trylock(owner)) {
+ int lockret;
+ ast_channel_trylock_assign(owner,lockret);
+ if (lockret) {
ast_debug(3, "Avoiding IAX destroy deadlock\n");
DEADLOCK_AVOIDANCE(&iaxsl[callno]);
goto retry;
@@ -8299,8 +8307,10 @@
ast_debug(1, "Ooh, voice format changed to %d\n", f.subclass);
if (iaxs[fr->callno]->owner) {
int orignative;
+ int lockret;
retryowner:
- if (ast_channel_trylock(iaxs[fr->callno]->owner)) {
+ ast_channel_trylock_assign(iaxs[fr->callno]->owner,lockret);
+ if (lockret) {
DEADLOCK_AVOIDANCE(&iaxsl[fr->callno]);
if (iaxs[fr->callno] && iaxs[fr->callno]->owner) goto retryowner;
}
@@ -8738,11 +8748,13 @@
} else {
ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED);
if (iaxs[fr->callno]->owner) {
+ int lockret;
/* Switch us to use a compatible format */
iaxs[fr->callno]->owner->nativeformats = iaxs[fr->callno]->peerformat;
ast_verb(3, "Format for call is %s\n", ast_getformatname(iaxs[fr->callno]->owner->nativeformats));
retryowner2:
- if (ast_channel_trylock(iaxs[fr->callno]->owner)) {
+ ast_channel_trylock_assign(iaxs[fr->callno]->owner,lockret);
+ if (lockret) {
DEADLOCK_AVOIDANCE(&iaxsl[fr->callno]);
if (iaxs[fr->callno] && iaxs[fr->callno]->owner) goto retryowner2;
}
Modified: team/murf/mtxprof/channels/chan_local.c
URL: http://svn.digium.com/view/asterisk/team/murf/mtxprof/channels/chan_local.c?view=diff&rev=125137&r1=125136&r2=125137
==============================================================================
--- team/murf/mtxprof/channels/chan_local.c (original)
+++ team/murf/mtxprof/channels/chan_local.c Wed Jun 25 17:46:22 2008
@@ -199,7 +199,8 @@
struct ast_channel *us, int us_locked)
{
struct ast_channel *other = NULL;
-
+ int lockret;
+
/* Recalculate outbound channel */
other = isoutbound ? p->owner : p->chan;
@@ -218,7 +219,8 @@
}
/* Ensure that we have both channels locked */
- while (other && ast_channel_trylock(other)) {
+ ast_channel_trylock_assign(other,lockret);
+ while (other && lockret) {
DLA_UNLOCK(&p->lock);
if (us && us_locked) {
CHANNEL_DEADLOCK_AVOIDANCE(us);
@@ -227,6 +229,7 @@
}
DLA_LOCK(&p->lock);
other = isoutbound ? p->owner : p->chan;
+ ast_channel_trylock_assign(other,lockret);
}
if (other) {
@@ -273,13 +276,16 @@
outbound channel during the masquerade)
*/
if (isoutbound && p->chan->_bridge /* Not ast_bridged_channel! Only go one step! */ && AST_LIST_EMPTY(&p->owner->readq)) {
+ int lockret;
/* Masquerade bridged channel into owner */
/* Lock everything we need, one by one, and give up if
we can't get everything. Remember, we'll get another
chance in just a little bit */
- if (!ast_channel_trylock(p->chan->_bridge)) {
+ ast_channel_trylock_assign(p->chan->_bridge,lockret);
+ if (!lockret) {
if (!ast_check_hangup(p->chan->_bridge)) {
- if (!ast_channel_trylock(p->owner)) {
+ ast_channel_trylock_assign(p->owner,lockret);
+ if (!lockret) {
if (!ast_check_hangup(p->owner)) {
if(p->owner->monitor && !p->chan->_bridge->monitor) {
/* If a local channel is being monitored, we don't want a masquerade
@@ -549,8 +555,10 @@
if (isoutbound) {
const char *status = pbx_builtin_getvar_helper(p->chan, "DIALSTATUS");
if ((status) && (p->owner)) {
+ int lockret;
/* Deadlock avoidance */
- while (p->owner && ast_channel_trylock(p->owner)) {
+ ast_channel_trylock_assign(p->owner,lockret);
+ while (p->owner && lockret) {
ast_mutex_unlock(&p->lock);
if (ast) {
ast_channel_unlock(ast);
@@ -560,6 +568,7 @@
ast_channel_lock(ast);
}
ast_mutex_lock(&p->lock);
+ ast_channel_trylock_assign(p->owner,lockret);
}
if (p->owner) {
pbx_builtin_setvar_helper(p->owner, "CHANLOCALSTATUS", status);
Modified: team/murf/mtxprof/channels/chan_mgcp.c
URL: http://svn.digium.com/view/asterisk/team/murf/mtxprof/channels/chan_mgcp.c?view=diff&rev=125137&r1=125136&r2=125137
==============================================================================
--- team/murf/mtxprof/channels/chan_mgcp.c (original)
+++ team/murf/mtxprof/channels/chan_mgcp.c Wed Jun 25 17:46:22 2008
@@ -591,7 +591,9 @@
{
for(;;) {
if (sub->owner) {
- if (!ast_channel_trylock(sub->owner)) {
+ int lockret;
+ ast_channel_trylock_assign(sub->owner,lockret);
+ if (!lockret) {
ast_queue_frame(sub->owner, f);
ast_channel_unlock(sub->owner);
break;
@@ -607,7 +609,9 @@
{
for(;;) {
if (sub->owner) {
- if (!ast_channel_trylock(sub->owner)) {
+ int lockret;
+ ast_channel_trylock_assign(sub->owner,lockret);
+ if (!lockret) {
ast_queue_hangup(sub->owner);
ast_channel_unlock(sub->owner);
break;
Modified: team/murf/mtxprof/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/murf/mtxprof/channels/chan_sip.c?view=diff&rev=125137&r1=125136&r2=125137
==============================================================================
--- team/murf/mtxprof/channels/chan_sip.c (original)
+++ team/murf/mtxprof/channels/chan_sip.c Wed Jun 25 17:46:22 2008
@@ -2449,12 +2449,14 @@
/* Unlink us from the owner (channel) if we have one */
if (dialog->owner) {
- if (lockowner)
+ if (lockowner) {
ast_channel_lock(dialog->owner);
+ }
ast_debug(1, "Detaching from channel %s\n", dialog->owner->name);
dialog->owner->tech_pvt = dialog_unref(dialog->owner->tech_pvt, "resetting channel dialog ptr in unlink_all");
- if (lockowner)
+ if (lockowner) {
ast_channel_unlock(dialog->owner);
+ }
}
if (dialog->registry) {
if (dialog->registry->call == dialog)
@@ -2959,12 +2961,18 @@
pkt->retransid = -1;
if (pkt->is_fatal) {
- while(pkt->owner->owner && ast_channel_trylock(pkt->owner->owner)) {
- sip_pvt_unlock(pkt->owner); /* SIP_PVT, not channel */
- usleep(1);
- sip_pvt_lock(pkt->owner);
- }
-
+ int lockret;
+ if (pkt->owner->owner)
+ {
+ ast_channel_trylock_assign(pkt->owner->owner,lockret);
+ while(pkt->owner->owner && lockret) {
+ sip_pvt_unlock(pkt->owner); /* SIP_PVT, not channel */
+ usleep(1);
+ sip_pvt_lock(pkt->owner);
+ ast_channel_trylock_assign(pkt->owner->owner,lockret);
+ }
+ }
+
if (pkt->owner->owner && !pkt->owner->owner->hangupcause)
pkt->owner->owner->hangupcause = AST_CAUSE_NO_USER_RESPONSE;
@@ -2987,8 +2995,9 @@
if (pkt->method == SIP_BYE) {
/* We're not getting answers on SIP BYE's. Tear down the call anyway. */
- if (pkt->owner->owner)
+ if (pkt->owner->owner){
ast_channel_unlock(pkt->owner->owner);
+ }
append_history(pkt->owner, "ByeFailure", "Remote peer doesn't respond to bye. Destroying call anyway.");
pkt->owner->needdestroy = 1;
}
@@ -4424,8 +4433,10 @@
sip_pvt_lock(p);
p->initid = -1; /* event gone, will not be rescheduled */
if (p->owner) {
+ int lockret;
/* XXX fails on possible deadlock */
- if (!ast_channel_trylock(p->owner)) {
+ ast_channel_trylock_assign(p->owner,lockret);
+ if (!lockret) {
append_history(p, "Cong", "Auto-congesting (timer)");
ast_queue_control(p->owner, AST_CONTROL_CONGESTION);
ast_channel_unlock(p->owner);
@@ -4568,15 +4579,17 @@
/* Unlink us from the owner if we have one */
if (p->owner) {
- if (lockowner)
+ if (lockowner) {
ast_channel_lock(p->owner);
+ }
if (option_debug)
ast_log(LOG_DEBUG, "Detaching from %s\n", p->owner->name);
p->owner->tech_pvt = NULL;
/* Make sure that the channel knows its backend is going away */
p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
- if (lockowner)
+ if (lockowner) {
ast_channel_unlock(p->owner);
+ }
/* Give the channel a chance to react before deallocation */
usleep(1);
}
@@ -9319,7 +9332,7 @@
while ((individual_hint = strsep(&hint2, "&"))) {
hint_count++;
-
+ ast_log(LOG_NOTICE,"Calling ast_device_state\n");
if (ast_device_state(individual_hint) == AST_DEVICE_UNAVAILABLE)
unavailable_count++;
}
@@ -11274,6 +11287,7 @@
sip_pvt_ptr = ao2_t_find(dialogs, &tmp_dialog, OBJ_POINTER, "ao2_find of dialog in dialogs table");
if (sip_pvt_ptr) {
char *ourtag = sip_pvt_ptr->tag;
+ int lockret;
/* Go ahead and lock it (and its owner) before returning */
sip_pvt_lock(sip_pvt_ptr);
@@ -11291,10 +11305,14 @@
sip_pvt_ptr->theirtag, sip_pvt_ptr->tag);
/* deadlock avoidance... */
- while (sip_pvt_ptr->owner && ast_channel_trylock(sip_pvt_ptr->owner)) {
- sip_pvt_unlock(sip_pvt_ptr);
- usleep(1);
- sip_pvt_lock(sip_pvt_ptr);
+ if (sip_pvt_ptr->owner) {
+ ast_channel_trylock_assign(sip_pvt_ptr->owner,lockret);
+ while (sip_pvt_ptr->owner && lockret) {
+ sip_pvt_unlock(sip_pvt_ptr);
+ usleep(1);
+ sip_pvt_lock(sip_pvt_ptr);
+ ast_channel_trylock_assign(sip_pvt_ptr->owner,lockret);
+ }
}
}
@@ -16880,6 +16898,7 @@
struct ast_channel *transferee, *transferer;
/* Chan2m: The transferer, chan1m: The transferee */
pthread_t th;
+ int lockret;
transferee = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan1->accountcode, chan1->exten, chan1->context, chan1->amaflags, "Parking/%s", chan1->name);
transferer = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan2->exten, chan2->context, chan2->amaflags, "SIPPeer/%s", chan2->name);
@@ -16917,11 +16936,13 @@
/* Prepare for taking over the channel. Go ahead and grab this channel
* lock here to avoid a deadlock with callbacks into the channel driver
* that hold the channel lock and want the pvt lock. */
- while (ast_channel_trylock(chan2)) {
+ ast_channel_trylock_assign(chan2,lockret);
+ while (lockret) {
struct sip_pvt *pvt = chan2->tech_pvt;
sip_pvt_unlock(pvt);
usleep(1);
sip_pvt_lock(pvt);
+ ast_channel_trylock_assign(chan2,lockret);
}
ast_channel_masquerade(transferer, chan2);
ast_channel_unlock(chan2);
@@ -17338,8 +17359,9 @@
ast_quiet_chan(targetcall);
ast_debug(4, "Invite/Replaces: preparing to masquerade %s into %s\n", c->name, replacecall->name);
/* Unlock clone, but not original (replacecall) */
- if (!oneleggedreplace)
+ if (!oneleggedreplace) {
ast_channel_unlock(c);
+ }
/* Unlock PVT */
sip_pvt_unlock(p->refer->refer_call);
@@ -17370,8 +17392,9 @@
ast_log(LOG_WARNING, "Invite/Replace: Could not read frame from RING channel \n");
}
c->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
- if (!oneleggedreplace)
+ if (!oneleggedreplace) {
ast_channel_unlock(replacecall);
+ }
} else { /* Bridged call, UP channel */
if ((f = ast_read(replacecall))) { /* Force the masq to happen */
/* Masq ok */
@@ -17899,9 +17922,29 @@
p->invitestate = INV_PROCEEDING;
ast_setstate(c, AST_STATE_RING);
if (strcmp(p->exten, ast_pickup_ext())) { /* Call to extension -start pbx on this call */
+ static int pbx_mark = -1;
enum ast_pbx_result res;
-
+ struct timeval start9, end9;
+ static int totaltime = 0;
+ static int numtimes = 0;
+ int timediff;
+ uint64_t st1;
+
+ if (pbx_mark == -1) {
+ pbx_mark = ast_add_profile("pbx_start_time", 0);
+ }
+
+ ast_log(LOG_NOTICE,"about to start PBX\n");
+ start9 = ast_tvnow();
+ st1 = ast_mark2();
res = ast_pbx_start(c);
+ ast_mark3(pbx_mark, st1);
+ end9 = ast_tvnow();
+ timediff = ast_tvdiff_us(end9, start9);
+ totaltime += timediff;
+ numtimes++;
+
+ ast_log(LOG_NOTICE,"PBX is started -- took %d microseconds, avg=%d usec (%d times)\n", timediff, totaltime/numtimes, numtimes);
switch(res) {
case AST_PBX_FAILED:
@@ -18166,8 +18209,9 @@
/* Failed transfer */
transmit_notify_with_sipfrag(transferer, seqno, "486 Busy Here", TRUE);
append_history(transferer, "Xfer", "Refer failed");
- if (targetcall_pvt->owner)
+ if (targetcall_pvt->owner) {
ast_channel_unlock(targetcall_pvt->owner);
+ }
/* Right now, we have to hangup, sorry. Bridge is destroyed */
if (res != -2)
ast_hangup(transferer->owner);
@@ -19485,6 +19529,7 @@
/* Process request, with netlock held, and with usual deadlock avoidance */
for (lockretry = 100; lockretry > 0; lockretry--) {
+ int lockret;
ast_mutex_lock(&netlock);
/* Find the active SIP dialog or create a new one */
@@ -19499,7 +19544,10 @@
/* Go ahead and lock the owner if it has one -- we may need it */
/* becaues this is deadlock-prone, we need to try and unlock if failed */
- if (!p->owner || !ast_channel_trylock(p->owner))
+ if (p->owner) {
+ ast_channel_trylock_assign(p->owner,lockret);
+ }
+ if (!p->owner || !lockret)
break; /* locking succeeded */
ast_debug(1, "Failed to grab owner channel lock, trying again. (SIP call %s)\n", p->callid);
sip_pvt_unlock(p);
@@ -19535,8 +19583,9 @@
if (recount)
ast_update_use_count();
- if (p->owner && !nounlock)
+ if (p->owner && !nounlock) {
ast_channel_unlock(p->owner);
+ }
sip_pvt_unlock(p);
ast_mutex_unlock(&netlock);
ao2_t_ref(p, -1, "throw away dialog ptr from find_call at end of routine"); /* p is gone after the return */
@@ -19772,10 +19821,15 @@
(t > dialog->lastrtprx + ast_rtp_get_rtpholdtimeout(dialog->rtp)))) {
/* Needs a hangup */
if (ast_rtp_get_rtptimeout(dialog->rtp)) {
- while (dialog->owner && ast_channel_trylock(dialog->owner)) {
+ int lockret;
+ if (dialog->owner) {
+ ast_channel_trylock_assign(dialog->owner,lockret);
+ }
+ while (dialog->owner && lockret) {
sip_pvt_unlock(dialog);
usleep(1);
sip_pvt_lock(dialog);
+ ast_channel_trylock_assign(dialog->owner,lockret);
}
ast_log(LOG_NOTICE, "Disconnecting call '%s' for lack of RTP activity in %ld seconds\n",
dialog->owner->name, (long) (t - dialog->lastrtprx));
@@ -19988,17 +20042,22 @@
} else {
p->stimer->st_expirys++;
if (p->stimer->st_expirys >= 2) {
+ int lockret;
ast_log(LOG_WARNING, "Session-Timer expired - %s\n", p->callid);
stop_session_timer(p);
- while (p->owner && ast_channel_trylock(p->owner)) {
+ if (p->owner) {
+ ast_channel_trylock_assign(p->owner,lockret);
+ }
+ while (p->owner && lockret) {
sip_pvt_unlock(p);
usleep(1);
sip_pvt_lock(p);
- }
-
- ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_DEV);
- ast_channel_unlock(p->owner);
+ ast_channel_trylock_assign(p->owner,lockret);
+ }
+
+ ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_DEV);
+ ast_channel_unlock(p->owner);
}
}
return 1;
Modified: team/murf/mtxprof/channels/console_video.c
URL: http://svn.digium.com/view/asterisk/team/murf/mtxprof/channels/console_video.c?view=diff&rev=125137&r1=125136&r2=125137
==============================================================================
--- team/murf/mtxprof/channels/console_video.c (original)
+++ team/murf/mtxprof/channels/console_video.c Wed Jun 25 17:46:22 2008
@@ -454,8 +454,9 @@
ast_channel_unlock(env->owner);
usleep(t);
t = 1000000;
- if (env->owner)
+ if (env->owner) {
ast_channel_lock(env->owner);
+ }
}
}
env->owner = NULL; /* this is unconditional */
Modified: team/murf/mtxprof/funcs/func_channel.c
URL: http://svn.digium.com/view/asterisk/team/murf/mtxprof/funcs/func_channel.c?view=diff&rev=125137&r1=125136&r2=125137
==============================================================================
--- team/murf/mtxprof/funcs/func_channel.c (original)
+++ team/murf/mtxprof/funcs/func_channel.c Wed Jun 25 17:46:22 2008
@@ -263,7 +263,7 @@
}
}
- for (c = ast_channel_walk_locked(NULL); c; ast_channel_unlock(c), c = ast_channel_walk_locked(c)) {
+ for (c = ast_channel_walk_locked(NULL); c; ast_channel_unlock_comma(c), c = ast_channel_walk_locked(c)) {
if (ast_strlen_zero(data) || regexec(&re, c->name, 0, NULL, 0) == 0) {
size_t namelen = strlen(c->name);
if (buflen + namelen + (ast_strlen_zero(buf) ? 0 : 1) + 1 < maxlen) {
Modified: team/murf/mtxprof/funcs/func_global.c
URL: http://svn.digium.com/view/asterisk/team/murf/mtxprof/funcs/func_global.c?view=diff&rev=125137&r1=125136&r2=125137
==============================================================================
--- team/murf/mtxprof/funcs/func_global.c (original)
+++ team/murf/mtxprof/funcs/func_global.c Wed Jun 25 17:46:22 2008
@@ -106,8 +106,9 @@
ast_log(LOG_ERROR, "Channel '%s' not found! Variable '%s' will be blank.\n", args.chan, args.var);
return -1;
}
- } else
+ } else {
ast_channel_lock(chan);
+ }
if (!(varstore = ast_channel_datastore_find(chan, &shared_variable_info, NULL))) {
ast_channel_unlock(chan);
@@ -154,8 +155,9 @@
ast_log(LOG_ERROR, "Channel '%s' not found! Variable '%s' not set to '%s'.\n", args.chan, args.var, value);
return -1;
}
- } else
+ } else {
ast_channel_lock(chan);
+ }
if (!(varstore = ast_channel_datastore_find(chan, &shared_variable_info, NULL))) {
if (!(varstore = ast_channel_datastore_alloc(&shared_variable_info, NULL))) {
Modified: team/murf/mtxprof/include/asterisk/lock.h
URL: http://svn.digium.com/view/asterisk/team/murf/mtxprof/include/asterisk/lock.h?view=diff&rev=125137&r1=125136&r2=125137
==============================================================================
--- team/murf/mtxprof/include/asterisk/lock.h (original)
+++ team/murf/mtxprof/include/asterisk/lock.h Wed Jun 25 17:46:22 2008
@@ -59,14 +59,14 @@
* non-blocking calls.
*/
#ifndef HAVE_MTX_PROFILE
-#define __MTX_PROF(a, file, func, lineno, start, mtx_prof) return pthread_mutex_lock((a))
+#define __MTX_PROF(a, file, func, lineno, start, mtx_prof, lockstr) return pthread_mutex_lock((a))
#else
/* make the MTX_PROF thread-safe (localize the start time, use fetchadd to add in the wait time, and bump the event count) */
-#define __MTX_PROF(a, file, func, lineno, start, mtx_prof) do { \
+#define __MTX_PROF(a, file, func, lineno, start, mtx_prof, lockstr) do { \
int i; \
if (*(mtx_prof) == -1) { \
char nbuf[512]; \
- snprintf(nbuf, sizeof(nbuf), "%s__%s__%d", file, func, lineno); \
+ snprintf(nbuf, sizeof(nbuf), "%s__%s__%d__%s", file, func, lineno, lockstr); \
*(mtx_prof) = ast_add_profile(nbuf, 0); \
} \
*(start) = ast_mark2(); \
@@ -1476,12 +1476,12 @@
{
return pthread_mutex_destroy(pmutex);
}
-#define ast_mutex_lock(x) {int start; static int mutprof=-1; ast_mutex_lock2((x), __FILE__, __FUNCTION__, __LINE__, &start, &mutprof);}
-#define ast_mutex_lock_assign(x,retval) {int start; static int mutprof=-1; retval = ast_mutex_lock2((x), __FILE__, __FUNCTION__, __LINE__, &start, &mutprof);}
+#define ast_mutex_lock(x) {int start; static int mutprof=-1; ast_mutex_lock2((x), __FILE__, __FUNCTION__, __LINE__, &start, &mutprof, #x);}
+#define ast_mutex_lock_assign(x,retval) {int start; static int mutprof=-1; retval = ast_mutex_lock2((x), __FILE__, __FUNCTION__, __LINE__, &start, &mutprof, #x);}
-static inline int ast_mutex_lock2(ast_mutex_t *pmutex, char *file, const char *func, int lineno, int *start, int *mutprof)
-{
- __MTX_PROF(pmutex, file, func, lineno, start, mutprof);
+static inline int ast_mutex_lock2(ast_mutex_t *pmutex, char *file, const char *func, int lineno, int *start, int *mutprof, char *lockstr)
+{
+ __MTX_PROF(pmutex, file, func, lineno, start, mutprof, lockstr);
}
static inline int ast_mutex_trylock(ast_mutex_t *pmutex)
@@ -1749,13 +1749,16 @@
#ifndef DEBUG_CHANNEL_LOCKS
/*! \brief Lock a channel. If DEBUG_CHANNEL_LOCKS is defined
in the Makefile, print relevant output for debugging */
-#define ast_channel_lock(x) ast_mutex_lock(&x->lock_dont_use)
+#define ast_channel_lock(x) ast_log(LOG_NOTICE,"LockChan %s\n", x->name); ast_mutex_lock(&x->lock_dont_use); \
+ ast_log(LOG_NOTICE,"LockChan %s OBTAINED\n", x->name);
/*! \brief Unlock a channel. If DEBUG_CHANNEL_LOCKS is defined
in the Makefile, print relevant output for debugging */
-#define ast_channel_unlock(x) ast_mutex_unlock(&x->lock_dont_use)
+#define ast_channel_unlock(x) ast_log(LOG_NOTICE,"UnLockChan %s\n", x->name); ast_mutex_unlock(&x->lock_dont_use)
+#define ast_channel_unlock_comma(x) ast_log(LOG_NOTICE,"UnLockChan %s\n", x->name), ast_mutex_unlock(&x->lock_dont_use)
/*! \brief Try locking a channel. If DEBUG_CHANNEL_LOCKS is defined
in the Makefile, print relevant output for debugging */
-#define ast_channel_trylock(x) ast_mutex_trylock(&x->lock_dont_use)
+#define ast_channel_trylock(x) ast_log(LOG_NOTICE,"TryChan %s\n", x->name); ast_mutex_trylock(&x->lock_dont_use)
+#define ast_channel_trylock_assign(x, var) ast_log(LOG_NOTICE,"TryChan %s\n", x->name); var = ast_mutex_trylock(&x->lock_dont_use)
#else
#define ast_channel_lock(a) __ast_channel_lock(a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
Modified: team/murf/mtxprof/main/channel.c
URL: http://svn.digium.com/view/asterisk/team/murf/mtxprof/main/channel.c?view=diff&rev=125137&r1=125136&r2=125137
==============================================================================
--- team/murf/mtxprof/main/channel.c (original)
+++ team/murf/mtxprof/main/channel.c Wed Jun 25 17:46:22 2008
@@ -1013,8 +1013,10 @@
int ast_queue_hangup(struct ast_channel *chan)
{
struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_HANGUP };
+ int lockret;
/* Yeah, let's not change a lock-critical value without locking */
- if (!ast_channel_trylock(chan)) {
+ ast_channel_trylock_assign(chan,lockret);
+ if (!lockret) {
chan->_softhangup |= AST_SOFTHANGUP_DEV;
ast_channel_unlock(chan);
}
@@ -1025,12 +1027,14 @@
int ast_queue_hangup_with_cause(struct ast_channel *chan, int cause)
{
struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_HANGUP };
+ int lockret;
if (cause >= 0)
f.data.uint32 = cause;
/* Yeah, let's not change a lock-critical value without locking */
- if (!ast_channel_trylock(chan)) {
+ ast_channel_trylock_assign(chan,lockret);
+ if (!lockret) {
chan->_softhangup |= AST_SOFTHANGUP_DEV;
if (cause < 0)
f.data.uint32 = chan->hangupcause;
@@ -1113,6 +1117,7 @@
{
const char *msg = prev ? "deadlock" : "initial deadlock";
int retries;
+ int lockret;
struct ast_channel *c;
const struct ast_channel *_prev = prev;
@@ -1154,7 +1159,12 @@
}
/* exit if chan not found or mutex acquired successfully */
/* this is slightly unsafe, as we _should_ hold the lock to access c->name */
- done = c == NULL || ast_channel_trylock(c) == 0;
+ if (c) {
+ ast_log(LOG_NOTICE,"prev=%p; name=%s, len=%d; context=%s; exten=%s\n", prev, name, namelen, context, exten);
+ ast_channel_trylock_assign(c,lockret);
+ }
+
+ done = c == NULL || lockret == 0;
if (!done) {
ast_debug(1, "Avoiding %s for channel '%p'\n", msg, c);
if (retries == 199) {
@@ -1680,7 +1690,18 @@
{
int res = 0;
- ast_channel_lock(chan);
+#ifdef DEBUG_THREADS
+
+ static int callcount = 0;
+ if (!((callcount++)%200)) {
+ ast_log(LOG_ERROR,"callcount is %d, channel is %s (%p)\n", callcount, chan->name, chan);
+
+ log_show_lock(&chan->lock_dont_use);
+ }
+
+#endif
+
+ ast_channel_lock(chan); /* in sip runs, this lock eats up a tremendous amount of time */
/* You can't answer an outbound call */
if (ast_test_flag(chan, AST_FLAG_OUTGOING)) {
@@ -1838,7 +1859,7 @@
/* Perform any pending masquerades */
for (x = 0; x < n; x++) {
- ast_channel_lock(c[x]);
+ ast_channel_lock(c[x]); /* this eats up a tremendous amount of time */
if (c[x]->masq && ast_do_masquerade(c[x])) {
ast_log(LOG_WARNING, "Masquerade failed\n");
*ms = -1;
@@ -2341,15 +2362,18 @@
int blah;
int prestate;
int count = 0, cause = 0;
+ int lockret;
/* this function is very long so make sure there is only one return
* point at the end (there are only two exceptions to this).
*/
- while(ast_channel_trylock(chan)) {
+ ast_channel_trylock_assign(chan,lockret);
+ while(lockret) {
if(count++ > 10)
/*cannot goto done since the channel is not locked*/
return &ast_null_frame;
usleep(1);
+ ast_channel_trylock_assign(chan,lockret);
}
if (chan->masq) {
@@ -2989,15 +3013,18 @@
int res = -1;
struct ast_frame *f = NULL, *f2 = NULL;
int count = 0;
+ int lockret;
/*Deadlock avoidance*/
- while(ast_channel_trylock(chan)) {
+ ast_channel_trylock_assign(chan,lockret);
+ while(lockret) {
/*cannot goto done since the channel is not locked*/
if(count++ > 10) {
ast_debug(1, "Deadlock avoided for write to channel '%s'\n", chan->name);
return 0;
}
usleep(1);
+ ast_channel_trylock_assign(chan,lockret);
}
/* Stop if we're a zombie or need a soft hangup */
if (ast_test_flag(chan, AST_FLAG_ZOMBIE) || ast_check_hangup(chan))
@@ -3636,6 +3663,7 @@
int ast_channel_masquerade(struct ast_channel *original, struct ast_channel *clone)
{
int res = -1;
+ int lockret;
struct ast_channel *final_orig, *final_clone, *base;
retrymasq:
@@ -3643,10 +3671,12 @@
final_clone = clone;
ast_channel_lock(original);
- while (ast_channel_trylock(clone)) {
+ ast_channel_trylock_assign(clone,lockret);
+ while (lockret) {
ast_channel_unlock(original);
usleep(1);
ast_channel_lock(original);
+ ast_channel_trylock_assign(clone,lockret);
}
/* each of these channels may be sitting behind a channel proxy (i.e. chan_agent)
@@ -3665,12 +3695,14 @@
/* Lots and lots of deadlock avoidance. The main one we're competing with
* is ast_write(), which locks channels recursively, when working with a
* proxy channel. */
- if (ast_channel_trylock(final_orig)) {
+ ast_channel_trylock_assign(final_orig,lockret);
+ if (lockret) {
ast_channel_unlock(clone);
ast_channel_unlock(original);
goto retrymasq;
}
- if (ast_channel_trylock(final_clone)) {
+ ast_channel_trylock_assign(final_clone,lockret);
+ if (lockret) {
ast_channel_unlock(final_orig);
ast_channel_unlock(clone);
ast_channel_unlock(original);
Modified: team/murf/mtxprof/main/features.c
URL: http://svn.digium.com/view/asterisk/team/murf/mtxprof/main/features.c?view=diff&rev=125137&r1=125136&r2=125137
==============================================================================
--- team/murf/mtxprof/main/features.c (original)
+++ team/murf/mtxprof/main/features.c Wed Jun 25 17:46:22 2008
@@ -3460,10 +3460,12 @@
if (!ast_strlen_zero(channela) && !ast_strlen_zero(channelb)) {
chana = ast_get_channel_by_name_prefix_locked(channela, strlen(channela));
chanb = ast_get_channel_by_name_prefix_locked(channelb, strlen(channelb));
- if (chana)
+ if (chana) {
ast_channel_unlock(chana);
- if (chanb)
+ }
+ if (chanb) {
ast_channel_unlock(chanb);
+ }
/* send errors if any of the channels could not be found/locked */
if (!chana) {
Modified: team/murf/mtxprof/main/pbx.c
URL: http://svn.digium.com/view/asterisk/team/murf/mtxprof/main/pbx.c?view=diff&rev=125137&r1=125136&r2=125137
==============================================================================
--- team/murf/mtxprof/main/pbx.c (original)
+++ team/murf/mtxprof/main/pbx.c Wed Jun 25 17:46:22 2008
@@ -2345,8 +2345,9 @@
*ret = substring(*ret, offset, length, workspace, workspacelen);
}
- if (c)
+ if (c) {
ast_channel_unlock(c);
+ }
}
static void exception_store_free(void *data)
@@ -6823,8 +6824,9 @@
chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
if (channel) {
*channel = chan;
- if (chan)
+ if (chan) {
ast_channel_lock(chan);
+ }
}
if (chan) {
if (chan->_state == AST_STATE_UP) {
@@ -6832,8 +6834,9 @@
ast_verb(4, "Channel %s was answered.\n", chan->name);
if (sync > 1) {
- if (channel)
+ if (channel) {
ast_channel_unlock(chan);
+ }
if (ast_pbx_run(chan)) {
ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
if (channel)
@@ -6913,8 +6916,9 @@
chan = ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name);
if (channel) {
*channel = chan;
- if (chan)
+ if (chan) {
ast_channel_lock(chan);
+ }
}
if (!chan) {
ast_free(as);
@@ -7016,17 +7020,20 @@
ast_copy_string(tmp->data, appdata, sizeof(tmp->data));
tmp->chan = chan;
if (sync > 1) {
- if (locked_channel)
+ if (locked_channel) {
ast_channel_unlock(chan);
+ }
ast_pbx_run_app(tmp);
} else {
- if (locked_channel)
+ if (locked_channel) {
ast_channel_lock(chan);
+ }
if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) {
ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno));
ast_free(tmp);
- if (locked_channel)
+ if (locked_channel) {
ast_channel_unlock(chan);
+ }
ast_hangup(chan);
res = -1;
} else {
@@ -7079,13 +7086,15 @@
if (account)
ast_cdr_setaccount(chan, account);
/* Start a new thread, and get something handling this channel. */
- if (locked_channel)
+ if (locked_channel) {
ast_channel_lock(chan);
+ }
if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
ast_log(LOG_WARNING, "Failed to start async wait\n");
ast_free(as);
- if (locked_channel)
+ if (locked_channel) {
ast_channel_unlock(chan);
+ }
ast_hangup(chan);
res = -1;
goto outgoing_app_cleanup;
@@ -7730,8 +7739,9 @@
break;
}
- if (chan)
+ if (chan) {
ast_channel_unlock(chan);
+ }
return ret;
}
@@ -7764,10 +7774,11 @@
AST_LIST_INSERT_HEAD(headp, newvariable, entries);
}
- if (chan)
+ if (chan) {
ast_channel_unlock(chan);
- else
+ } else {
ast_rwlock_unlock(&globalslock);
+ }
}
void pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
@@ -7821,10 +7832,12 @@
chan ? chan->uniqueid : "none");
}
- if (chan)
+ if (chan) {
ast_channel_unlock(chan);
- else
+ } else {
ast_rwlock_unlock(&globalslock);
+ }
+
}
int pbx_builtin_setvar(struct ast_channel *chan, void *data)
Modified: team/murf/mtxprof/main/rtp.c
URL: http://svn.digium.com/view/asterisk/team/murf/mtxprof/main/rtp.c?view=diff&rev=125137&r1=125136&r2=125137
==============================================================================
--- team/murf/mtxprof/main/rtp.c (original)
+++ team/murf/mtxprof/main/rtp.c Wed Jun 25 17:46:22 2008
@@ -2015,10 +2015,13 @@
/* Lock channels */
ast_channel_lock(c0);
if (c1) {
- while (ast_channel_trylock(c1)) {
+ int lockret;
+ ast_channel_trylock_assign(c1,lockret);
+ while (lockret) {
ast_channel_unlock(c0);
usleep(1);
ast_channel_lock(c0);
+ ast_channel_trylock_assign(c1,lockret);
}
}
@@ -2029,15 +2032,17 @@
if (!destpr) {
ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", c0->name);
ast_channel_unlock(c0);
- if (c1)
+ if (c1) {
ast_channel_unlock(c1);
+ }
return -1;
}
if (!srcpr) {
ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", c1 ? c1->name : "<unspecified>");
ast_channel_unlock(c0);
- if (c1)
+ if (c1) {
ast_channel_unlock(c1);
+ }
return -1;
}
@@ -2055,8 +2060,9 @@
if (audio_dest_res != AST_RTP_TRY_NATIVE) {
/* Somebody doesn't want to play... */
ast_channel_unlock(c0);
- if (c1)
+ if (c1) {
ast_channel_unlock(c1);
+ }
return -1;
}
if (audio_src_res == AST_RTP_TRY_NATIVE && srcpr->get_codec)
@@ -2070,8 +2076,9 @@
/* Ensure we have at least one matching codec */
if (!(srccodec & destcodec)) {
ast_channel_unlock(c0);
- if (c1)
+ if (c1) {
ast_channel_unlock(c1);
+ }
return 0;
}
/* Consider empty media as non-existent */
@@ -2083,8 +2090,9 @@
[... 158 lines stripped ...]
More information about the asterisk-commits
mailing list