[asterisk-commits] russell: branch russell/debug_threads r77822 - in /team/russell/debug_threads...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Jul 31 10:14:32 CDT 2007


Author: russell
Date: Tue Jul 31 10:14:31 2007
New Revision: 77822

URL: http://svn.digium.com/view/asterisk?view=rev&rev=77822
Log:
step 1 ... backport the "core show threads" CLI command.  It's nice to have, but
the real reason is that it provides a common entry point for every thread, and
I'd rather use the same code that is in 1.4/trunk.

Modified:
    team/russell/debug_threads/asterisk.c
    team/russell/debug_threads/include/asterisk/utils.h
    team/russell/debug_threads/utils.c

Modified: team/russell/debug_threads/asterisk.c
URL: http://svn.digium.com/view/asterisk/team/russell/debug_threads/asterisk.c?view=diff&rev=77822&r1=77821&r2=77822
==============================================================================
--- team/russell/debug_threads/asterisk.c (original)
+++ team/russell/debug_threads/asterisk.c Tue Jul 31 10:14:31 2007
@@ -286,6 +286,65 @@
 	AST_LIST_UNLOCK(&file_versions);
 	if (find)
 		free(find);
+}
+
+struct thread_list_t {
+	AST_LIST_ENTRY(thread_list_t) list;
+	char *name;
+	pthread_t id;
+};
+
+static AST_LIST_HEAD_STATIC(thread_list, thread_list_t);
+
+static char show_threads_help[] =
+"Usage: core show threads\n"
+"       List threads currently active in the system.\n";
+
+void ast_register_thread(char *name)
+{ 
+	struct thread_list_t *new = calloc(1, sizeof(*new));
+
+	if (!new)
+		return;
+	new->id = pthread_self();
+	new->name = name; /* steal the allocated memory for the thread name */
+	AST_LIST_LOCK(&thread_list);
+	AST_LIST_INSERT_HEAD(&thread_list, new, list);
+	AST_LIST_UNLOCK(&thread_list);
+}
+
+void ast_unregister_thread(void *id)
+{
+	struct thread_list_t *x;
+
+	AST_LIST_LOCK(&thread_list);
+	AST_LIST_TRAVERSE_SAFE_BEGIN(&thread_list, x, list) {
+		if ((void *) 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 *cur;
+
+	AST_LIST_LOCK(&thread_list);
+	AST_LIST_TRAVERSE(&thread_list, cur, list) {
+		ast_cli(fd, "%p %s\n", (void *)cur->id, cur->name);
+		count++;
+	}
+        AST_LIST_UNLOCK(&thread_list);
+	ast_cli(fd, "%d threads listed.\n", count);
+	return 0;
 }
 
 static char show_version_files_help[] = 
@@ -1250,6 +1309,10 @@
 #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 },
+	
+	{ { "core", "show", "threads", NULL },
+	handle_show_threads, "Show running threads",
+	show_threads_help },
 #endif /* ! LOW_MEMORY */
 };
 

Modified: team/russell/debug_threads/include/asterisk/utils.h
URL: http://svn.digium.com/view/asterisk/team/russell/debug_threads/include/asterisk/utils.h?view=diff&rev=77822&r1=77821&r2=77822
==============================================================================
--- team/russell/debug_threads/include/asterisk/utils.h (original)
+++ team/russell/debug_threads/include/asterisk/utils.h Tue Jul 31 10:14:31 2007
@@ -220,8 +220,18 @@
 }
 
 #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);
+
+void ast_register_thread(char *name);
+void ast_unregister_thread(void *id);
+
+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);
+
+#define ast_pthread_create(a, b, c, d) ast_pthread_create_stack(a, b, c, d,			\
+							        0,				\
+	 						        __FILE__, __FUNCTION__,		\
+ 							        __LINE__, #c)
 
 /*!
 	\brief Process a string to find and replace characters

Modified: team/russell/debug_threads/utils.c
URL: http://svn.digium.com/view/asterisk/team/russell/debug_threads/utils.c?view=diff&rev=77822&r1=77821&r2=77822
==============================================================================
--- team/russell/debug_threads/utils.c (original)
+++ team/russell/debug_threads/utils.c Tue Jul 31 10:14:31 2007
@@ -479,13 +479,59 @@
 #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)
-{
-	pthread_attr_t lattr;
+#if !defined(LOW_MEMORY)
+/*
+ * support for 'show threads'. The start routine is wrapped by
+ * dummy_start(), so that ast_register_thread() and
+ * ast_unregister_thread() know the thread identifier.
+ */
+struct thr_arg {
+	void *(*start_routine)(void *);
+	void *data;
+	char *name;
+};
+
+/*
+ * on OS/X, pthread_cleanup_push() and pthread_cleanup_pop()
+ * are odd macros which start and end a block, so they _must_ be
+ * used in pairs (the latter with a '1' argument to call the
+ * handler on exit.
+ * On BSD we don't need this, but we keep it for compatibility.
+ */
+static void *dummy_start(void *data)
+{
+	void *ret;
+	struct thr_arg a = *((struct thr_arg *) data);	/* make a local copy */
+
+	/* note that even though data->name is a pointer to allocated memory,
+	   we are not freeing it here because ast_register_thread is going to
+	   keep a copy of the pointer and then ast_unregister_thread will
+	   free the memory
+	*/
+	free(data);
+	ast_register_thread(a.name);
+	pthread_cleanup_push(ast_unregister_thread, (void *) pthread_self());
+	ret = a.start_routine(a.data);
+	pthread_cleanup_pop(1);
+
+	return ret;
+}
+
+#endif /* !LOW_MEMORY */
+
+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)
+{
+#if !defined(LOW_MEMORY)
+	struct thr_arg *a;
+#endif
+
 	if (!attr) {
-		pthread_attr_init(&lattr);
-		attr = &lattr;
-	}
+		attr = alloca(sizeof(*attr));
+		pthread_attr_init(attr);
+	}
+
 #ifdef __linux__
 	/* On Linux, pthread_attr_init() defaults to PTHREAD_EXPLICIT_SCHED,
 	   which is kind of useless. Change this here to
@@ -494,16 +540,27 @@
 	   This does mean that callers cannot set a different priority using
 	   PTHREAD_EXPLICIT_SCHED in the attr argument; instead they must set
 	   the priority afterwards with pthread_setschedparam(). */
-	errno = pthread_attr_setinheritsched(attr, PTHREAD_INHERIT_SCHED);
-	if (errno)
-		ast_log(LOG_WARNING, "pthread_attr_setinheritsched returned non-zero: %s\n", strerror(errno));
+	if ((errno = pthread_attr_setinheritsched(attr, PTHREAD_INHERIT_SCHED)))
+		ast_log(LOG_WARNING, "pthread_attr_setinheritsched: %s\n", strerror(errno));
 #endif
 
 	if (!stacksize)
 		stacksize = AST_STACKSIZE;
-	errno = pthread_attr_setstacksize(attr, stacksize);
-	if (errno)
-		ast_log(LOG_WARNING, "pthread_attr_setstacksize returned non-zero: %s\n", strerror(errno));
+
+	if ((errno = pthread_attr_setstacksize(attr, stacksize ? stacksize : AST_STACKSIZE)))
+		ast_log(LOG_WARNING, "pthread_attr_setstacksize: %s\n", strerror(errno));
+
+#if !defined(LOW_MEMORY)
+	if ((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;
+	}
+#endif /* !LOW_MEMORY */
+
 	return pthread_create(thread, attr, start_routine, data); /* We're in ast_pthread_create, so it's okay */
 }
 




More information about the asterisk-commits mailing list