[Asterisk-bsd] How to implement locking in channel drivers
Hans Petter Selasky
hselasky at c2i.net
Tue Aug 2 13:46:34 CDT 2005
Hi,
I sent this mail to "asterisk-dev at lists.digium.com", but it hasn't passed the
moderator yet, so I'm posting it here meanwhile:
I'm writing a channel driver for asterisk and I have hit some problems.
1)
I want to have my channel driver under a BSD license, but I see no
ASTERISK_BSD_KEY. Must all code be under GPL or is BSD also allowed?
2)
From what I see, "ast_hangup()" does not perform any race condition checks. It
is not impossible that two threads can call this function in parallell, and
succeed until "ast_channel_free()" is called, which handle races.
I'm trying to stay straight with mutexes, and as you probably know, locking
order cannot be reversed. That will lead to a deadlock. My code looks like
this:
struct call_desc { // private structure associated with ast_channel
struct ast_channel *p_ch;
astmutex_t *p_mtx;
} *cd;
When I setup things I do like this:
cd->p_ch = ast_channel_alloc(1);
cd->p_mtx = &cd->p_ch->lock;
Then I have a routine to lookup call descriptors by number:
/*---------------------------------------------------------------------------*
* cd_by_cid - find call descriptor by ID;
*
* NOTE: returns with "cd->mtx" locked
*---------------------------------------------------------------------------*/
static struct call_desc *
cd_by_cid(u_int32_t cid)
{
struct call_desc *cd;
ast_mutex_lock(&cd_global_lock);
cd = cd_root;
ast_mutex_unlock(&cd_global_lock);
while(cd)
{
ast_mutex_lock(&cd->p_mtx);
if((cd->cid != 0) &&
(((cd->cid ^ cid) & 0xFFFF) == 0))
{
break;
}
ast_mutex_unlock(&cd->p_mtx);
cd = cd->next;
}
return cd;
}
The problem is that asterisk destroys it's channel mutex when "ast_hangup()"
is called. But this mutex must be present even after that the channel has
been freed, hence code might be about to lock that mutex and access struct
ast_channel. Also struct ast_channel must be static and not freed by free().
One solution is to use a single lock for all of my channel driver, but that is
not what I want. Does anyone have a solution for this problem?
Another solution is to allocate my own mutex, but then I end up with locking
order reversal between my mutex and "p_ch->lock".
--HPS
More information about the Asterisk-BSD
mailing list