chan_local: Misc lock and ref tweaks.

* awesome_locking() does not need to thrash the pvt lock as much.

* local_setoption() does not need to check for NULL pvt on cleanup since
it will never be NULL.

* Made ref the pvt before locking for consistency.


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@378072 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Richard Mudgett
2012-12-17 20:34:25 +00:00
parent de026cf92f
commit 87cb8e94cd

View File

@@ -161,7 +161,7 @@ struct local_pvt {
#define LOCAL_BRIDGE (1 << 3) /*!< Report back the "true" channel as being bridged to */ #define LOCAL_BRIDGE (1 << 3) /*!< Report back the "true" channel as being bridged to */
#define LOCAL_MOH_PASSTHRU (1 << 4) /*!< Pass through music on hold start/stop frames */ #define LOCAL_MOH_PASSTHRU (1 << 4) /*!< Pass through music on hold start/stop frames */
/* /*!
* \brief Send a pvt in with no locks held and get all locks * \brief Send a pvt in with no locks held and get all locks
* *
* \note NO locks should be held prior to calling this function * \note NO locks should be held prior to calling this function
@@ -175,8 +175,8 @@ static void awesome_locking(struct local_pvt *p, struct ast_channel **outchan, s
struct ast_channel *chan = NULL; struct ast_channel *chan = NULL;
struct ast_channel *owner = NULL; struct ast_channel *owner = NULL;
ao2_lock(p);
for (;;) { for (;;) {
ao2_lock(p);
if (p->chan) { if (p->chan) {
chan = p->chan; chan = p->chan;
ast_channel_ref(chan); ast_channel_ref(chan);
@@ -194,12 +194,11 @@ static void awesome_locking(struct local_pvt *p, struct ast_channel **outchan, s
} else if(chan) { } else if(chan) {
ast_channel_lock(chan); ast_channel_lock(chan);
} }
ao2_lock(p);
} else { } else {
/* lock both channels first, then get the pvt lock */ /* lock both channels first, then get the pvt lock */
ast_channel_lock_both(chan, owner); ast_channel_lock_both(chan, owner);
ao2_lock(p);
} }
ao2_lock(p);
/* Now that we have all the locks, validate that nothing changed */ /* Now that we have all the locks, validate that nothing changed */
if (p->owner != owner || p->chan != chan) { if (p->owner != owner || p->chan != chan) {
@@ -211,7 +210,6 @@ static void awesome_locking(struct local_pvt *p, struct ast_channel **outchan, s
ast_channel_unlock(chan); ast_channel_unlock(chan);
chan = ast_channel_unref(chan); chan = ast_channel_unref(chan);
} }
ao2_unlock(p);
continue; continue;
} }
@@ -225,7 +223,7 @@ static void awesome_locking(struct local_pvt *p, struct ast_channel **outchan, s
static int local_setoption(struct ast_channel *ast, int option, void * data, int datalen) static int local_setoption(struct ast_channel *ast, int option, void * data, int datalen)
{ {
int res = 0; int res = 0;
struct local_pvt *p = NULL; struct local_pvt *p;
struct ast_channel *otherchan = NULL; struct ast_channel *otherchan = NULL;
ast_chan_write_info_t *write_info; ast_chan_write_info_t *write_info;
@@ -272,9 +270,7 @@ static int local_setoption(struct ast_channel *ast, int option, void * data, int
ast_channel_unlock(otherchan); ast_channel_unlock(otherchan);
setoption_cleanup: setoption_cleanup:
if (p) { ao2_ref(p, -1);
ao2_ref(p, -1);
}
if (otherchan) { if (otherchan) {
ast_channel_unref(otherchan); ast_channel_unref(otherchan);
} }
@@ -468,8 +464,8 @@ static int local_answer(struct ast_channel *ast)
return -1; return -1;
} }
ao2_lock(p);
ao2_ref(p, 1); ao2_ref(p, 1);
ao2_lock(p);
isoutbound = IS_OUTBOUND(ast, p); isoutbound = IS_OUTBOUND(ast, p);
if (isoutbound) { if (isoutbound) {
/* Pass along answer since somebody answered us */ /* Pass along answer since somebody answered us */
@@ -839,8 +835,8 @@ static int local_sendtext(struct ast_channel *ast, const char *text)
return -1; return -1;
} }
ao2_lock(p);
ao2_ref(p, 1); /* ref for local_queue_frame */ ao2_ref(p, 1); /* ref for local_queue_frame */
ao2_lock(p);
isoutbound = IS_OUTBOUND(ast, p); isoutbound = IS_OUTBOUND(ast, p);
f.data.ptr = (char *) text; f.data.ptr = (char *) text;
f.datalen = strlen(text) + 1; f.datalen = strlen(text) + 1;
@@ -861,8 +857,8 @@ static int local_sendhtml(struct ast_channel *ast, int subclass, const char *dat
return -1; return -1;
} }
ao2_lock(p);
ao2_ref(p, 1); /* ref for local_queue_frame */ ao2_ref(p, 1); /* ref for local_queue_frame */
ao2_lock(p);
isoutbound = IS_OUTBOUND(ast, p); isoutbound = IS_OUTBOUND(ast, p);
f.subclass.integer = subclass; f.subclass.integer = subclass;
f.data.ptr = (char *)data; f.data.ptr = (char *)data;