aboutsummaryrefslogtreecommitdiffstats
path: root/channel.c
diff options
context:
space:
mode:
authoroej <oej@f38db490-d61c-443f-a65b-d21fe96a405b>2006-04-15 08:07:50 +0000
committeroej <oej@f38db490-d61c-443f-a65b-d21fe96a405b>2006-04-15 08:07:50 +0000
commitf33b337077b11c3d312e9e0e87a1f675c8dd235b (patch)
tree8e37585dc242426cd3070d0e6771d0af748f60ca /channel.c
parent91102c5a2cae50a81cc3e135cad4d297aa5d71d6 (diff)
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) git-svn-id: http://svn.digium.com/svn/asterisk/trunk@20264 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channel.c')
-rw-r--r--channel.c124
1 files changed, 124 insertions, 0 deletions
diff --git a/channel.c b/channel.c
index f813e32f8..303cc32c1 100644
--- a/channel.c
+++ b/channel.c
@@ -4187,3 +4187,127 @@ const char *channelreloadreason2txt(enum channelreloadreason reason)
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