[asterisk-commits] trunk r20264 - in /trunk: ./ channels/
include/asterisk/
asterisk-commits at lists.digium.com
asterisk-commits at lists.digium.com
Sat Apr 15 01:07:55 MST 2006
Author: oej
Date: Sat Apr 15 03:07:50 2006
New Revision: 20264
URL: http://svn.digium.com/view/asterisk?rev=20264&view=rev
Log:
New functions for locking a channel - these simplify debugging
when you have channel locking issues.
(Part of the SIP transfer patch, where I had a *lot* of
channel locking problems)
Modified:
trunk/Makefile
trunk/channel.c
trunk/channels/chan_sip.c
trunk/include/asterisk/lock.h
Modified: trunk/Makefile
URL: http://svn.digium.com/view/asterisk/trunk/Makefile?rev=20264&r1=20263&r2=20264&view=diff
==============================================================================
--- trunk/Makefile (original)
+++ trunk/Makefile Sat Apr 15 03:07:50 2006
@@ -89,6 +89,10 @@
# Optional debugging parameters
DEBUG_THREADS = #-DDUMP_SCHEDULER #-DDEBUG_SCHEDULER #-DDEBUG_THREADS #-DDO_CRASH #-DDETECT_DEADLOCKS
+
+# If you want to debug channel locking, try this (depends on code using
+# ast_channel_lock and companions to work)
+DEBUG_THREADS += #-DDEBUG_CHANNEL_LOCKS
# Uncomment next one to enable ast_frame tracing (for debugging)
TRACE_FRAMES = #-DTRACE_FRAMES
Modified: trunk/channel.c
URL: http://svn.digium.com/view/asterisk/trunk/channel.c?rev=20264&r1=20263&r2=20264&view=diff
==============================================================================
--- trunk/channel.c (original)
+++ trunk/channel.c Sat Apr 15 03:07:50 2006
@@ -4187,3 +4187,127 @@
return "MANAGERRELOAD (Channel module reload by manager)";
}
};
+
+#ifdef DEBUG_CHANNEL_LOCKS
+
+/*! \brief Unlock AST channel (and print debugging output)
+\note You need to enable DEBUG_CHANNEL_LOCKS for this function
+*/
+int ast_channel_unlock(struct ast_channel *chan)
+{
+ int res = 0;
+ if (option_debug > 2)
+ ast_log(LOG_DEBUG, "::::==== Unlocking AST channel %s\n", chan->name);
+
+ if (!chan) {
+ ast_log(LOG_DEBUG, "::::==== Unlocking non-existing channel \n");
+ return 0;
+ }
+
+ res = ast_mutex_unlock(&chan->lock);
+
+ if (option_debug > 2) {
+ /* Try to find counter if possible on your platform
+ I've only found out how to do this on Linux
+ DEBUG_THREADS changes the lock structure
+ */
+#ifdef __linux__
+ int count = 0;
+#ifdef DEBUG_THREADS
+ if ((count = chan->lock.mutex.__m_count))
+#else
+ if ((count = chan->lock.__m_count))
+#endif
+ ast_log(LOG_DEBUG, ":::=== Still have %d locks (recursive)\n", count);
+#endif
+ if (!res)
+ ast_log(LOG_DEBUG, "::::==== Channel %s was unlocked\n", chan->name);
+ if (res == EINVAL) {
+ ast_log(LOG_DEBUG, "::::==== Channel %s had no lock by this thread. Failed unlocking\n", chan->name);
+ }
+ }
+ if (res == EPERM) {
+ /* We had no lock, so okay any way*/
+ if (option_debug > 3)
+ ast_log(LOG_DEBUG, "::::==== Channel %s was not locked at all \n", chan->name);
+ res = 0;
+ }
+ return res;
+}
+
+/*! \brief Lock AST channel (and print debugging output)
+\note You need to enable DEBUG_CHANNEL_LOCKS for this function */
+int ast_channel_lock(struct ast_channel *chan)
+{
+ int res;
+
+ if (option_debug > 3)
+ ast_log(LOG_DEBUG, "====:::: Locking AST channel %s\n", chan->name);
+
+ res = ast_mutex_lock(&chan->lock);
+
+ if (option_debug > 3) {
+#ifdef __linux__
+ int count = 0;
+#ifdef DEBUG_THREADS
+ if ((count = chan->lock.mutex.__m_count))
+#else
+ if ((count = chan->lock.__m_count))
+#endif
+ ast_log(LOG_DEBUG, ":::=== Now have %d locks (recursive)\n", count);
+#endif
+ if (!res)
+ ast_log(LOG_DEBUG, "::::==== Channel %s was locked\n", chan->name);
+ if (res == EDEADLK) {
+ /* We had no lock, so okey any way */
+ if (option_debug > 3)
+ ast_log(LOG_DEBUG, "::::==== Channel %s was not locked by us. Lock would cause deadlock.\n", chan->name);
+ }
+ if (res == EINVAL) {
+ if (option_debug > 3)
+ ast_log(LOG_DEBUG, "::::==== Channel %s lock failed. No mutex.\n", chan->name);
+ }
+ }
+ return res;
+}
+
+/*! \brief Lock AST channel (and print debugging output)
+\note You need to enable DEBUG_CHANNEL_LOCKS for this function */
+int __ast_channel_trylock(struct ast_channel *chan)
+{
+ int res;
+
+ if (option_debug > 2)
+ ast_log(LOG_DEBUG, "====:::: Trying to lock AST channel %s\n", chan->name);
+
+ res = ast_mutex_trylock(&chan->lock);
+
+ if (option_debug > 2) {
+#ifdef __linux__
+ int count = 0;
+#ifdef DEBUG_THREADS
+ if ((count = chan->lock.mutex.__m_count))
+#else
+ if ((count = chan->lock.__m_count))
+#endif
+ ast_log(LOG_DEBUG, ":::=== Now have %d locks (recursive)\n", count);
+#endif
+ if (!res)
+ ast_log(LOG_DEBUG, "::::==== Channel %s was locked\n", chan->name);
+ if (res == EBUSY) {
+ /* We failed to lock */
+ if (option_debug > 2)
+ ast_log(LOG_DEBUG, "::::==== Channel %s failed to lock. Not waiting around...\n", chan->name);
+ }
+ if (res == EDEADLK) {
+ /* We had no lock, so okey any way*/
+ if (option_debug > 2)
+ ast_log(LOG_DEBUG, "::::==== Channel %s was not locked. Lock would cause deadlock.\n", chan->name);
+ }
+ if (res == EINVAL && option_debug > 2)
+ ast_log(LOG_DEBUG, "::::==== Channel %s lock failed. No mutex.\n", chan->name);
+ }
+ return res;
+}
+
+#endif
Modified: trunk/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/trunk/channels/chan_sip.c?rev=20264&r1=20263&r2=20264&view=diff
==============================================================================
--- trunk/channels/chan_sip.c (original)
+++ trunk/channels/chan_sip.c Sat Apr 15 03:07:50 2006
@@ -1344,7 +1344,7 @@
int reschedule = DEFAULT_RETRANS;
/* Lock channel */
- ast_mutex_lock(&pkt->owner->lock);
+ ast_channel_lock(&pkt->owner);
if (pkt->retrans < MAX_RETRANS) {
pkt->retrans++;
@@ -1381,7 +1381,7 @@
append_history(pkt->owner, "ReTx", "%d %s", reschedule, pkt->data);
__sip_xmit(pkt->owner, pkt->data, pkt->packetlen);
- ast_mutex_unlock(&pkt->owner->lock);
+ ast_channel_unlock(&pkt->owner);
return reschedule;
}
/* Too many retries */
Modified: trunk/include/asterisk/lock.h
URL: http://svn.digium.com/view/asterisk/trunk/include/asterisk/lock.h?rev=20264&r1=20263&r2=20264&view=diff
==============================================================================
--- trunk/include/asterisk/lock.h (original)
+++ trunk/include/asterisk/lock.h Sat Apr 15 03:07:50 2006
@@ -761,4 +761,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);
+/*! \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);
+/*! \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);
+#endif
+
#endif /* _ASTERISK_LOCK_H */
More information about the asterisk-commits
mailing list