A new feature thanks to the fine folks at Switchvox!
authorMark Michelson <mmichelson@digium.com>
Fri, 23 May 2008 22:35:50 +0000 (22:35 +0000)
committerMark Michelson <mmichelson@digium.com>
Fri, 23 May 2008 22:35:50 +0000 (22:35 +0000)
If a deadlock is detected, then the typical lock information will be
printed along with a backtrace of the stack for the offending threads.
Use of this requires compiling with DETECT_DEADLOCKS and having glibc
installed.

Furthermore, issuing the "core show locks" CLI command will print the
normal lock information as well as a backtraces for each lock. This
requires that DEBUG_THREADS is enabled and that glibc is installed.

All the backtrace features may be disabled by running the configure
script with --without-execinfo as an argument

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@118173 65c4cc65-6c06-0410-ace0-fbb531ad65f3

CHANGES
include/asterisk/lock.h
include/asterisk/logger.h
main/logger.c
main/utils.c
utils/ael_main.c
utils/check_expr.c
utils/conf2ael.c
utils/hashtest.c
utils/hashtest2.c
utils/refcounter.c

diff --git a/CHANGES b/CHANGES
index b917295..cf98b2f 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -744,3 +744,9 @@ Miscellaneous
      turned on, via the CHANNEL(trace) dialplan function.  Could be useful for
      dialplan debugging.
   * iLBC source code no longer included (see UPGRADE.txt for details)
+  * If compiled with DETECT_DEADLOCKS enabled and if you have glibc, then if 
+     deadlock is detected, a backtrace of the stack which led to the lock calls
+        will be output to the CLI.
+  * If compiled with DEBUG_THREADS enabled and if you have glibc, then issuing
+     the "core show locks" CLI command will give lock information output as well
+        as a backtrace of the stack which led to the lock calls.
index cbc2926..d78a834 100644 (file)
@@ -51,6 +51,8 @@
 #include <pthread.h>
 #include <sys/param.h>
 
+#include <execinfo.h>
+
 #include "asterisk/logger.h"
 
 /* internal macro to profile mutexes. Only computes the delay on
 
 #include <errno.h>
 
+#ifdef HAVE_BKTR
+#define AST_MUTEX_INIT_VALUE { PTHREAD_MUTEX_INIT_VALUE, 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_MUTEX_INIT_VALUE }
+#define AST_MUTEX_INIT_VALUE_NOTRACKING \
+                             { PTHREAD_MUTEX_INIT_VALUE, 0, { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_MUTEX_INIT_VALUE }
+#else
 #define AST_MUTEX_INIT_VALUE { PTHREAD_MUTEX_INIT_VALUE, 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INIT_VALUE }
 #define AST_MUTEX_INIT_VALUE_NOTRACKING \
                              { PTHREAD_MUTEX_INIT_VALUE, 0, { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INIT_VALUE }
+#endif
 
 #define AST_MAX_REENTRANCY 10
 
@@ -125,6 +133,9 @@ struct ast_mutex_info {
        int reentrancy;
        const char *func[AST_MAX_REENTRANCY];
        pthread_t thread[AST_MAX_REENTRANCY];
+#ifdef HAVE_BKTR
+       struct ast_bt backtrace[AST_MAX_REENTRANCY];
+#endif
        pthread_mutex_t reentr_mutex;
 };
 
@@ -149,12 +160,22 @@ enum ast_lock_type {
  * on the lock.  ast_mark_lock_acquired() will mark it as held by this thread.
  */
 #if !defined(LOW_MEMORY)
+#ifdef HAVE_BKTR
+void ast_store_lock_info(enum ast_lock_type type, const char *filename,
+       int line_num, const char *func, const char *lock_name, void *lock_addr, struct ast_bt *bt);
+#else
 void ast_store_lock_info(enum ast_lock_type type, const char *filename,
        int line_num, const char *func, const char *lock_name, void *lock_addr);
+#endif /* HAVE_BKTR */
+
 #else
-#define ast_store_lock_info(I,DONT,CARE,ABOUT,THE,PARAMETERS)
-#endif
 
+#ifdef HAVE_BKTR
+#define ast_store_lock_info(I,DONT,CARE,ABOUT,THE,PARAMETERS,BUD)
+#else
+#define ast_store_lock_info(I,DONT,CARE,ABOUT,THE,PARAMETERS)
+#endif /* HAVE_BKTR */
+#endif /* !defined(LOW_MEMORY) */
 
 /*!
  * \brief Mark the last lock as acquired
@@ -181,12 +202,34 @@ void ast_mark_lock_failed(void *lock_addr);
  * be removed from the current thread's lock info struct.
  */
 #if !defined(LOW_MEMORY)
+#ifdef HAVE_BKTR
+void ast_remove_lock_info(void *lock_addr, struct ast_bt *bt);
+#else
 void ast_remove_lock_info(void *lock_addr);
+#endif /* HAVE_BKTR */
+#else
+#ifdef HAVE_BKTR
+#define ast_remove_lock_info(ignore,me)
 #else
 #define ast_remove_lock_info(ignore)
-#endif
+#endif /* HAVE_BKTR */
+#endif /* !defined(LOW_MEMORY) */
+
+#ifdef HAVE_BKTR
+static inline void __dump_backtrace(struct ast_bt *bt, int canlog)
+{
+       char **strings;
+
+       size_t i;
 
+       strings = backtrace_symbols(bt->addresses, bt->num_frames);
 
+       for (i = 0; i < bt->num_frames; i++)
+               __ast_mutex_logger("%s\n", strings[i]);
+
+       free(strings);
+}
+#endif
 
 /*!
  * \brief log info for the current lock with ast_log().
@@ -223,6 +266,9 @@ static inline void ast_reentrancy_init(ast_mutex_t *p_ast_mutex)
                p_ast_mutex->lineno[i] = 0;
                p_ast_mutex->func[i] = NULL;
                p_ast_mutex->thread[i] = 0;
+#ifdef HAVE_BKTR
+               memset(&p_ast_mutex->backtrace[i], 0, sizeof(p_ast_mutex->backtrace[i]));
+#endif
        }
 
        p_ast_mutex->reentrancy = 0;
@@ -308,6 +354,9 @@ static inline int __ast_pthread_mutex_destroy(const char *filename, int lineno,
                ast_reentrancy_lock(t);
                __ast_mutex_logger("%s line %d (%s): Error: '%s' was locked here.\n",
                            t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
+#ifdef HAVE_BKTR
+               __dump_backtrace(&t->backtrace[t->reentrancy-1], canlog);
+#endif
                ast_reentrancy_unlock(t);
                break;
        }
@@ -325,6 +374,9 @@ static inline int __ast_pthread_mutex_destroy(const char *filename, int lineno,
        t->func[0] = func;
        t->reentrancy = 0;
        t->thread[0] = 0;
+#ifdef HAVE_BKTR
+       memset(&t->backtrace[0], 0, sizeof(t->backtrace[0]));
+#endif
        ast_reentrancy_unlock(t);
        delete_reentrancy_cs(t);
 
@@ -336,6 +388,9 @@ static inline int __ast_pthread_mutex_lock(const char *filename, int lineno, con
 {
        int res;
        int canlog = strcmp(filename, "logger.c") & t->track;
+#ifdef HAVE_BKTR
+       struct ast_bt *bt = NULL;
+#endif
 
 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
        if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
@@ -352,8 +407,17 @@ static inline int __ast_pthread_mutex_lock(const char *filename, int lineno, con
        }
 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
 
-       if (t->track)
+       if (t->track) {
+#ifdef HAVE_BKTR
+               ast_reentrancy_lock(t);
+               ast_bt_get_addresses(&t->backtrace[t->reentrancy]);
+               bt = &t->backtrace[t->reentrancy];
+               ast_reentrancy_unlock(t);
+               ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, &t->mutex, bt);
+#else
                ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, &t->mutex);
+#endif
+       }
 
 #ifdef DETECT_DEADLOCKS
        {
@@ -373,9 +437,15 @@ static inline int __ast_pthread_mutex_lock(const char *filename, int lineno, con
                                        __ast_mutex_logger("%s line %d (%s): Deadlock? waited %d sec for mutex '%s'?\n",
                                                           filename, lineno, func, (int) wait_time, mutex_name);
                                        ast_reentrancy_lock(t);
+#ifdef HAVE_BKTR
+                                       __dump_backtrace(&t->backtrace[t->reentrancy], canlog);
+#endif
                                        __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
                                                           t->file[t->reentrancy-1], t->lineno[t->reentrancy-1],
                                                           t->func[t->reentrancy-1], mutex_name);
+#ifdef HAVE_BKTR
+                                       __dump_backtrace(&t->backtrace[t->reentrancy-1], canlog);
+#endif
                                        ast_reentrancy_unlock(t);
                                        reported_wait = wait_time;
                                }
@@ -409,8 +479,20 @@ static inline int __ast_pthread_mutex_lock(const char *filename, int lineno, con
                if (t->track)
                        ast_mark_lock_acquired(&t->mutex);
        } else {
+#ifdef HAVE_BKTR
+               if (t->reentrancy) {
+                       ast_reentrancy_lock(t);
+                       bt = &t->backtrace[t->reentrancy-1];
+                       ast_reentrancy_unlock(t);
+               } else {
+                       bt = NULL;
+               }
+               if (t->track)
+                       ast_remove_lock_info(&t->mutex, bt);
+#else
                if (t->track)
                        ast_remove_lock_info(&t->mutex);
+#endif
                __ast_mutex_logger("%s line %d (%s): Error obtaining mutex: %s\n",
                                   filename, lineno, func, strerror(res));
                DO_THREAD_CRASH;
@@ -424,6 +506,9 @@ static inline int __ast_pthread_mutex_trylock(const char *filename, int lineno,
 {
        int res;
        int canlog = strcmp(filename, "logger.c") & t->track;
+#ifdef HAVE_BKTR
+       struct ast_bt *bt = NULL;
+#endif
 
 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
        if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
@@ -440,8 +525,17 @@ static inline int __ast_pthread_mutex_trylock(const char *filename, int lineno,
        }
 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
 
-       if (t->track)
+       if (t->track) {
+#ifdef HAVE_BKTR
+               ast_reentrancy_lock(t);
+               ast_bt_get_addresses(&t->backtrace[t->reentrancy]);
+               bt = &t->backtrace[t->reentrancy];
+               ast_reentrancy_unlock(t);
+               ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, &t->mutex, bt);
+#else
                ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, &t->mutex);
+#endif
+       }
 
        if (!(res = pthread_mutex_trylock(&t->mutex))) {
                ast_reentrancy_lock(t);
@@ -470,6 +564,9 @@ static inline int __ast_pthread_mutex_unlock(const char *filename, int lineno, c
 {
        int res;
        int canlog = strcmp(filename, "logger.c") & t->track;
+#ifdef HAVE_BKTR
+       struct ast_bt *bt = NULL;
+#endif
 
 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
        if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
@@ -490,6 +587,9 @@ static inline int __ast_pthread_mutex_unlock(const char *filename, int lineno, c
                                   filename, lineno, func, mutex_name);
                __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
                                   t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
+#ifdef HAVE_BKTR
+               __dump_backtrace(&t->backtrace[t->reentrancy-1], canlog);
+#endif
                DO_THREAD_CRASH;
        }
 
@@ -505,11 +605,21 @@ static inline int __ast_pthread_mutex_unlock(const char *filename, int lineno, c
                t->func[t->reentrancy] = NULL;
                t->thread[t->reentrancy] = 0;
        }
+
+#ifdef HAVE_BKTR
+       if (t->reentrancy) {
+               bt = &t->backtrace[t->reentrancy - 1];
+       }
+#endif
        ast_reentrancy_unlock(t);
 
-       if (t->track)
+       if (t->track) {
+#ifdef HAVE_BKTR
+               ast_remove_lock_info(&t->mutex, bt);
+#else
                ast_remove_lock_info(&t->mutex);
-
+#endif
+       }
        if ((res = pthread_mutex_unlock(&t->mutex))) {
                __ast_mutex_logger("%s line %d (%s): Error releasing mutex: %s\n", 
                                   filename, lineno, func, strerror(res));
@@ -549,6 +659,9 @@ static inline int __ast_cond_wait(const char *filename, int lineno, const char *
 {
        int res;
        int canlog = strcmp(filename, "logger.c") & t->track;
+#ifdef HAVE_BKTR
+       struct ast_bt *bt = NULL;
+#endif
 
 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
        if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
@@ -569,6 +682,9 @@ static inline int __ast_cond_wait(const char *filename, int lineno, const char *
                                   filename, lineno, func, mutex_name);
                __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
                                   t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
+#ifdef HAVE_BKTR
+               __dump_backtrace(&t->backtrace[t->reentrancy-1], canlog);
+#endif
                DO_THREAD_CRASH;
        }
 
@@ -584,10 +700,21 @@ static inline int __ast_cond_wait(const char *filename, int lineno, const char *
                t->func[t->reentrancy] = NULL;
                t->thread[t->reentrancy] = 0;
        }
+
+#ifdef HAVE_BKTR
+       if (t->reentrancy) {
+               bt = &t->backtrace[t->reentrancy - 1];
+       }
+#endif
        ast_reentrancy_unlock(t);
 
-       if (t->track)
+       if (t->track) {
+#ifdef HAVE_BKTR
+               ast_remove_lock_info(&t->mutex, bt);
+#else
                ast_remove_lock_info(&t->mutex);
+#endif
+       }
 
        if ((res = pthread_cond_wait(cond, &t->mutex))) {
                __ast_mutex_logger("%s line %d (%s): Error waiting on condition mutex '%s'\n", 
@@ -600,6 +727,10 @@ static inline int __ast_cond_wait(const char *filename, int lineno, const char *
                        t->lineno[t->reentrancy] = lineno;
                        t->func[t->reentrancy] = func;
                        t->thread[t->reentrancy] = pthread_self();
+#ifdef HAVE_BKTR
+                       ast_bt_get_addresses(&t->backtrace[t->reentrancy]);
+                       bt = &t->backtrace[t->reentrancy];
+#endif
                        t->reentrancy++;
                } else {
                        __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
@@ -607,8 +738,13 @@ static inline int __ast_cond_wait(const char *filename, int lineno, const char *
                }
                ast_reentrancy_unlock(t);
 
-               if (t->track)
+               if (t->track) {
+#ifdef HAVE_BKTR
+                       ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, &t->mutex, bt);
+#else
                        ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, &t->mutex);
+#endif
+               }
        }
 
        return res;
@@ -620,6 +756,9 @@ static inline int __ast_cond_timedwait(const char *filename, int lineno, const c
 {
        int res;
        int canlog = strcmp(filename, "logger.c") & t->track;
+#ifdef HAVE_BKTR
+       struct ast_bt *bt = NULL;
+#endif
 
 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
        if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
@@ -640,6 +779,9 @@ static inline int __ast_cond_timedwait(const char *filename, int lineno, const c
                                   filename, lineno, func, mutex_name);
                __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
                                   t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
+#ifdef HAVE_BKTR
+               __dump_backtrace(&t->backtrace[t->reentrancy-1], canlog);
+#endif
                DO_THREAD_CRASH;
        }
 
@@ -655,10 +797,19 @@ static inline int __ast_cond_timedwait(const char *filename, int lineno, const c
                t->func[t->reentrancy] = NULL;
                t->thread[t->reentrancy] = 0;
        }
+#ifdef HAVE_BKTR
+       if (t->reentrancy) {
+               bt = &t->backtrace[t->reentrancy - 1];
+       }
+#endif
        ast_reentrancy_unlock(t);
 
        if (t->track)
+#ifdef HAVE_BKTR
+               ast_remove_lock_info(&t->mutex, bt);
+#else
                ast_remove_lock_info(&t->mutex);
+#endif
 
        if ((res = pthread_cond_timedwait(cond, &t->mutex, abstime)) && (res != ETIMEDOUT)) {
                __ast_mutex_logger("%s line %d (%s): Error waiting on condition mutex '%s'\n", 
@@ -671,6 +822,10 @@ static inline int __ast_cond_timedwait(const char *filename, int lineno, const c
                        t->lineno[t->reentrancy] = lineno;
                        t->func[t->reentrancy] = func;
                        t->thread[t->reentrancy] = pthread_self();
+#ifdef HAVE_BKTR
+                       ast_bt_get_addresses(&t->backtrace[t->reentrancy]);
+                       bt = &t->backtrace[t->reentrancy];
+#endif
                        t->reentrancy++;
                } else {
                        __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
@@ -678,8 +833,13 @@ static inline int __ast_cond_timedwait(const char *filename, int lineno, const c
                }
                ast_reentrancy_unlock(t);
 
-               if (t->track)
+               if (t->track) {
+#ifdef HAVE_BKTR
+                       ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, &t->mutex, bt);
+#else
                        ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, &t->mutex);
+#endif
+               }
        }
 
        return res;
@@ -696,151 +856,14 @@ static inline int __ast_cond_timedwait(const char *filename, int lineno, const c
 #define ast_cond_wait(cond, mutex)             __ast_cond_wait(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #mutex, cond, mutex)
 #define ast_cond_timedwait(cond, mutex, time)  __ast_cond_timedwait(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #mutex, cond, mutex, time)
 
-#else /* !DEBUG_THREADS */
-
-
-typedef pthread_mutex_t ast_mutex_t;
-
-#define AST_MUTEX_INIT_VALUE                   ((ast_mutex_t) PTHREAD_MUTEX_INIT_VALUE)
-#define AST_MUTEX_INIT_VALUE_NOTRACKING                ((ast_mutex_t) PTHREAD_MUTEX_INIT_VALUE)
-
-#define ast_mutex_init_notracking(m)           ast_mutex_init(m)
-
-static inline int ast_mutex_init(ast_mutex_t *pmutex)
-{
-       int res;
-       pthread_mutexattr_t attr;
-
-       pthread_mutexattr_init(&attr);
-       pthread_mutexattr_settype(&attr, AST_MUTEX_KIND);
-
-       res = pthread_mutex_init(pmutex, &attr);
-       pthread_mutexattr_destroy(&attr);
-       return res;
-}
-
-#define ast_pthread_mutex_init(pmutex,a) pthread_mutex_init(pmutex,a)
-
-static inline int ast_mutex_unlock(ast_mutex_t *pmutex)
-{
-       return pthread_mutex_unlock(pmutex);
-}
-
-static inline int ast_mutex_destroy(ast_mutex_t *pmutex)
-{
-       return pthread_mutex_destroy(pmutex);
-}
-
-static inline int ast_mutex_lock(ast_mutex_t *pmutex)
-{
-       __MTX_PROF(pmutex);
-}
-
-static inline int ast_mutex_trylock(ast_mutex_t *pmutex)
-{
-       return pthread_mutex_trylock(pmutex);
-}
-
-typedef pthread_cond_t ast_cond_t;
-
-static inline int ast_cond_init(ast_cond_t *cond, pthread_condattr_t *cond_attr)
-{
-       return pthread_cond_init(cond, cond_attr);
-}
-
-static inline int ast_cond_signal(ast_cond_t *cond)
-{
-       return pthread_cond_signal(cond);
-}
-
-static inline int ast_cond_broadcast(ast_cond_t *cond)
-{
-       return pthread_cond_broadcast(cond);
-}
-
-static inline int ast_cond_destroy(ast_cond_t *cond)
-{
-       return pthread_cond_destroy(cond);
-}
-
-static inline int ast_cond_wait(ast_cond_t *cond, ast_mutex_t *t)
-{
-       return pthread_cond_wait(cond, t);
-}
-
-static inline int ast_cond_timedwait(ast_cond_t *cond, ast_mutex_t *t, const struct timespec *abstime)
-{
-       return pthread_cond_timedwait(cond, t, abstime);
-}
-
-#endif /* !DEBUG_THREADS */
-
-#if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
-/*
- * If AST_MUTEX_INIT_W_CONSTRUCTORS is defined, use file scope constructors
- * and destructors to create/destroy global mutexes.
- */
-#define __AST_MUTEX_DEFINE(scope, mutex, init_val, track)      \
-       scope ast_mutex_t mutex = init_val;                     \
-static void  __attribute__ ((constructor)) init_##mutex(void)  \
-{                                                              \
-       if (track)                                              \
-               ast_mutex_init(&mutex);                         \
-       else                                                    \
-               ast_mutex_init_notracking(&mutex);              \
-}                                                              \
-                                                               \
-static void  __attribute__ ((destructor)) fini_##mutex(void)   \
-{                                                              \
-       ast_mutex_destroy(&mutex);                              \
-}
-#else /* !AST_MUTEX_INIT_W_CONSTRUCTORS */
-/* By default, use static initialization of mutexes. */ 
-#define __AST_MUTEX_DEFINE(scope, mutex, init_val, track)      scope ast_mutex_t mutex = init_val
-#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
-
-#ifndef __CYGWIN__     /* temporary disabled for cygwin */
-#define pthread_mutex_t                use_ast_mutex_t_instead_of_pthread_mutex_t
-#define pthread_cond_t         use_ast_cond_t_instead_of_pthread_cond_t
-#endif
-#define pthread_mutex_lock     use_ast_mutex_lock_instead_of_pthread_mutex_lock
-#define pthread_mutex_unlock   use_ast_mutex_unlock_instead_of_pthread_mutex_unlock
-#define pthread_mutex_trylock  use_ast_mutex_trylock_instead_of_pthread_mutex_trylock
-#define pthread_mutex_init     use_ast_mutex_init_instead_of_pthread_mutex_init
-#define pthread_mutex_destroy  use_ast_mutex_destroy_instead_of_pthread_mutex_destroy
-#define pthread_cond_init      use_ast_cond_init_instead_of_pthread_cond_init
-#define pthread_cond_destroy   use_ast_cond_destroy_instead_of_pthread_cond_destroy
-#define pthread_cond_signal    use_ast_cond_signal_instead_of_pthread_cond_signal
-#define pthread_cond_broadcast use_ast_cond_broadcast_instead_of_pthread_cond_broadcast
-#define pthread_cond_wait      use_ast_cond_wait_instead_of_pthread_cond_wait
-#define pthread_cond_timedwait use_ast_cond_timedwait_instead_of_pthread_cond_timedwait
-
-#define AST_MUTEX_DEFINE_STATIC(mutex)                 __AST_MUTEX_DEFINE(static, mutex, AST_MUTEX_INIT_VALUE, 1)
-#define AST_MUTEX_DEFINE_STATIC_NOTRACKING(mutex)      __AST_MUTEX_DEFINE(static, mutex, AST_MUTEX_INIT_VALUE_NOTRACKING, 0)
-
-#define AST_MUTEX_INITIALIZER __use_AST_MUTEX_DEFINE_STATIC_rather_than_AST_MUTEX_INITIALIZER__
-
-#define gethostbyname __gethostbyname__is__not__reentrant__use__ast_gethostbyname__instead__
-
-#ifndef __linux__
-#define pthread_create __use_ast_pthread_create_instead__
-#endif
-
-/*
- * Same as above, definitions of ast_rwlock_t for the various cases:
- * simple wrappers for the pthread equivalent in the non-debug case,
- * more sophisticated tracking in the debug case.
- */
-
-typedef pthread_rwlock_t ast_rwlock_t;
-
-#ifdef HAVE_PTHREAD_RWLOCK_INITIALIZER
-#define AST_RWLOCK_INIT_VALUE PTHREAD_RWLOCK_INITIALIZER
-#else
-#define AST_RWLOCK_INIT_VALUE { 0 }
+struct ast_rwlock_info {
+       pthread_rwlock_t lock;
+#ifdef HAVE_BKTR
+       struct ast_bt backtrace;
 #endif
+};
 
-#ifdef DEBUG_THREADS
+typedef struct ast_rwlock_info ast_rwlock_t;
 
 #define ast_rwlock_init(rwlock)                __ast_rwlock_init(__FILE__, __LINE__, __PRETTY_FUNCTION__, #rwlock, rwlock)
 #define ast_rwlock_destroy(rwlock)     __ast_rwlock_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #rwlock, rwlock)
@@ -850,6 +873,19 @@ typedef pthread_rwlock_t ast_rwlock_t;
 #define ast_rwlock_tryrdlock(a)                _ast_rwlock_tryrdlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
 #define ast_rwlock_trywrlock(a) _ast_rwlock_trywrlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
 
+#ifdef HAVE_PTHREAD_RWLOCK_INITIALIZER
+#ifdef HAVE_BKTR
+#define AST_RWLOCK_INIT_VALUE { PTHREAD_RWLOCK_INITIALIZER, {{0,},} }
+#else
+#define AST_RWLOCK_INIT_VALUE { PTHREAD_RWLOCK_INITIALIZER }
+#endif /* HAVE_BKTR */
+#else  /* HAVE_PTHREAD_RWLOCK_INITIALIZER */
+#ifdef HAVE_BKTR
+#define AST_RWLOCK_INIT_VALUE { 0 , {0,},}}
+#else
+#define AST_RWLOCK_INIT_VALUE { 0 }
+#endif /* HAVE_BKTR */
+#endif /* HAVE_PTHREAD_RWLOCK_INITIALIZER */
 
 static inline int __ast_rwlock_init(const char *filename, int lineno, const char *func, const char *rwlock_name, ast_rwlock_t *prwlock)
 {
@@ -870,7 +906,7 @@ static inline int __ast_rwlock_init(const char *filename, int lineno, const char
        pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NP);
 #endif
 
-       res = pthread_rwlock_init(prwlock, &attr);
+       res = pthread_rwlock_init(&prwlock->lock, &attr);
        pthread_rwlockattr_destroy(&attr);
        return res;
 }
@@ -889,7 +925,7 @@ static inline int __ast_rwlock_destroy(const char *filename, int lineno, const c
        }
 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
        
-       if ((res = pthread_rwlock_destroy(prwlock)))
+       if ((res = pthread_rwlock_destroy(&prwlock->lock)))
                __ast_mutex_logger("%s line %d (%s): Error destroying rwlock %s: %s\n",
                                filename, lineno, func, rwlock_name, strerror(res));
 
@@ -916,8 +952,13 @@ static inline int _ast_rwlock_unlock(ast_rwlock_t *lock, const char *name,
        }
 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
        
-       res = pthread_rwlock_unlock(lock);
+       res = pthread_rwlock_unlock(&lock->lock);
+#ifdef HAVE_BKTR
+       memset(&lock->backtrace, 0, sizeof(lock->backtrace));
+       ast_remove_lock_info(lock, NULL);
+#else
        ast_remove_lock_info(lock);
+#endif
        return res;
 }
 
@@ -942,13 +983,20 @@ static inline int _ast_rwlock_rdlock(ast_rwlock_t *lock, const char *name,
                }
        }
 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
-       
+#ifdef HAVE_BKTR       
+       ast_store_lock_info(AST_RDLOCK, file, line, func, name, lock, &lock->backtrace);
+#else
        ast_store_lock_info(AST_RDLOCK, file, line, func, name, lock);
-       res = pthread_rwlock_rdlock(lock);
+#endif
+       res = pthread_rwlock_rdlock(&lock->lock);
        if (!res)
                ast_mark_lock_acquired(lock);
        else
+#ifdef HAVE_BKTR
+               ast_remove_lock_info(lock, NULL);
+#else
                ast_remove_lock_info(lock);
+#endif
        return res;
 }
 
@@ -973,13 +1021,20 @@ static inline int _ast_rwlock_wrlock(ast_rwlock_t *lock, const char *name,
                }
        }
 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
-
+#ifdef HAVE_BKTR
+       ast_store_lock_info(AST_WRLOCK, file, line, func, name, lock, &lock->backtrace);
+#else
        ast_store_lock_info(AST_WRLOCK, file, line, func, name, lock);
-       res = pthread_rwlock_wrlock(lock);
+#endif
+       res = pthread_rwlock_wrlock(&lock->lock);
        if (!res)
                ast_mark_lock_acquired(lock);
        else
+#ifdef HAVE_BKTR
+               ast_remove_lock_info(lock, NULL);
+#else
                ast_remove_lock_info(lock);
+#endif
        return res;
 }
 
@@ -1004,13 +1059,20 @@ static inline int _ast_rwlock_tryrdlock(ast_rwlock_t *lock, const char *name,
                }
        }
 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
-
+#ifdef HAVE_BKTR
+       ast_store_lock_info(AST_RDLOCK, file, line, func, name, lock, &lock->backtrace);
+#else
        ast_store_lock_info(AST_RDLOCK, file, line, func, name, lock);
-       res = pthread_rwlock_tryrdlock(lock);
+#endif
+       res = pthread_rwlock_tryrdlock(&lock->lock);
        if (!res)
                ast_mark_lock_acquired(lock);
        else
+#ifdef HAVE_BKTR
+               ast_remove_lock_info(lock, NULL);
+#else
                ast_remove_lock_info(lock);
+#endif
        return res;
 }
 
@@ -1035,18 +1097,108 @@ static inline int _ast_rwlock_trywrlock(ast_rwlock_t *lock, const char *name,
                }
        }
 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
-
+#ifdef HAVE_BKTR
+       ast_store_lock_info(AST_WRLOCK, file, line, func, name, lock, &lock->backtrace);
+#else
        ast_store_lock_info(AST_WRLOCK, file, line, func, name, lock);
-       res = pthread_rwlock_trywrlock(lock);
+#endif
+       res = pthread_rwlock_trywrlock(&lock->lock);
        if (!res)
                ast_mark_lock_acquired(lock);
        else
+#ifdef HAVE_BKTR
+               ast_remove_lock_info(lock, NULL);
+#else
                ast_remove_lock_info(lock);
+#endif
        return res;
 }
 
 #else /* !DEBUG_THREADS */
 
+typedef pthread_mutex_t ast_mutex_t;
+
+#define AST_MUTEX_INIT_VALUE                   ((ast_mutex_t) PTHREAD_MUTEX_INIT_VALUE)
+#define AST_MUTEX_INIT_VALUE_NOTRACKING                ((ast_mutex_t) PTHREAD_MUTEX_INIT_VALUE)
+
+#define ast_mutex_init_notracking(m)           ast_mutex_init(m)
+
+static inline int ast_mutex_init(ast_mutex_t *pmutex)
+{
+       int res;
+       pthread_mutexattr_t attr;
+
+       pthread_mutexattr_init(&attr);
+       pthread_mutexattr_settype(&attr, AST_MUTEX_KIND);
+
+       res = pthread_mutex_init(pmutex, &attr);
+       pthread_mutexattr_destroy(&attr);
+       return res;
+}
+
+#define ast_pthread_mutex_init(pmutex,a) pthread_mutex_init(pmutex,a)
+
+static inline int ast_mutex_unlock(ast_mutex_t *pmutex)
+{
+       return pthread_mutex_unlock(pmutex);
+}
+
+static inline int ast_mutex_destroy(ast_mutex_t *pmutex)
+{
+       return pthread_mutex_destroy(pmutex);
+}
+
+static inline int ast_mutex_lock(ast_mutex_t *pmutex)
+{
+       __MTX_PROF(pmutex);
+}
+
+static inline int ast_mutex_trylock(ast_mutex_t *pmutex)
+{
+       return pthread_mutex_trylock(pmutex);
+}
+
+typedef pthread_cond_t ast_cond_t;
+
+static inline int ast_cond_init(ast_cond_t *cond, pthread_condattr_t *cond_attr)
+{
+       return pthread_cond_init(cond, cond_attr);
+}
+
+static inline int ast_cond_signal(ast_cond_t *cond)
+{
+       return pthread_cond_signal(cond);
+}
+
+static inline int ast_cond_broadcast(ast_cond_t *cond)
+{
+       return pthread_cond_broadcast(cond);
+}
+
+static inline int ast_cond_destroy(ast_cond_t *cond)
+{
+       return pthread_cond_destroy(cond);
+}
+
+static inline int ast_cond_wait(ast_cond_t *cond, ast_mutex_t *t)
+{
+       return pthread_cond_wait(cond, t);
+}
+
+static inline int ast_cond_timedwait(ast_cond_t *cond, ast_mutex_t *t, const struct timespec *abstime)
+{
+       return pthread_cond_timedwait(cond, t, abstime);
+}
+
+
+typedef pthread_rwlock_t ast_rwlock_t;
+
+#ifdef HAVE_PTHREAD_RWLOCK_INITIALIZER
+#define AST_RWLOCK_INIT_VALUE PTHREAD_RWLOCK_INITIALIZER
+#else
+#define AST_RWLOCK_INIT_VALUE { 0 }
+#endif
+
 static inline int ast_rwlock_init(ast_rwlock_t *prwlock)
 {
        int res;
@@ -1092,8 +1244,60 @@ static inline int ast_rwlock_trywrlock(ast_rwlock_t *prwlock)
 {
        return pthread_rwlock_trywrlock(prwlock);
 }
+
 #endif /* !DEBUG_THREADS */
 
+#if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
+/*
+ * If AST_MUTEX_INIT_W_CONSTRUCTORS is defined, use file scope constructors
+ * and destructors to create/destroy global mutexes.
+ */
+#define __AST_MUTEX_DEFINE(scope, mutex, init_val, track)      \
+       scope ast_mutex_t mutex = init_val;                     \
+static void  __attribute__ ((constructor)) init_##mutex(void)  \
+{                                                              \
+       if (track)                                              \
+               ast_mutex_init(&mutex);                         \
+       else                                                    \
+               ast_mutex_init_notracking(&mutex);              \
+}                                                              \
+                                                               \
+static void  __attribute__ ((destructor)) fini_##mutex(void)   \
+{                                                              \
+       ast_mutex_destroy(&mutex);                              \
+}
+#else /* !AST_MUTEX_INIT_W_CONSTRUCTORS */
+/* By default, use static initialization of mutexes. */ 
+#define __AST_MUTEX_DEFINE(scope, mutex, init_val, track)      scope ast_mutex_t mutex = init_val
+#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
+
+#ifndef __CYGWIN__     /* temporary disabled for cygwin */
+#define pthread_mutex_t                use_ast_mutex_t_instead_of_pthread_mutex_t
+#define pthread_cond_t         use_ast_cond_t_instead_of_pthread_cond_t
+#endif
+#define pthread_mutex_lock     use_ast_mutex_lock_instead_of_pthread_mutex_lock
+#define pthread_mutex_unlock   use_ast_mutex_unlock_instead_of_pthread_mutex_unlock
+#define pthread_mutex_trylock  use_ast_mutex_trylock_instead_of_pthread_mutex_trylock
+#define pthread_mutex_init     use_ast_mutex_init_instead_of_pthread_mutex_init
+#define pthread_mutex_destroy  use_ast_mutex_destroy_instead_of_pthread_mutex_destroy
+#define pthread_cond_init      use_ast_cond_init_instead_of_pthread_cond_init
+#define pthread_cond_destroy   use_ast_cond_destroy_instead_of_pthread_cond_destroy
+#define pthread_cond_signal    use_ast_cond_signal_instead_of_pthread_cond_signal
+#define pthread_cond_broadcast use_ast_cond_broadcast_instead_of_pthread_cond_broadcast
+#define pthread_cond_wait      use_ast_cond_wait_instead_of_pthread_cond_wait
+#define pthread_cond_timedwait use_ast_cond_timedwait_instead_of_pthread_cond_timedwait
+
+#define AST_MUTEX_DEFINE_STATIC(mutex)                 __AST_MUTEX_DEFINE(static, mutex, AST_MUTEX_INIT_VALUE, 1)
+#define AST_MUTEX_DEFINE_STATIC_NOTRACKING(mutex)      __AST_MUTEX_DEFINE(static, mutex, AST_MUTEX_INIT_VALUE_NOTRACKING, 0)
+
+#define AST_MUTEX_INITIALIZER __use_AST_MUTEX_DEFINE_STATIC_rather_than_AST_MUTEX_INITIALIZER__
+
+#define gethostbyname __gethostbyname__is__not__reentrant__use__ast_gethostbyname__instead__
+
+#ifndef __linux__
+#define pthread_create __use_ast_pthread_create_instead__
+#endif
+
 /* Statically declared read/write locks */
 
 #ifndef HAVE_PTHREAD_RWLOCK_INITIALIZER
index 4995c54..2695efb 100644 (file)
@@ -219,6 +219,50 @@ unsigned int ast_verbose_get_by_file(const char *file);
        } \
 } while (0)
 
+#ifndef _LOGGER_BACKTRACE_H
+#define _LOGGER_BACKTRACE_H
+#ifdef HAVE_BKTR
+#define AST_MAX_BT_FRAMES 32
+/* \brief
+ *
+ * A structure to hold backtrace information. This structure provides an easy means to 
+ * store backtrace information or pass backtraces to other functions.
+ */
+struct ast_bt {
+       /*! The addresses of the stack frames. This is filled in by calling the glibc backtrace() function */
+       void *addresses[AST_MAX_BT_FRAMES];
+       /*! The number of stack frames in the backtrace */
+       int num_frames;
+       /*! Tells if the ast_bt structure was dynamically allocated */
+       unsigned int alloced:1;
+};
+
+/* \brief
+ * Allocates memory for an ast_bt and stores addresses and symbols.
+ *
+ * \return Returns NULL on failure, or the allocated ast_bt on success
+ */
+struct ast_bt *ast_bt_create(void);
+
+/* \brief
+ * Fill an allocated ast_bt with addresses
+ *
+ * \retval 0 Success
+ * \retval -1 Failure
+ */
+int ast_bt_get_addresses(struct ast_bt *bt);
+
+/* \brief
+ * 
+ * Free dynamically allocated portions of an ast_bt
+ *
+ * \retval NULL.
+ */
+void *ast_bt_destroy(struct ast_bt *bt);
+
+#endif /* HAVE_BKTR */
+#endif /* _LOGGER_BACKTRACE_H */
+
 #if defined(__cplusplus) || defined(c_plusplus)
 }
 #endif
index a4936ba..d20ac8b 100644 (file)
@@ -1127,30 +1127,67 @@ void ast_log(int level, const char *file, int line, const char *function, const
        return;
 }
 
+#ifdef HAVE_BKTR
+
+struct ast_bt *ast_bt_create(void) 
+{
+       struct ast_bt *bt = ast_calloc(1, sizeof(*bt));
+       if (!bt) {
+               ast_log(LOG_ERROR, "Unable to allocate memory for backtrace structure!\n");
+               return NULL;
+       }
+
+       bt->alloced = 1;
+
+       ast_bt_get_addresses(bt);
+
+       return bt;
+}
+
+int ast_bt_get_addresses(struct ast_bt *bt)
+{
+       bt->num_frames = backtrace(bt->addresses, AST_MAX_BT_FRAMES);
+
+       return 0;
+}
+
+void *ast_bt_destroy(struct ast_bt *bt)
+{
+       if (bt->alloced) {
+               ast_free(bt);
+       }
+
+       return NULL;
+}
+
+#endif /* HAVE_BKTR */
+
 void ast_backtrace(void)
 {
 #ifdef HAVE_BKTR
-       int count = 0, i = 0;
-       void **addresses;
+       struct ast_bt *backtrace;
+       int i = 0;
        char **strings;
 
-       if ((addresses = ast_calloc(MAX_BACKTRACE_FRAMES, sizeof(*addresses)))) {
-               count = backtrace(addresses, MAX_BACKTRACE_FRAMES);
-               if ((strings = backtrace_symbols(addresses, count))) {
-                       ast_debug(1, "Got %d backtrace record%c\n", count, count != 1 ? 's' : ' ');
-                       for (i = 0; i < count; i++) {
+       if (!(backtrace = ast_bt_create())) {
+               ast_log(LOG_WARNING, "Unable to allocate space for backtrace structure\n");
+               return;
+       }
+
+       if ((strings = backtrace_symbols(backtrace->addresses, backtrace->num_frames))) {
+               ast_debug(1, "Got %d backtrace record%c\n", backtrace->num_frames, backtrace->num_frames != 1 ? 's' : ' ');
+               for (i = 0; i < backtrace->num_frames; i++) {
 #if __WORDSIZE == 32
-                               ast_log(LOG_DEBUG, "#%d: [%08X] %s\n", i, (unsigned int)addresses[i], strings[i]);
+                       ast_log(LOG_DEBUG, "#%d: [%08X] %s\n", i, (unsigned int)backtrace->addresses[i], strings[i]);
 #elif __WORDSIZE == 64
-                               ast_log(LOG_DEBUG, "#%d: [%016lX] %s\n", i, (unsigned long)addresses[i], strings[i]);
+                       ast_log(LOG_DEBUG, "#%d: [%016lX] %s\n", i, (unsigned long)backtrace->addresses[i], strings[i]);
 #endif
-                       }
-                       free(strings);
-               } else {
-                       ast_debug(1, "Could not allocate memory for backtrace\n");
                }
-               ast_free(addresses);
+               free(strings);
+       } else {
+               ast_debug(1, "Could not allocate memory for backtrace\n");
        }
+       ast_bt_destroy(backtrace);
 #else
        ast_log(LOG_WARNING, "Must run configure with '--with-execinfo' for stack backtraces.\n");
 #endif
index 3946df9..dfa32eb 100644 (file)
@@ -540,6 +540,9 @@ struct thr_lock_info {
                enum ast_lock_type type;
                /*! This thread is waiting on this lock */
                int pending:2;
+#ifdef HAVE_BKTR
+               struct ast_bt *backtrace;
+#endif
        } locks[AST_MAX_LOCKS];
        /*! This is the number of locks currently held by this thread.
         *  The index (num_locks - 1) has the info on the last one in the
@@ -583,9 +586,13 @@ static void lock_info_destroy(void *data)
  * \brief The thread storage key for per-thread lock info
  */
 AST_THREADSTORAGE_CUSTOM(thread_lock_info, NULL, lock_info_destroy);
-
+#ifdef HAVE_BKTR
+void ast_store_lock_info(enum ast_lock_type type, const char *filename,
+       int line_num, const char *func, const char *lock_name, void *lock_addr, struct ast_bt *bt)
+#else
 void ast_store_lock_info(enum ast_lock_type type, const char *filename,
        int line_num, const char *func, const char *lock_name, void *lock_addr)
+#endif
 {
        struct thr_lock_info *lock_info;
        int i;
@@ -598,6 +605,9 @@ void ast_store_lock_info(enum ast_lock_type type, const char *filename,
        for (i = 0; i < lock_info->num_locks; i++) {
                if (lock_info->locks[i].lock_addr == lock_addr) {
                        lock_info->locks[i].times_locked++;
+#ifdef HAVE_BKTR
+                       lock_info->locks[i].backtrace = bt;
+#endif
                        pthread_mutex_unlock(&lock_info->lock);
                        return;
                }
@@ -628,6 +638,9 @@ void ast_store_lock_info(enum ast_lock_type type, const char *filename,
        lock_info->locks[i].times_locked = 1;
        lock_info->locks[i].type = type;
        lock_info->locks[i].pending = 1;
+#ifdef HAVE_BKTR
+       lock_info->locks[i].backtrace = bt;
+#endif
        lock_info->num_locks++;
 
        pthread_mutex_unlock(&lock_info->lock);
@@ -661,8 +674,11 @@ void ast_mark_lock_failed(void *lock_addr)
        }
        pthread_mutex_unlock(&lock_info->lock);
 }
-
+#ifdef HAVE_BKTR
+void ast_remove_lock_info(void *lock_addr, struct ast_bt *bt)
+#else
 void ast_remove_lock_info(void *lock_addr)
+#endif
 {
        struct thr_lock_info *lock_info;
        int i = 0;
@@ -685,6 +701,9 @@ void ast_remove_lock_info(void *lock_addr)
 
        if (lock_info->locks[i].times_locked > 1) {
                lock_info->locks[i].times_locked--;
+#ifdef HAVE_BKTR
+               lock_info->locks[i].backtrace = bt;
+#endif
                pthread_mutex_unlock(&lock_info->lock);
                return;
        }
@@ -714,6 +733,30 @@ static const char *locktype2str(enum ast_lock_type type)
        return "UNKNOWN";
 }
 
+#ifdef HAVE_BKTR
+static void append_backtrace_information(struct ast_str **str, struct ast_bt *bt)
+{
+       char **symbols;
+
+       if (!bt) {
+               ast_str_append(str, 0, "\tNo backtrace to print\n");
+               return;
+       }
+
+       if ((symbols = backtrace_symbols(bt->addresses, bt->num_frames))) {
+               int frame_iterator;
+               
+               for (frame_iterator = 0; frame_iterator < bt->num_frames; ++frame_iterator) {
+                       ast_str_append(str, 0, "\t%s\n", symbols[frame_iterator]);
+               }
+
+               free(symbols);
+       } else {
+               ast_str_append(str, 0, "\tCouldn't retrieve backtrace symbols\n");
+       }
+}
+#endif
+
 static void append_lock_information(struct ast_str **str, struct thr_lock_info *lock_info, int i)
 {
        int j;
@@ -728,6 +771,9 @@ static void append_lock_information(struct ast_str **str, struct thr_lock_info *
                                   lock_info->locks[i].func, lock_info->locks[i].lock_name,
                                   lock_info->locks[i].lock_addr, 
                                   lock_info->locks[i].times_locked);
+#ifdef HAVE_BKTR
+       append_backtrace_information(str, lock_info->locks[i].backtrace);
+#endif
        
        if (!lock_info->locks[i].pending || lock_info->locks[i].pending == -1)
                return;
index f8477ed..166fefb 100644 (file)
@@ -578,7 +578,16 @@ unsigned int ast_hashtab_hash_contexts(const void *obj)
 void ast_mark_lock_acquired(void *lock_addr)
 {
 }
+#ifdef HAVE_BKTR
+void ast_remove_lock_info(void *lock_addr, struct ast_bt *bt)
+{
+}
 
+void ast_store_lock_info(enum ast_lock_type type, const char *filename,
+       int line_num, const char *func, const char *lock_name, void *lock_addr, struct ast_bt *bt)
+{
+}
+#else
 void ast_remove_lock_info(void *lock_addr)
 {
 }
@@ -587,5 +596,6 @@ void ast_store_lock_info(enum ast_lock_type type, const char *filename,
        int line_num, const char *func, const char *lock_name, void *lock_addr)
 {
 }
-#endif
-#endif
+#endif /* HAVE_BKTR */
+#endif /* !defined(LOW_MEMORY) */
+#endif /* DEBUG_THREADS */
index 7b013f1..5293acc 100644 (file)
@@ -86,16 +86,25 @@ enum ast_lock_type {
 };
 #endif
 #if !defined(LOW_MEMORY)
+#ifdef HAVE_BKTR
 void ast_store_lock_info(enum ast_lock_type type, const char *filename,
-                       int line_num, const char *func, const char *lock_name, void *lock_addr);
+                       int line_num, const char *func, const char *lock_name, void *lock_addr, struct ast_bt *bt);
 void ast_store_lock_info(enum ast_lock_type type, const char *filename,
-                       int line_num, const char *func, const char *lock_name, void *lock_addr)
+                       int line_num, const char *func, const char *lock_name, void *lock_addr, struct ast_bt *bt)
 {
     /* not a lot to do in a standalone w/o threading! */
 }
 
-void ast_mark_lock_acquired(void *);
-void ast_mark_lock_acquired(void *foo)
+void ast_remove_lock_info(void *lock_addr, struct ast_bt *bt);
+void ast_remove_lock_info(void *lock_addr, struct ast_bt *bt)
+{
+    /* not a lot to do in a standalone w/o threading! */
+}
+#else
+void ast_store_lock_info(enum ast_lock_type type, const char *filename,
+                       int line_num, const char *func, const char *lock_name, void *lock_addr);
+void ast_store_lock_info(enum ast_lock_type type, const char *filename,
+                       int line_num, const char *func, const char *lock_name, void *lock_addr)
 {
     /* not a lot to do in a standalone w/o threading! */
 }
@@ -105,6 +114,13 @@ void ast_remove_lock_info(void *lock_addr)
 {
     /* not a lot to do in a standalone w/o threading! */
 }
+#endif /* HAVE_BKTR */
+
+void ast_mark_lock_acquired(void *);
+void ast_mark_lock_acquired(void *foo)
+{
+    /* not a lot to do in a standalone w/o threading! */
+}
 #endif
 
 static int global_lineno = 1;
index 4572cbd..a55a795 100644 (file)
@@ -705,7 +705,16 @@ unsigned int ast_hashtab_hash_contexts(const void *obj)
 void ast_mark_lock_acquired(void *lock_addr)
 {
 }
+#ifdef HAVE_BKTR
+void ast_remove_lock_info(void *lock_addr, struct ast_bt *bt)
+{
+}
 
+void ast_store_lock_info(enum ast_lock_type type, const char *filename,
+       int line_num, const char *func, const char *lock_name, void *lock_addr, struct ast_bt *bt)
+{
+}
+#else
 void ast_remove_lock_info(void *lock_addr)
 {
 }
@@ -714,5 +723,6 @@ void ast_store_lock_info(enum ast_lock_type type, const char *filename,
        int line_num, const char *func, const char *lock_name, void *lock_addr)
 {
 }
-#endif
-#endif
+#endif /* HAVE_BKTR */
+#endif /* !defined(LOW_MEMORY) */
+#endif /* DEBUG_THREADS */
index 95f463d..7ff7a55 100644 (file)
@@ -366,3 +366,23 @@ void ast_register_thread(char *name)
 void ast_unregister_thread(void *id)
 {
 }
+
+#ifdef HAVE_BKTR
+struct ast_bt *ast_bt_create(void);
+struct ast_bt *ast_bt_create(void) 
+{
+       return NULL;
+}
+
+int ast_bt_get_addresses(struct ast_bt *bt);
+int ast_bt_get_addresses(struct ast_bt *bt)
+{
+       return 0;
+}
+
+void *ast_bt_destroy(struct ast_bt *bt);
+void *ast_bt_destroy(struct ast_bt *bt)
+{
+       return NULL;
+}
+#endif
index 2865822..27ed307 100644 (file)
@@ -378,3 +378,20 @@ void ast_register_thread(char *name)
 void ast_unregister_thread(void *id)
 {
 }
+
+#ifdef HAVE_BKTR
+struct ast_bt* ast_bt_create(void)
+{
+       return NULL;
+}
+
+int ast_bt_get_addresses(struct ast_bt *bt)
+{
+       return -1;
+}
+
+void *ast_bt_destroy(struct ast_bt *bt)
+{
+       return NULL;
+}
+#endif
index 5e75061..4712c26 100644 (file)
@@ -269,3 +269,22 @@ void ast_register_thread(char *name)
 void ast_unregister_thread(void *id)
 {
 }
+#ifdef HAVE_BKTR
+struct ast_bt *ast_bt_create(void);
+struct ast_bt *ast_bt_create(void) 
+{
+       return NULL;
+}
+
+int ast_bt_get_addresses(struct ast_bt *bt);
+int ast_bt_get_addresses(struct ast_bt *bt)
+{
+       return 0;
+}
+
+void *ast_bt_destroy(struct ast_bt *bt);
+void *ast_bt_destroy(struct ast_bt *bt)
+{
+       return NULL;
+}
+#endif