Index: utils.c
===================================================================
--- utils.c	(revision 7604)
+++ utils.c	(working copy)
@@ -484,8 +484,32 @@ int ast_utils_init(void)
 #undef pthread_create /* For ast_pthread_create function only */
 #endif /* !__linux__ */
 
-int ast_pthread_create_stack(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *data, size_t stacksize)
+void ast_register_thread(char *name);
+void ast_unregister_thread(void *id);
+
+struct thr_arg {
+	void *(*start_routine)(void *);
+	void *data;
+	char *name;
+};
+
+void *dummy_start(void *data);
+void *dummy_start(void *data)
+{
+	struct thr_arg a = *((struct thr_arg *)data);	/* make a local copy */
+	free(data);
+	/* ast_log(LOG_WARNING, "started %s at %p\n", a.name, pthread_self()); */
+	ast_register_thread(a.name);
+	pthread_cleanup_push(ast_unregister_thread, pthread_self());	/* on unregister */
+	return a.start_routine(a.data);
+}
+
+int ast_pthread_create_stack(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *data, size_t stacksize,
+	const char *file, const char *caller, int line, const char *start_fn)
 {
+	int retval;
+	struct thr_arg *a;
+
 	pthread_attr_t lattr;
 	if (!attr) {
 		pthread_attr_init(&lattr);
@@ -509,7 +533,19 @@ int ast_pthread_create_stack(pthread_t *
 	errno = pthread_attr_setstacksize(attr, stacksize);
 	if (errno)
 		ast_log(LOG_WARNING, "pthread_attr_setstacksize returned non-zero: %s\n", strerror(errno));
-	return pthread_create(thread, attr, start_routine, data); /* We're in ast_pthread_create, so it's okay */
+	a = NULL;
+#if 1
+	a = malloc(sizeof(*a));
+	a->start_routine = start_routine;
+	a->data = data;
+	start_routine = dummy_start;
+	asprintf(&a->name, "%-20s started at [%5d] %s %s()",
+		start_fn, line, file, caller);
+	data = a;
+	/* ast_log(LOG_WARNING, "about to start %s\n", a->name); */
+#endif
+	retval = pthread_create(thread, attr, start_routine, data); /* We're in ast_pthread_create, so it's okay */
+	return retval;
 }
 
 int ast_wait_for_input(int fd, int ms)
Index: include/asterisk/utils.h
===================================================================
--- include/asterisk/utils.h	(revision 7604)
+++ include/asterisk/utils.h	(working copy)
@@ -220,8 +220,10 @@ static force_inline int inaddrcmp(const 
 }
 
 #define AST_STACKSIZE 256 * 1024
-#define ast_pthread_create(a,b,c,d) ast_pthread_create_stack(a,b,c,d,0)
-int ast_pthread_create_stack(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *data, size_t stacksize);
+#define ast_pthread_create(a,b,c,d) ast_pthread_create_stack(a,b,c,d,0, \
+	 __FILE__, __FUNCTION__, __LINE__, #c)
+int ast_pthread_create_stack(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *data, size_t stacksize,
+	const char *file, const char *caller, int line, const char *start_fn);
 
 /*!
 	\brief Process a string to find and replace characters
Index: asterisk.c
===================================================================
--- asterisk.c	(revision 7604)
+++ asterisk.c	(working copy)
@@ -254,6 +254,71 @@ void ast_unregister_file_version(const c
 		free(find);
 }
 
+struct thread_list_t {
+	AST_LIST_ENTRY(thread_list_t) list;
+	char *name;
+	const void *id;
+};
+
+static AST_LIST_HEAD_STATIC(thread_list, thread_list_t);
+
+static char show_threads_help[] =
+"Usage: show threads\n"
+"       Shows existing threads.\n";
+
+void ast_register_thread(char *name);
+void ast_register_thread(char *name)
+{ 
+        struct thread_list_t *new;
+
+        new = calloc(1, sizeof(*new));
+        if (!new)
+                return;
+	/* ast_log(LOG_WARNING, "registering thread <%s>\n", name); */
+        new->id = pthread_self();
+        new->name = name; /* this was a copy already */
+        AST_LIST_LOCK(&thread_list);
+        AST_LIST_INSERT_HEAD(&thread_list, new, list);
+        AST_LIST_UNLOCK(&thread_list);
+}
+
+void ast_unregister_thread(void *id);
+void ast_unregister_thread(void *id)
+{
+        struct thread_list_t *x;
+
+	/* ast_log(LOG_WARNING, "thread %p destroyed\n", id); */
+        AST_LIST_LOCK(&thread_list);
+        AST_LIST_TRAVERSE_SAFE_BEGIN(&thread_list, x, list) {
+                if (x->id == id) {
+                        AST_LIST_REMOVE_CURRENT(&thread_list, list);
+                        break;
+                }
+        }
+        AST_LIST_TRAVERSE_SAFE_END;
+        AST_LIST_UNLOCK(&thread_list);
+        if (x) {
+		free(x->name);
+		free(x);
+	}
+}
+
+
+static int handle_show_threads(int fd, int argc, char *argv[])
+{
+	int count = 0;
+	struct thread_list_t *iterator;
+
+	AST_LIST_LOCK(&thread_list);
+	AST_LIST_TRAVERSE(&thread_list, iterator, list) {
+		ast_cli(fd, "%p %s\n", iterator->id, iterator->name);
+		count++;
+	}
+	AST_LIST_UNLOCK(&thread_list);
+	ast_cli(fd, "%d threads listed.\n", count);
+	return 0;
+}
+
 static char show_version_files_help[] = 
 "Usage: show version files [like <pattern>]\n"
 "       Shows the revision numbers of the files used to build this copy of Asterisk.\n"
@@ -1142,6 +1209,8 @@ static struct ast_cli_entry core_cli[] =
 #if !defined(LOW_MEMORY)
 	{ { "show", "version", "files", NULL }, handle_show_version_files,
 	  "Show versions of files used to build Asterisk", show_version_files_help, complete_show_version_files },
+	{ { "show", "threads", NULL }, handle_show_threads,
+	  "Show running threads", show_threads_help, NULL },
 #endif /* ! LOW_MEMORY */
 };
 
