add 'show threads' and 'show profile' commands.

These are momstly debugging tools for developers,
a bit documented in the header files (utils.h),
although more documentation is definitely necessary.

The performance impact is close to zero(*) so there is no
need to compile it conditionally.
(*) not completely true - thread destruction still needs
to search a list _but_ this can be easily optimized if we
end up with hundreds of active threads (in which case, though,
the problem is clearly elsewhere).



git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@19544 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Luigi Rizzo
2006-04-12 20:40:46 +00:00
parent 8f09c4345f
commit 2876a25505
7 changed files with 354 additions and 4 deletions

47
utils.c
View File

@@ -509,8 +509,42 @@ 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)
/*
* 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 with the MAC.
*/
static void *dummy_start(void *data)
{
void *ret;
struct thr_arg a = *((struct thr_arg *)data); /* make a local copy */
free(data);
ast_register_thread(a.name);
pthread_cleanup_push(ast_unregister_thread, (void *)pthread_self()); /* on unregister */
ret = a.start_routine(a.data);
pthread_cleanup_pop(1);
return ret;
}
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)
{
struct thr_arg *a;
pthread_attr_t lattr;
if (!attr) {
pthread_attr_init(&lattr);
@@ -534,6 +568,17 @@ int ast_pthread_create_stack(pthread_t *thread, pthread_attr_t *attr, void *(*st
errno = pthread_attr_setstacksize(attr, stacksize);
if (errno)
ast_log(LOG_WARNING, "pthread_attr_setstacksize returned non-zero: %s\n", strerror(errno));
a = ast_malloc(sizeof(*a));
if (!a)
ast_log(LOG_WARNING, "no memory, thread %s will not be listed\n", start_fn);
else { /* remap parameters */
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;
}
return pthread_create(thread, attr, start_routine, data); /* We're in ast_pthread_create, so it's okay */
}