![]() |
Home page |
Mailing list |
Docs
Asterisk developer's documentation :: Codename Pineapple
threadstorage.c
Go to the documentation of this file.
00001 /* 00002 * Asterisk -- An open source telephony toolkit. 00003 * 00004 * Copyright (C) 1999 - 2005, Digium, Inc. 00005 * 00006 * Kevin P. Fleming <kpfleming@digium.com> 00007 * 00008 * See http://www.asterisk.org for more information about 00009 * the Asterisk project. Please do not directly contact 00010 * any of the maintainers of this project for assistance; 00011 * the project provides a web site, mailing lists and IRC 00012 * channels for your use. 00013 * 00014 * This program is free software, distributed under the terms of 00015 * the GNU General Public License Version 2. See the LICENSE file 00016 * at the top of the source tree. 00017 */ 00018 00019 /*! \file 00020 * 00021 * \brief Debugging support for thread-local-storage objects 00022 * 00023 * \author Kevin P. Fleming <kpfleming@digium.com> 00024 */ 00025 00026 #include "asterisk.h" 00027 00028 #if defined(DEBUG_THREADLOCALS) 00029 00030 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 49618 $") 00031 00032 #include <stdio.h> 00033 #include <stdlib.h> 00034 #include <string.h> 00035 00036 #include "asterisk/logger.h" 00037 #include "asterisk/strings.h" 00038 #include "asterisk/utils.h" 00039 #include "asterisk/threadstorage.h" 00040 #include "asterisk/linkedlists.h" 00041 #include "asterisk/cli.h" 00042 00043 struct tls_object { 00044 void *key; 00045 size_t size; 00046 const char *file; 00047 const char *function; 00048 unsigned int line; 00049 pthread_t thread; 00050 AST_LIST_ENTRY(tls_object) entry; 00051 }; 00052 00053 static AST_RWLIST_HEAD_STATIC(tls_objects, tls_object); 00054 00055 void __ast_threadstorage_object_add(void *key, size_t len, const char *file, const char *function, unsigned int line) 00056 { 00057 struct tls_object *to; 00058 00059 if (!(to = ast_calloc(sizeof(*to), 1))) 00060 return; 00061 00062 to->key = key; 00063 to->size = len; 00064 to->file = file; 00065 to->function = function; 00066 to->line = line; 00067 to->thread = pthread_self(); 00068 00069 AST_RWLIST_WRLOCK(&tls_objects); 00070 AST_LIST_INSERT_TAIL(&tls_objects, to, entry); 00071 AST_RWLIST_UNLOCK(&tls_objects); 00072 } 00073 00074 void __ast_threadstorage_object_remove(void *key) 00075 { 00076 struct tls_object *to; 00077 00078 AST_RWLIST_WRLOCK(&tls_objects); 00079 AST_LIST_TRAVERSE_SAFE_BEGIN(&tls_objects, to, entry) { 00080 if (to->key == key) { 00081 AST_LIST_REMOVE_CURRENT(&tls_objects, entry); 00082 break; 00083 } 00084 } 00085 AST_LIST_TRAVERSE_SAFE_END; 00086 AST_RWLIST_UNLOCK(&tls_objects); 00087 if (to) 00088 free(to); 00089 } 00090 00091 void __ast_threadstorage_object_replace(void *key_old, void *key_new, size_t len) 00092 { 00093 struct tls_object *to; 00094 00095 AST_RWLIST_WRLOCK(&tls_objects); 00096 AST_LIST_TRAVERSE_SAFE_BEGIN(&tls_objects, to, entry) { 00097 if (to->key == key_old) { 00098 to->key = key_new; 00099 to->size = len; 00100 break; 00101 } 00102 } 00103 AST_LIST_TRAVERSE_SAFE_END; 00104 AST_RWLIST_UNLOCK(&tls_objects); 00105 } 00106 00107 static int handle_show_allocations(int fd, int argc, char *argv[]) 00108 { 00109 char *fn = NULL; 00110 size_t len = 0; 00111 unsigned int count = 0; 00112 struct tls_object *to; 00113 00114 if (argc > 3) 00115 fn = argv[3]; 00116 00117 AST_RWLIST_RDLOCK(&tls_objects); 00118 00119 AST_LIST_TRAVERSE(&tls_objects, to, entry) { 00120 if (fn && strcasecmp(to->file, fn)) 00121 continue; 00122 00123 ast_cli(fd, "%10d bytes allocated in %20s at line %5d of %25s (thread %p)\n", 00124 (int) to->size, to->function, to->line, to->file, (void *) to->thread); 00125 len += to->size; 00126 count++; 00127 } 00128 00129 AST_RWLIST_UNLOCK(&tls_objects); 00130 00131 ast_cli(fd, "%10d bytes allocated in %d allocation%s\n", (int) len, count, count > 1 ? "s" : ""); 00132 00133 return RESULT_SUCCESS; 00134 } 00135 00136 static int handle_show_summary(int fd, int argc, char *argv[]) 00137 { 00138 char *fn = NULL; 00139 size_t len = 0; 00140 unsigned int count = 0; 00141 struct tls_object *to; 00142 struct file { 00143 const char *name; 00144 size_t len; 00145 unsigned int count; 00146 AST_LIST_ENTRY(file) entry; 00147 } *file; 00148 AST_LIST_HEAD_NOLOCK_STATIC(file_summary, file); 00149 00150 if (argc > 3) 00151 fn = argv[3]; 00152 00153 AST_RWLIST_RDLOCK(&tls_objects); 00154 00155 AST_LIST_TRAVERSE(&tls_objects, to, entry) { 00156 if (fn && strcasecmp(to->file, fn)) 00157 continue; 00158 00159 AST_LIST_TRAVERSE(&file_summary, file, entry) { 00160 if ((!fn && (file->name == to->file)) || (fn && (file->name == to->function))) 00161 break; 00162 } 00163 00164 if (!file) { 00165 file = alloca(sizeof(*file)); 00166 memset(file, 0, sizeof(*file)); 00167 file->name = fn ? to->function : to->file; 00168 AST_LIST_INSERT_TAIL(&file_summary, file, entry); 00169 } 00170 00171 file->len += to->size; 00172 file->count++; 00173 } 00174 00175 AST_RWLIST_UNLOCK(&tls_objects); 00176 00177 AST_LIST_TRAVERSE(&file_summary, file, entry) { 00178 len += file->len; 00179 count += file->count; 00180 if (fn) { 00181 ast_cli(fd, "%10d bytes in %d allocation%ss in function %s\n", 00182 (int) file->len, file->count, file->count > 1 ? "s" : "", file->name); 00183 } else { 00184 ast_cli(fd, "%10d bytes in %d allocation%s in file %s\n", 00185 (int) file->len, file->count, file->count > 1 ? "s" : "", file->name); 00186 } 00187 } 00188 00189 ast_cli(fd, "%10d bytes allocated in %d allocation%s\n", (int) len, count, count > 1 ? "s" : ""); 00190 00191 return RESULT_SUCCESS; 00192 } 00193 00194 static struct ast_cli_entry cli[] = { 00195 { 00196 .cmda = { "threadstorage", "show", "allocations", NULL }, 00197 .handler = handle_show_allocations, 00198 .summary = "Display outstanding thread local storage allocations", 00199 .usage = 00200 "Usage: threadstorage show allocations [<file>]\n" 00201 " Dumps a list of all thread-specific memory allocations,\n" 00202 "optionally limited to those from a specific file\n", 00203 }, 00204 { 00205 .cmda = { "threadstorage", "show", "summary", NULL }, 00206 .handler = handle_show_summary, 00207 .summary = "Summarize outstanding memory allocations", 00208 .usage = 00209 "Usage: threadstorage show summary [<file>]\n" 00210 " Summarizes thread-specific memory allocations by file, or optionally\n" 00211 "by function, if a file is specified\n", 00212 }, 00213 }; 00214 00215 void threadstorage_init(void) 00216 { 00217 ast_cli_register_multiple(cli, sizeof(cli) / sizeof(cli[0])); 00218 } 00219 00220 #else /* !defined(DEBUG_THREADLOCALS) */ 00221 00222 void threadstorage_init(void) 00223 { 00224 } 00225 00226 #endif /* !defined(DEBUG_THREADLOCALS) */ 00227