[asterisk-commits] russell: branch russell/debug_threads r77843 - /team/russell/debug_threads/
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Tue Jul 31 15:12:27 CDT 2007
Author: russell
Date: Tue Jul 31 15:12:26 2007
New Revision: 77843
URL: http://svn.digium.com/view/asterisk?view=rev&rev=77843
Log:
Introduce a "core show locks" CLI command. This CLI command will list which
locks each active thread on the system currently holds.
Modified:
team/russell/debug_threads/utils.c
Modified: team/russell/debug_threads/utils.c
URL: http://svn.digium.com/view/asterisk/team/russell/debug_threads/utils.c?view=diff&rev=77843&r1=77842&r2=77843
==============================================================================
--- team/russell/debug_threads/utils.c (original)
+++ team/russell/debug_threads/utils.c Tue Jul 31 15:12:26 2007
@@ -47,6 +47,8 @@
#include "asterisk/md5.h"
#include "asterisk/options.h"
#include "asterisk/compat.h"
+#include "asterisk/linkedlists.h"
+#include "asterisk/cli.h"
#define AST_API_MODULE /* ensure that inlinable API functions will be built in this module if required */
#include "asterisk/strings.h"
@@ -472,12 +474,6 @@
return inet_ntop(AF_INET, &ia, buf, bufsiz);
}
-int ast_utils_init(void)
-{
- base64_init();
- return 0;
-}
-
#ifndef __linux__
#undef pthread_create /* For ast_pthread_create function only */
#endif /* !__linux__ */
@@ -499,9 +495,17 @@
/*! \brief A reasonable maximum number of locks a thread would be holding ... */
#define AST_MAX_LOCKS 16
+/* Allow direct use of pthread_mutex_t */
+#undef pthread_mutex_t
+#undef pthread_mutex_lock
+#undef pthread_mutex_unlock
+#undef pthread_mutex_init
+#undef pthread_mutex_destroy
+
/*! \brief Keep track of which locks a thread holds */
struct thr_lock_info {
pthread_t thread_id;
+ const char *thread_name;
struct {
const char *file;
int line_num;
@@ -511,12 +515,25 @@
int times_locked;
} locks[AST_MAX_LOCKS];
unsigned int num_locks;
+ /* Protects the contents of the locks member
+ * Intentionally not ast_mutex_t */
+ pthread_mutex_t lock;
+ AST_LIST_ENTRY(thr_lock_info) entry;
};
+AST_RWLOCK_DEFINE_STATIC(lock_infos_rwlock);
+static AST_LIST_HEAD_NOLOCK_STATIC(lock_infos, thr_lock_info);
+
static void lock_info_destroy(void *data)
{
struct thr_lock_info *lock_info = data;
+ pthread_rwlock_wrlock(&lock_infos_rwlock);
+ AST_LIST_REMOVE(&lock_infos, lock_info, entry);
+ pthread_rwlock_unlock(&lock_infos_rwlock);
+
+ pthread_mutex_destroy(&lock_info->lock);
+ free((void *) lock_info->thread_name);
free(lock_info);
}
@@ -530,10 +547,13 @@
if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
return;
+
+ pthread_mutex_lock(&lock_info->lock);
for (i = 0; i < lock_info->num_locks; i++) {
if (lock_info->locks[i].lock_addr == lock_addr) {
lock_info->locks[i].times_locked++;
+ pthread_mutex_unlock(&lock_info->lock);
return;
}
}
@@ -542,6 +562,7 @@
/* Can't use ast_log here, because it will cause infinite recursion */
fprintf(stderr, "XXX ERROR XXX A thread holds more locks than '%d'."
" Increase AST_MAX_LOCKS!\n", AST_MAX_LOCKS);
+ pthread_mutex_unlock(&lock_info->lock);
return;
}
@@ -552,6 +573,8 @@
lock_info->locks[i].lock_addr = lock_addr;
lock_info->locks[i].times_locked = 1;
lock_info->num_locks++;
+
+ pthread_mutex_unlock(&lock_info->lock);
}
void ast_remove_lock_info(void *lock_addr)
@@ -561,17 +584,23 @@
if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
return;
+
+ pthread_mutex_lock(&lock_info->lock);
for (i = lock_info->num_locks - 1; i >= 0; i--) {
if (lock_info->locks[i].lock_addr == lock_addr)
break;
}
- if (i == -1) /* Lock not found :( */
+ if (i == -1) {
+ /* Lock not found :( */
+ pthread_mutex_unlock(&lock_info->lock);
return;
+ }
if (lock_info->locks[i].times_locked > 1) {
lock_info->locks[i].times_locked--;
+ pthread_mutex_unlock(&lock_info->lock);
return;
}
@@ -582,7 +611,56 @@
}
lock_info->num_locks--;
-}
+
+ pthread_mutex_unlock(&lock_info->lock);
+}
+
+static int handle_show_locks(int fd, int argc, char *argv[])
+{
+ struct thr_lock_info *lock_info;
+
+ ast_cli(fd, "\n"
+ "=======================================================================\n"
+ "=== Currently Held Locks ==============================================\n"
+ "=======================================================================\n"
+ "===\n"
+ "=== <file> <line num> <function> <lock name> <lock addr> (times locked)\n"
+ "===\n");
+
+ pthread_rwlock_rdlock(&lock_infos_rwlock);
+ AST_LIST_TRAVERSE(&lock_infos, lock_info, entry) {
+ int i;
+ ast_cli(fd, "=== Thread ID: %d (%s)\n", (int) lock_info->thread_id,
+ lock_info->thread_name);
+ pthread_mutex_lock(&lock_info->lock);
+ for (i = 0; i < lock_info->num_locks; i++) {
+ ast_cli(fd, "=== ---> Lock #%d: %s %d %s %s %p (%d)\n", i,
+ lock_info->locks[i].file, lock_info->locks[i].line_num,
+ lock_info->locks[i].func, lock_info->locks[i].lock_name,
+ lock_info->locks[i].lock_addr,
+ lock_info->locks[i].times_locked);
+ }
+ pthread_mutex_unlock(&lock_info->lock);
+ ast_cli(fd, "=== -------------------------------------------------------------------\n"
+ "===\n");
+ }
+ pthread_rwlock_unlock(&lock_infos_rwlock);
+
+ ast_cli(fd, "=======================================================================\n"
+ "\n");
+
+ return 0;
+}
+
+static char show_locks_help[] =
+"Usage: core show locks\n"
+" This command is for lock debugging. It prints out which locks\n"
+"are owned by each active thread.\n";
+
+static struct ast_cli_entry utils_cli[] = {
+ { { "core", "show", "locks", NULL }, handle_show_locks,
+ "Show which locks are locked by which thread", show_locks_help },
+};
#endif /* DEBUG_THREADS */
@@ -613,6 +691,12 @@
return NULL;
lock_info->thread_id = pthread_self();
+ lock_info->thread_name = strdup(a.name);
+ pthread_mutex_init(&lock_info->lock, NULL);
+
+ pthread_rwlock_wrlock(&lock_infos_rwlock); /* Intentionally not the wrapper */
+ AST_LIST_INSERT_TAIL(&lock_infos, lock_info, entry);
+ pthread_rwlock_unlock(&lock_infos_rwlock); /* Intentionally not the wrapper */
#endif /* DEBUG_THREADS */
@@ -1083,3 +1167,14 @@
ast_mutex_unlock(&fetchadd_m);
return ret;
}
+
+int ast_utils_init(void)
+{
+ base64_init();
+#ifdef DEBUG_THREADS
+ ast_cli_register_multiple(utils_cli, sizeof(utils_cli) / sizeof(utils_cli[0]));
+#endif
+ return 0;
+}
+
+
More information about the asterisk-commits
mailing list