[asterisk-commits] russell: trunk r120064 - in /trunk: include/asterisk/ main/ utils/
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Tue Jun 3 13:26:51 CDT 2008
Author: russell
Date: Tue Jun 3 13:26:51 2008
New Revision: 120064
URL: http://svn.digium.com/view/asterisk?view=rev&rev=120064
Log:
Add lock tracking for rwlocks. Previously, lock.h only had the ability to
hold tracking information for mutexes. Now, the "core show locks" output
will output information about who is holding a rwlock when a thread is
waiting on it.
(closes issue #11279)
Reported by: ys
Patches:
trunk_lock_utils.v8.diff uploaded by ys (license 281)
Modified:
trunk/include/asterisk/lock.h
trunk/main/channel.c
trunk/main/utils.c
trunk/utils/ael_main.c
trunk/utils/conf2ael.c
Modified: trunk/include/asterisk/lock.h
URL: http://svn.digium.com/view/asterisk/trunk/include/asterisk/lock.h?view=diff&rev=120064&r1=120063&r2=120064
==============================================================================
--- trunk/include/asterisk/lock.h (original)
+++ trunk/include/asterisk/lock.h Tue Jun 3 13:26:51 2008
@@ -111,23 +111,20 @@
#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_LOCK_TRACK_INIT_VALUE { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_MUTEX_INIT_VALUE }
+
+#else
+#define AST_LOCK_TRACK_INIT_VALUE { { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INIT_VALUE }
+#endif
+
+#define AST_MUTEX_INIT_VALUE { AST_LOCK_TRACK_INIT_VALUE, 1, PTHREAD_MUTEX_INIT_VALUE }
+#define AST_MUTEX_INIT_VALUE_NOTRACKING { AST_LOCK_TRACK_INIT_VALUE, 0, PTHREAD_MUTEX_INIT_VALUE }
#define AST_MAX_REENTRANCY 10
struct ast_channel;
-struct ast_mutex_info {
- pthread_mutex_t mutex;
- /*! Track which thread holds this lock */
- unsigned int track:1;
+struct ast_lock_track {
const char *file[AST_MAX_REENTRANCY];
int lineno[AST_MAX_REENTRANCY];
int reentrancy;
@@ -139,11 +136,16 @@
pthread_mutex_t reentr_mutex;
};
+struct ast_mutex_info {
+ /*! Track which thread holds this mutex */
+ struct ast_lock_track track;
+ unsigned int tracking:1;
+ pthread_mutex_t mutex;
+};
+
typedef struct ast_mutex_info ast_mutex_t;
typedef pthread_cond_t ast_cond_t;
-
-static pthread_mutex_t empty_mutex;
enum ast_lock_type {
AST_MUTEX,
@@ -273,50 +275,45 @@
} \
} while (0)
-static void __attribute__((constructor)) init_empty_mutex(void)
-{
- memset(&empty_mutex, 0, sizeof(empty_mutex));
-}
-
-static inline void ast_reentrancy_lock(ast_mutex_t *p_ast_mutex)
-{
- pthread_mutex_lock(&p_ast_mutex->reentr_mutex);
-}
-
-static inline void ast_reentrancy_unlock(ast_mutex_t *p_ast_mutex)
-{
- pthread_mutex_unlock(&p_ast_mutex->reentr_mutex);
-}
-
-static inline void ast_reentrancy_init(ast_mutex_t *p_ast_mutex)
+static inline void ast_reentrancy_lock(struct ast_lock_track *lt)
+{
+ pthread_mutex_lock(<->reentr_mutex);
+}
+
+static inline void ast_reentrancy_unlock(struct ast_lock_track *lt)
+{
+ pthread_mutex_unlock(<->reentr_mutex);
+}
+
+static inline void ast_reentrancy_init(struct ast_lock_track *lt)
{
int i;
pthread_mutexattr_t reentr_attr;
for (i = 0; i < AST_MAX_REENTRANCY; i++) {
- p_ast_mutex->file[i] = NULL;
- 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;
+ lt->file[i] = NULL;
+ lt->lineno[i] = 0;
+ lt->func[i] = NULL;
+ lt->thread[i] = 0;
+#ifdef HAVE_BKTR
+ memset(<->backtrace[i], 0, sizeof(lt->backtrace[i]));
+#endif
+ }
+
+ lt->reentrancy = 0;
pthread_mutexattr_init(&reentr_attr);
pthread_mutexattr_settype(&reentr_attr, AST_MUTEX_KIND);
- pthread_mutex_init(&p_ast_mutex->reentr_mutex, &reentr_attr);
+ pthread_mutex_init(<->reentr_mutex, &reentr_attr);
pthread_mutexattr_destroy(&reentr_attr);
}
-static inline void delete_reentrancy_cs(ast_mutex_t * p_ast_mutex)
-{
- pthread_mutex_destroy(&p_ast_mutex->reentr_mutex);
-}
-
-static inline int __ast_pthread_mutex_init(int track, const char *filename, int lineno, const char *func,
+static inline void delete_reentrancy_cs(struct ast_lock_track *lt)
+{
+ pthread_mutex_destroy(<->reentr_mutex);
+}
+
+static inline int __ast_pthread_mutex_init(int tracking, const char *filename, int lineno, const char *func,
const char *mutex_name, ast_mutex_t *t)
{
int res;
@@ -336,8 +333,8 @@
#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
- ast_reentrancy_init(t);
- t->track = track;
+ ast_reentrancy_init(&t->track);
+ t->tracking = tracking;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, AST_MUTEX_KIND);
@@ -355,7 +352,8 @@
const char *mutex_name, ast_mutex_t *t)
{
int res;
- int canlog = strcmp(filename, "logger.c") & t->track;
+ struct ast_lock_track *lt;
+ int canlog = strcmp(filename, "logger.c") & t->tracking;
#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
@@ -370,6 +368,8 @@
return 0;
}
#endif
+
+ lt = &t->track;
res = pthread_mutex_trylock(&t->mutex);
switch (res) {
@@ -383,34 +383,36 @@
case EBUSY:
__ast_mutex_logger("%s line %d (%s): Error: attempt to destroy locked mutex '%s'.\n",
filename, lineno, func, mutex_name);
- ast_reentrancy_lock(t);
+ ast_reentrancy_lock(lt);
__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);
+ lt->file[lt->reentrancy-1], lt->lineno[lt->reentrancy-1], lt->func[lt->reentrancy-1], mutex_name);
+#ifdef HAVE_BKTR
+ __dump_backtrace(<->backtrace[lt->reentrancy-1], canlog);
+#endif
+ ast_reentrancy_unlock(lt);
break;
}
- if ((res = pthread_mutex_destroy(&t->mutex)))
+
+ if ((res = pthread_mutex_destroy(&t->mutex))) {
__ast_mutex_logger("%s line %d (%s): Error destroying mutex %s: %s\n",
filename, lineno, func, mutex_name, strerror(res));
+ }
#ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
else
t->mutex = PTHREAD_MUTEX_INIT_VALUE;
#endif
- ast_reentrancy_lock(t);
- t->file[0] = filename;
- t->lineno[0] = 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);
+ ast_reentrancy_lock(lt);
+ lt->file[0] = filename;
+ lt->lineno[0] = lineno;
+ lt->func[0] = func;
+ lt->reentrancy = 0;
+ lt->thread[0] = 0;
+#ifdef HAVE_BKTR
+ memset(<->backtrace[0], 0, sizeof(lt->backtrace[0]));
+#endif
+ ast_reentrancy_unlock(lt);
+ delete_reentrancy_cs(lt);
return res;
}
@@ -419,7 +421,8 @@
const char* mutex_name, ast_mutex_t *t)
{
int res;
- int canlog = strcmp(filename, "logger.c") & t->track;
+ struct ast_lock_track *lt = &t->track;
+ int canlog = strcmp(filename, "logger.c") & t->tracking;
#ifdef HAVE_BKTR
struct ast_bt *bt = NULL;
#endif
@@ -430,7 +433,7 @@
* Simple try to initialize it.
* May be not needed in linux system.
*/
- res = __ast_pthread_mutex_init(t->track, filename, lineno, func, mutex_name, t);
+ res = __ast_pthread_mutex_init(t->tracking, filename, lineno, func, mutex_name, t);
if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
__ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized and unable to initialize.\n",
filename, lineno, func, mutex_name);
@@ -439,12 +442,12 @@
}
#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
- 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);
+ if (t->tracking) {
+#ifdef HAVE_BKTR
+ ast_reentrancy_lock(lt);
+ ast_bt_get_addresses(<->backtrace[lt->reentrancy]);
+ bt = <->backtrace[lt->reentrancy];
+ ast_reentrancy_unlock(lt);
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);
@@ -468,17 +471,17 @@
if (wait_time > reported_wait && (wait_time % 5) == 0) {
__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);
+ ast_reentrancy_lock(lt);
+#ifdef HAVE_BKTR
+ __dump_backtrace(<->backtrace[lt->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);
+ lt->file[lt->reentrancy-1], lt->lineno[lt->reentrancy-1],
+ lt->func[lt->reentrancy-1], mutex_name);
+#ifdef HAVE_BKTR
+ __dump_backtrace(<->backtrace[lt->reentrancy-1], canlog);
+#endif
+ ast_reentrancy_unlock(lt);
reported_wait = wait_time;
}
usleep(200);
@@ -496,34 +499,37 @@
#endif /* DETECT_DEADLOCKS */
if (!res) {
- ast_reentrancy_lock(t);
- if (t->reentrancy < AST_MAX_REENTRANCY) {
- t->file[t->reentrancy] = filename;
- t->lineno[t->reentrancy] = lineno;
- t->func[t->reentrancy] = func;
- t->thread[t->reentrancy] = pthread_self();
- t->reentrancy++;
+ ast_reentrancy_lock(lt);
+ if (lt->reentrancy < AST_MAX_REENTRANCY) {
+ lt->file[lt->reentrancy] = filename;
+ lt->lineno[lt->reentrancy] = lineno;
+ lt->func[lt->reentrancy] = func;
+ lt->thread[lt->reentrancy] = pthread_self();
+ lt->reentrancy++;
} else {
__ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
filename, lineno, func, mutex_name);
}
- ast_reentrancy_unlock(t);
- if (t->track)
+ ast_reentrancy_unlock(lt);
+ if (t->tracking) {
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);
+ if (lt->reentrancy) {
+ ast_reentrancy_lock(lt);
+ bt = <->backtrace[lt->reentrancy-1];
+ ast_reentrancy_unlock(lt);
} else {
bt = NULL;
}
- if (t->track)
+ if (t->tracking) {
ast_remove_lock_info(&t->mutex, bt);
-#else
- if (t->track)
+ }
+#else
+ if (t->tracking) {
ast_remove_lock_info(&t->mutex);
+ }
#endif
__ast_mutex_logger("%s line %d (%s): Error obtaining mutex: %s\n",
filename, lineno, func, strerror(res));
@@ -537,7 +543,8 @@
const char* mutex_name, ast_mutex_t *t)
{
int res;
- int canlog = strcmp(filename, "logger.c") & t->track;
+ struct ast_lock_track *lt= &t->track;
+ int canlog = strcmp(filename, "logger.c") & t->tracking;
#ifdef HAVE_BKTR
struct ast_bt *bt = NULL;
#endif
@@ -548,7 +555,7 @@
* Simple try to initialize it.
* May be not needed in linux system.
*/
- res = __ast_pthread_mutex_init(t->track, filename, lineno, func, mutex_name, t);
+ res = __ast_pthread_mutex_init(t->tracking, filename, lineno, func, mutex_name, t);
if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
__ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized and unable to initialize.\n",
filename, lineno, func, mutex_name);
@@ -557,12 +564,12 @@
}
#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
- 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);
+ if (t->tracking) {
+#ifdef HAVE_BKTR
+ ast_reentrancy_lock(lt);
+ ast_bt_get_addresses(<->backtrace[lt->reentrancy]);
+ bt = <->backtrace[lt->reentrancy];
+ ast_reentrancy_unlock(lt);
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);
@@ -570,21 +577,22 @@
}
if (!(res = pthread_mutex_trylock(&t->mutex))) {
- ast_reentrancy_lock(t);
- if (t->reentrancy < AST_MAX_REENTRANCY) {
- t->file[t->reentrancy] = filename;
- t->lineno[t->reentrancy] = lineno;
- t->func[t->reentrancy] = func;
- t->thread[t->reentrancy] = pthread_self();
- t->reentrancy++;
+ ast_reentrancy_lock(lt);
+ if (lt->reentrancy < AST_MAX_REENTRANCY) {
+ lt->file[lt->reentrancy] = filename;
+ lt->lineno[lt->reentrancy] = lineno;
+ lt->func[lt->reentrancy] = func;
+ lt->thread[lt->reentrancy] = pthread_self();
+ lt->reentrancy++;
} else {
__ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
filename, lineno, func, mutex_name);
}
- ast_reentrancy_unlock(t);
- if (t->track)
+ ast_reentrancy_unlock(lt);
+ if (t->tracking) {
ast_mark_lock_acquired(&t->mutex);
- } else if (t->track) {
+ }
+ } else if (t->tracking) {
ast_mark_lock_failed(&t->mutex);
}
@@ -595,7 +603,8 @@
const char *mutex_name, ast_mutex_t *t)
{
int res;
- int canlog = strcmp(filename, "logger.c") & t->track;
+ struct ast_lock_track *lt = &t->track;
+ int canlog = strcmp(filename, "logger.c") & t->tracking;
#ifdef HAVE_BKTR
struct ast_bt *bt = NULL;
#endif
@@ -604,7 +613,7 @@
if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
__ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
filename, lineno, func, mutex_name);
- res = __ast_pthread_mutex_init(t->track, filename, lineno, func, mutex_name, t);
+ res = __ast_pthread_mutex_init(t->tracking, filename, lineno, func, mutex_name, t);
if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
__ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized and unable to initialize.\n",
filename, lineno, func, mutex_name);
@@ -613,45 +622,46 @@
}
#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
- ast_reentrancy_lock(t);
- if (t->reentrancy && (t->thread[t->reentrancy-1] != pthread_self())) {
+ ast_reentrancy_lock(lt);
+ if (lt->reentrancy && (lt->thread[lt->reentrancy-1] != pthread_self())) {
__ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
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);
+ lt->file[lt->reentrancy-1], lt->lineno[lt->reentrancy-1], lt->func[lt->reentrancy-1], mutex_name);
+#ifdef HAVE_BKTR
+ __dump_backtrace(<->backtrace[lt->reentrancy-1], canlog);
#endif
DO_THREAD_CRASH;
}
- if (--t->reentrancy < 0) {
+ if (--lt->reentrancy < 0) {
__ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
filename, lineno, func, mutex_name);
- t->reentrancy = 0;
- }
-
- if (t->reentrancy < AST_MAX_REENTRANCY) {
- t->file[t->reentrancy] = NULL;
- t->lineno[t->reentrancy] = 0;
- 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) {
+ lt->reentrancy = 0;
+ }
+
+ if (lt->reentrancy < AST_MAX_REENTRANCY) {
+ lt->file[lt->reentrancy] = NULL;
+ lt->lineno[lt->reentrancy] = 0;
+ lt->func[lt->reentrancy] = NULL;
+ lt->thread[lt->reentrancy] = 0;
+ }
+
+#ifdef HAVE_BKTR
+ if (lt->reentrancy) {
+ bt = <->backtrace[lt->reentrancy - 1];
+ }
+#endif
+ ast_reentrancy_unlock(lt);
+
+ if (t->tracking) {
#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));
@@ -690,7 +700,8 @@
ast_cond_t *cond, ast_mutex_t *t)
{
int res;
- int canlog = strcmp(filename, "logger.c") & t->track;
+ struct ast_lock_track *lt= &t->track;
+ int canlog = strcmp(filename, "logger.c") & t->tracking;
#ifdef HAVE_BKTR
struct ast_bt *bt = NULL;
#endif
@@ -699,7 +710,7 @@
if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
__ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
filename, lineno, func, mutex_name);
- res = __ast_pthread_mutex_init(t->track, filename, lineno, func, mutex_name, t);
+ res = __ast_pthread_mutex_init(t->tracking, filename, lineno, func, mutex_name, t);
if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
__ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized and unable to initialize.\n",
filename, lineno, func, mutex_name);
@@ -708,39 +719,39 @@
}
#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
- ast_reentrancy_lock(t);
- if (t->reentrancy && (t->thread[t->reentrancy-1] != pthread_self())) {
+ ast_reentrancy_lock(lt);
+ if (lt->reentrancy && (lt->thread[lt->reentrancy-1] != pthread_self())) {
__ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
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);
+ lt->file[lt->reentrancy-1], lt->lineno[lt->reentrancy-1], lt->func[lt->reentrancy-1], mutex_name);
+#ifdef HAVE_BKTR
+ __dump_backtrace(<->backtrace[lt->reentrancy-1], canlog);
#endif
DO_THREAD_CRASH;
}
- if (--t->reentrancy < 0) {
+ if (--lt->reentrancy < 0) {
__ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
filename, lineno, func, mutex_name);
- t->reentrancy = 0;
- }
-
- if (t->reentrancy < AST_MAX_REENTRANCY) {
- t->file[t->reentrancy] = NULL;
- t->lineno[t->reentrancy] = 0;
- 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) {
+ lt->reentrancy = 0;
+ }
+
+ if (lt->reentrancy < AST_MAX_REENTRANCY) {
+ lt->file[lt->reentrancy] = NULL;
+ lt->lineno[lt->reentrancy] = 0;
+ lt->func[lt->reentrancy] = NULL;
+ lt->thread[lt->reentrancy] = 0;
+ }
+
+#ifdef HAVE_BKTR
+ if (lt->reentrancy) {
+ bt = <->backtrace[lt->reentrancy - 1];
+ }
+#endif
+ ast_reentrancy_unlock(lt);
+
+ if (t->tracking) {
#ifdef HAVE_BKTR
ast_remove_lock_info(&t->mutex, bt);
#else
@@ -753,24 +764,24 @@
filename, lineno, func, strerror(res));
DO_THREAD_CRASH;
} else {
- ast_reentrancy_lock(t);
- if (t->reentrancy < AST_MAX_REENTRANCY) {
- t->file[t->reentrancy] = filename;
- 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++;
+ ast_reentrancy_lock(lt);
+ if (lt->reentrancy < AST_MAX_REENTRANCY) {
+ lt->file[lt->reentrancy] = filename;
+ lt->lineno[lt->reentrancy] = lineno;
+ lt->func[lt->reentrancy] = func;
+ lt->thread[lt->reentrancy] = pthread_self();
+#ifdef HAVE_BKTR
+ ast_bt_get_addresses(<->backtrace[lt->reentrancy]);
+ bt = <->backtrace[lt->reentrancy];
+#endif
+ lt->reentrancy++;
} else {
__ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
filename, lineno, func, mutex_name);
}
- ast_reentrancy_unlock(t);
-
- if (t->track) {
+ ast_reentrancy_unlock(lt);
+
+ if (t->tracking) {
#ifdef HAVE_BKTR
ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, &t->mutex, bt);
#else
@@ -787,7 +798,8 @@
ast_mutex_t *t, const struct timespec *abstime)
{
int res;
- int canlog = strcmp(filename, "logger.c") & t->track;
+ struct ast_lock_track *lt = &t->track;
+ int canlog = strcmp(filename, "logger.c") & t->tracking;
#ifdef HAVE_BKTR
struct ast_bt *bt = NULL;
#endif
@@ -796,7 +808,7 @@
if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
__ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
filename, lineno, func, mutex_name);
- res = __ast_pthread_mutex_init(t->track, filename, lineno, func, mutex_name, t);
+ res = __ast_pthread_mutex_init(t->tracking, filename, lineno, func, mutex_name, t);
if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
__ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized and unable to initialize.\n",
filename, lineno, func, mutex_name);
@@ -805,67 +817,68 @@
}
#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
- ast_reentrancy_lock(t);
- if (t->reentrancy && (t->thread[t->reentrancy-1] != pthread_self())) {
+ ast_reentrancy_lock(lt);
+ if (lt->reentrancy && (lt->thread[lt->reentrancy-1] != pthread_self())) {
__ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
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);
+ lt->file[lt->reentrancy-1], lt->lineno[lt->reentrancy-1], lt->func[lt->reentrancy-1], mutex_name);
+#ifdef HAVE_BKTR
+ __dump_backtrace(<->backtrace[lt->reentrancy-1], canlog);
#endif
DO_THREAD_CRASH;
}
- if (--t->reentrancy < 0) {
+ if (--lt->reentrancy < 0) {
__ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
filename, lineno, func, mutex_name);
- t->reentrancy = 0;
- }
-
- if (t->reentrancy < AST_MAX_REENTRANCY) {
- t->file[t->reentrancy] = NULL;
- t->lineno[t->reentrancy] = 0;
- 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)
+ lt->reentrancy = 0;
+ }
+
+ if (lt->reentrancy < AST_MAX_REENTRANCY) {
+ lt->file[lt->reentrancy] = NULL;
+ lt->lineno[lt->reentrancy] = 0;
+ lt->func[lt->reentrancy] = NULL;
+ lt->thread[lt->reentrancy] = 0;
+ }
+#ifdef HAVE_BKTR
+ if (lt->reentrancy) {
+ bt = <->backtrace[lt->reentrancy - 1];
+ }
+#endif
+ ast_reentrancy_unlock(lt);
+
+ if (t->tracking) {
#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",
filename, lineno, func, strerror(res));
DO_THREAD_CRASH;
} else {
- ast_reentrancy_lock(t);
- if (t->reentrancy < AST_MAX_REENTRANCY) {
- t->file[t->reentrancy] = filename;
- 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++;
+ ast_reentrancy_lock(lt);
+ if (lt->reentrancy < AST_MAX_REENTRANCY) {
+ lt->file[lt->reentrancy] = filename;
+ lt->lineno[lt->reentrancy] = lineno;
+ lt->func[lt->reentrancy] = func;
+ lt->thread[lt->reentrancy] = pthread_self();
+#ifdef HAVE_BKTR
+ ast_bt_get_addresses(<->backtrace[lt->reentrancy]);
+ bt = <->backtrace[lt->reentrancy];
+#endif
+ lt->reentrancy++;
} else {
__ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
filename, lineno, func, mutex_name);
}
- ast_reentrancy_unlock(t);
-
- if (t->track) {
+ ast_reentrancy_unlock(lt);
+
+ if (t->tracking) {
#ifdef HAVE_BKTR
ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, &t->mutex, bt);
#else
@@ -889,15 +902,17 @@
#define ast_cond_timedwait(cond, mutex, time) __ast_cond_timedwait(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #mutex, cond, mutex, time)
struct ast_rwlock_info {
+ /*! Track which thread holds this lock */
+ struct ast_lock_track track;
+ unsigned int tracking:1;
pthread_rwlock_t lock;
-#ifdef HAVE_BKTR
- struct ast_bt backtrace;
-#endif
};
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_init(rwlock) __ast_rwlock_init(1, __FILE__, __LINE__, __PRETTY_FUNCTION__, #rwlock, rwlock)
+#define ast_rwlock_init_notracking(rwlock) __ast_rwlock_init(0, __FILE__, __LINE__, __PRETTY_FUNCTION__, #rwlock, rwlock)
+
#define ast_rwlock_destroy(rwlock) __ast_rwlock_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #rwlock, rwlock)
#define ast_rwlock_unlock(a) _ast_rwlock_unlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define ast_rwlock_rdlock(a) _ast_rwlock_rdlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
@@ -905,244 +920,486 @@
#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 */
+#define __AST_RWLOCK_INIT_VALUE PTHREAD_RWLOCK_INITIALIZER
#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 */
+#define __AST_RWLOCK_INIT_VALUE {0}
#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)
+#define AST_RWLOCK_INIT_VALUE \
+ { AST_LOCK_TRACK_INIT_VALUE, 1, __AST_RWLOCK_INIT_VALUE }
+#define AST_RWLOCK_INIT_VALUE_NOTRACKING \
+ { AST_LOCK_TRACK_INIT_VALUE, 0, __AST_RWLOCK_INIT_VALUE }
+
+static inline int __ast_rwlock_init(int tracking, const char *filename, int lineno, const char *func, const char *rwlock_name, ast_rwlock_t *t)
{
int res;
+ struct ast_lock_track *lt= &t->track;
pthread_rwlockattr_t attr;
+
#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
- int canlog = strcmp(filename, "logger.c");
-
- if (*prwlock != ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
+ int canlog = strcmp(filename, "logger.c") & t->tracking;
+
+ if (t->lock != ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
__ast_mutex_logger("%s line %d (%s): Warning: rwlock '%s' is already initialized.\n",
filename, lineno, func, rwlock_name);
return 0;
}
#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
+
+ ast_reentrancy_init(lt);
+ t->tracking = tracking;
pthread_rwlockattr_init(&attr);
#ifdef HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NP
pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NP);
#endif
- res = pthread_rwlock_init(&prwlock->lock, &attr);
+ res = pthread_rwlock_init(&t->lock, &attr);
pthread_rwlockattr_destroy(&attr);
return res;
}
-
-static inline int __ast_rwlock_destroy(const char *filename, int lineno, const char *func, const char *rwlock_name, ast_rwlock_t *prwlock)
+static inline int __ast_rwlock_destroy(const char *filename, int lineno, const char *func, const char *rwlock_name, ast_rwlock_t *t)
{
int res;
- int canlog = strcmp(filename, "logger.c");
+ struct ast_lock_track *lt = &t->track;
+ int canlog = strcmp(filename, "logger.c") & t->tracking;
#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
- if (*prwlock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
+ if (t->lock == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
__ast_mutex_logger("%s line %d (%s): Warning: rwlock '%s' is uninitialized.\n",
filename, lineno, func, rwlock_name);
return 0;
}
#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
- if ((res = pthread_rwlock_destroy(&prwlock->lock)))
+ if ((res = pthread_rwlock_destroy(&t->lock))) {
__ast_mutex_logger("%s line %d (%s): Error destroying rwlock %s: %s\n",
filename, lineno, func, rwlock_name, strerror(res));
+ }
+ ast_reentrancy_lock(lt);
+ lt->file[0] = filename;
+ lt->lineno[0] = lineno;
+ lt->func[0] = func;
+ lt->reentrancy = 0;
+ lt->thread[0] = 0;
+#ifdef HAVE_BKTR
+ memset(<->backtrace[0], 0, sizeof(lt->backtrace[0]));
+#endif
+ ast_reentrancy_unlock(lt);
+ delete_reentrancy_cs(lt);
return res;
}
-
-static inline int _ast_rwlock_unlock(ast_rwlock_t *lock, const char *name,
- const char *file, int line, const char *func)
+static inline int _ast_rwlock_unlock(ast_rwlock_t *t, const char *name,
+ const char *filename, int line, const char *func)
{
int res;
+ struct ast_lock_track *lt = &t->track;
+ int canlog = strcmp(filename, "logger.c") & t->tracking;
+#ifdef HAVE_BKTR
+ struct ast_bt *bt = NULL;
+#endif
+
+
#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
- int canlog = strcmp(file, "logger.c");
-
- if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
+ if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
__ast_mutex_logger("%s line %d (%s): Warning: rwlock '%s' is uninitialized.\n",
- file, line, func, name);
- res = __ast_rwlock_init(file, line, func, name, lock);
- if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
+ filename, line, func, name);
+ res = __ast_rwlock_init(t->tracking, filename, line, func, name, t);
+ if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
__ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
- file, line, func, name);
+ filename, line, func, name);
}
return res;
}
#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
- 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
+ ast_reentrancy_lock(lt);
+ if (lt->reentrancy && (lt->thread[lt->reentrancy-1] != pthread_self())) {
+ __ast_mutex_logger("%s line %d (%s): attempted unlock rwlock '%s' without owning it!\n",
+ filename, line, func, name);
+ __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
+ lt->file[lt->reentrancy-1], lt->lineno[lt->reentrancy-1], lt->func[lt->reentrancy-1], name);
+#ifdef HAVE_BKTR
+ __dump_backtrace(<->backtrace[lt->reentrancy-1], canlog);
+#endif
+ DO_THREAD_CRASH;
+ }
+
+ if (--lt->reentrancy < 0) {
+ __ast_mutex_logger("%s line %d (%s): rwlock '%s' freed more times than we've locked!\n",
+ filename, line, func, name);
+ lt->reentrancy = 0;
+ }
+
+ if (lt->reentrancy < AST_MAX_REENTRANCY) {
+ lt->file[lt->reentrancy] = NULL;
+ lt->lineno[lt->reentrancy] = 0;
+ lt->func[lt->reentrancy] = NULL;
+ lt->thread[lt->reentrancy] = 0;
+ }
+
+#ifdef HAVE_BKTR
+ if (lt->reentrancy) {
+ bt = <->backtrace[lt->reentrancy - 1];
+ }
+#endif
+ ast_reentrancy_unlock(lt);
+
+ if (t->tracking) {
+#ifdef HAVE_BKTR
+ ast_remove_lock_info(&t->lock, bt);
+#else
+ ast_remove_lock_info(&t->lock);
+#endif
+ }
+
+ if ((res = pthread_rwlock_unlock(&t->lock))) {
+ __ast_mutex_logger("%s line %d (%s): Error releasing rwlock: %s\n",
+ filename, line, func, strerror(res));
+ DO_THREAD_CRASH;
+ }
+
return res;
}
-
-static inline int _ast_rwlock_rdlock(ast_rwlock_t *lock, const char *name,
- const char *file, int line, const char *func)
+static inline int _ast_rwlock_rdlock(ast_rwlock_t *t, const char *name,
+ const char *filename, int line, const char *func)
{
int res;
+ struct ast_lock_track *lt = &t->track;
+ int canlog = strcmp(filename, "logger.c") & t->tracking;
+#ifdef HAVE_BKTR
+ struct ast_bt *bt = NULL;
+#endif
+
#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
- int canlog = strcmp(file, "logger.c");
-
- if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
+ if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
/* Don't warn abount uninitialized lock.
* Simple try to initialize it.
* May be not needed in linux system.
*/
- res = __ast_rwlock_init(file, line, func, name, lock);
- if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
+ res = __ast_rwlock_init(t->tracking, filename, line, func, name, t);
+ if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
__ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
- file, line, func, name);
+ filename, line, func, name);
return res;
}
}
#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);
-#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
+
+ if (t->tracking) {
+#ifdef HAVE_BKTR
+ ast_reentrancy_lock(lt);
+ ast_bt_get_addresses(<->backtrace[lt->reentrancy]);
+ bt = <->backtrace[lt->reentrancy];
+ ast_reentrancy_unlock(lt);
+ ast_store_lock_info(AST_RDLOCK, filename, line, func, name, &t->lock, bt);
+#else
+ ast_store_lock_info(AST_RDLOCK, filename, line, func, name, &t->lock);
+#endif
+ }
+
+#ifdef DETECT_DEADLOCKS
+ {
+ time_t seconds = time(NULL);
+ time_t wait_time, reported_wait = 0;
+ do {
+ res = pthread_rwlock_tryrdlock(&t->lock);
+ if (res == EBUSY) {
+ wait_time = time(NULL) - seconds;
+ if (wait_time > reported_wait && (wait_time % 5) == 0) {
+ __ast_mutex_logger("%s line %d (%s): Deadlock? waited %d sec for readlock '%s'?\n",
+ filename, line, func, (int)wait_time, name);
+ ast_reentrancy_lock(lt);
+#ifdef HAVE_BKTR
+ __dump_backtrace(<->backtrace[lt->reentrancy], canlog);
+#endif
+ __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
+ lt->file[lt->reentrancy-1], lt->lineno[lt->reentrancy-1],
+ lt->func[lt->reentrancy-1], name);
+#ifdef HAVE_BKTR
+ __dump_backtrace(<->backtrace[lt->reentrancy-1], canlog);
+#endif
+ ast_reentrancy_unlock(lt);
+ reported_wait = wait_time;
+ }
+ usleep(200);
+ }
+ } while (res == EBUSY);
+ }
+#else /* !DETECT_DEADLOCKS */
+ res = pthread_rwlock_rdlock(&t->lock);
+#endif /* !DETECT_DEADLOCKS */
+
+ if (!res) {
+ ast_reentrancy_lock(lt);
+ if (lt->reentrancy < AST_MAX_REENTRANCY) {
+ lt->file[lt->reentrancy] = filename;
+ lt->lineno[lt->reentrancy] = line;
+ lt->func[lt->reentrancy] = func;
+ lt->thread[lt->reentrancy] = pthread_self();
+ lt->reentrancy++;
+ } else {
+ __ast_mutex_logger("%s line %d (%s): read lock '%s' really deep reentrancy!\n",
+ filename, line, func, name);
+ }
+ ast_reentrancy_unlock(lt);
+ if (t->tracking) {
+ ast_mark_lock_acquired(&t->lock);
+ }
+ } else {
+#ifdef HAVE_BKTR
+ if (lt->reentrancy) {
+ ast_reentrancy_lock(lt);
+ bt = <->backtrace[lt->reentrancy-1];
+ ast_reentrancy_unlock(lt);
+ } else {
+ bt = NULL;
+ }
+ if (t->tracking) {
+ ast_remove_lock_info(&t->lock, bt);
+ }
+#else
+ if (t->tracking) {
+ ast_remove_lock_info(&t->lock);
+ }
+#endif
+ __ast_mutex_logger("%s line %d (%s): Error obtaining read lock: %s\n",
+ filename, line, func, strerror(res));
+ DO_THREAD_CRASH;
+ }
return res;
}
-
-static inline int _ast_rwlock_wrlock(ast_rwlock_t *lock, const char *name,
- const char *file, int line, const char *func)
+static inline int _ast_rwlock_wrlock(ast_rwlock_t *t, const char *name,
+ const char *filename, int line, const char *func)
{
int res;
+ struct ast_lock_track *lt = &t->track;
+ int canlog = strcmp(filename, "logger.c") & t->tracking;
+#ifdef HAVE_BKTR
+ struct ast_bt *bt = NULL;
+#endif
+
#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
- int canlog = strcmp(file, "logger.c");
-
- if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
+ if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
/* Don't warn abount uninitialized lock.
* Simple try to initialize it.
* May be not needed in linux system.
*/
- res = __ast_rwlock_init(file, line, func, name, lock);
- if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
+ res = __ast_rwlock_init(t->tracking, filename, line, func, name, t);
+ if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
__ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
- file, line, func, name);
+ filename, line, func, name);
return res;
}
}
#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);
-#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
+
+ if (t->tracking) {
+#ifdef HAVE_BKTR
+ ast_reentrancy_lock(lt);
+ ast_bt_get_addresses(<->backtrace[lt->reentrancy]);
+ bt = <->backtrace[lt->reentrancy];
+ ast_reentrancy_unlock(lt);
+ ast_store_lock_info(AST_WRLOCK, filename, line, func, name, &t->lock, bt);
+#else
+ ast_store_lock_info(AST_WRLOCK, filename, line, func, name, &t->lock);
+#endif
+ }
+#ifdef DETECT_DEADLOCKS
+ {
+ time_t seconds = time(NULL);
+ time_t wait_time, reported_wait = 0;
+ do {
+ res = pthread_rwlock_trywrlock(&t->lock);
+ if (res == EBUSY) {
+ wait_time = time(NULL) - seconds;
+ if (wait_time > reported_wait && (wait_time % 5) == 0) {
+ __ast_mutex_logger("%s line %d (%s): Deadlock? waited %d sec for writelock '%s'?\n",
+ filename, line, func, (int)wait_time, name);
+ ast_reentrancy_lock(lt);
+#ifdef HAVE_BKTR
+ __dump_backtrace(<->backtrace[lt->reentrancy], canlog);
+#endif
+ __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
+ lt->file[lt->reentrancy-1], lt->lineno[lt->reentrancy-1],
+ lt->func[lt->reentrancy-1], name);
+#ifdef HAVE_BKTR
+ __dump_backtrace(<->backtrace[lt->reentrancy-1], canlog);
+#endif
+ ast_reentrancy_unlock(lt);
+ reported_wait = wait_time;
+ }
+ usleep(200);
+ }
+ } while (res == EBUSY);
+ }
+#else /* !DETECT_DEADLOCKS */
+ res = pthread_rwlock_wrlock(&t->lock);
+#endif /* !DETECT_DEADLOCKS */
+
+ if (!res) {
+ ast_reentrancy_lock(lt);
+ if (lt->reentrancy < AST_MAX_REENTRANCY) {
+ lt->file[lt->reentrancy] = filename;
+ lt->lineno[lt->reentrancy] = line;
+ lt->func[lt->reentrancy] = func;
+ lt->thread[lt->reentrancy] = pthread_self();
+ lt->reentrancy++;
+ } else {
+ __ast_mutex_logger("%s line %d (%s): write lock '%s' really deep reentrancy!\n",
+ filename, line, func, name);
+ }
+ ast_reentrancy_unlock(lt);
+ if (t->tracking) {
+ ast_mark_lock_acquired(&t->lock);
+ }
+ } else {
+#ifdef HAVE_BKTR
+ if (lt->reentrancy) {
[... 337 lines stripped ...]
More information about the asterisk-commits
mailing list