Memory Management. More...
#include "asterisk.h"#include "asterisk/paths.h"#include <stddef.h>#include <time.h>#include "asterisk/cli.h"#include "asterisk/lock.h"#include "asterisk/strings.h"#include "asterisk/unaligned.h"
Go to the source code of this file.
Data Structures | |
| struct | ast_region |
Defines | |
| #define | astmm_log(...) |
| #define | FENCE_MAGIC 0xdeadbeef |
| #define | HASH(a) (((unsigned long)(a)) % SOME_PRIME) |
| #define | SOME_PRIME 563 |
Enumerations | |
| enum | func_type { FUNC_CALLOC = 1, FUNC_MALLOC, FUNC_REALLOC, FUNC_STRDUP, FUNC_STRNDUP, FUNC_VASPRINTF, FUNC_ASPRINTF } |
Functions | |
| static void * | __ast_alloc_region (size_t size, const enum func_type which, const char *file, int lineno, const char *func, unsigned int cache) |
| int | __ast_asprintf (const char *file, int lineno, const char *func, char **strp, const char *fmt,...) |
| void * | __ast_calloc (size_t nmemb, size_t size, const char *file, int lineno, const char *func) |
| void * | __ast_calloc_cache (size_t nmemb, size_t size, const char *file, int lineno, const char *func) |
| void | __ast_free (void *ptr, const char *file, int lineno, const char *func) |
| static void | __ast_free_region (void *ptr, const char *file, int lineno, const char *func) |
| void * | __ast_malloc (size_t size, const char *file, int lineno, const char *func) |
| void | __ast_mm_init (void) |
| void * | __ast_realloc (void *ptr, size_t size, const char *file, int lineno, const char *func) |
| static size_t | __ast_sizeof_region (void *ptr) |
| char * | __ast_strdup (const char *s, const char *file, int lineno, const char *func) |
| char * | __ast_strndup (const char *s, size_t n, const char *file, int lineno, const char *func) |
| int | __ast_vasprintf (char **strp, const char *fmt, va_list ap, const char *file, int lineno, const char *func) |
| static char * | handle_memory_show (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_memory_show_summary (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
Variables | |
| static struct ast_cli_entry | cli_memory [] |
| static FILE * | mmlog |
| static struct ast_region * | regions [SOME_PRIME] |
| static ast_mutex_t | reglock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) |
Memory Management.
Definition in file astmm.c.
| #define astmm_log | ( | ... | ) |
Definition at line 98 of file astmm.c.
Referenced by __ast_alloc_region(), __ast_free_region(), __ast_realloc(), and handle_memory_show().
| #define FENCE_MAGIC 0xdeadbeef |
Definition at line 63 of file astmm.c.
Referenced by __ast_alloc_region(), __ast_free_region(), and handle_memory_show().
| #define HASH | ( | a | ) | (((unsigned long)(a)) % SOME_PRIME) |
Definition at line 91 of file astmm.c.
Referenced by __ast_alloc_region(), __ast_free_region(), and __ast_sizeof_region().
| #define SOME_PRIME 563 |
Definition at line 41 of file astmm.c.
Referenced by handle_memory_show(), and handle_memory_show_summary().
| enum func_type |
| FUNC_CALLOC | |
| FUNC_MALLOC | |
| FUNC_REALLOC | |
| FUNC_STRDUP | |
| FUNC_STRNDUP | |
| FUNC_VASPRINTF | |
| FUNC_ASPRINTF |
Definition at line 43 of file astmm.c.
00043 { 00044 FUNC_CALLOC = 1, 00045 FUNC_MALLOC, 00046 FUNC_REALLOC, 00047 FUNC_STRDUP, 00048 FUNC_STRNDUP, 00049 FUNC_VASPRINTF, 00050 FUNC_ASPRINTF 00051 };
| static void* __ast_alloc_region | ( | size_t | size, | |
| const enum func_type | which, | |||
| const char * | file, | |||
| int | lineno, | |||
| const char * | func, | |||
| unsigned int | cache | |||
| ) | [inline, static] |
Definition at line 107 of file astmm.c.
References ast_copy_string(), ast_mutex_lock(), ast_mutex_unlock(), astmm_log, ast_region::cache, ast_region::data, ast_region::fence, FENCE_MAGIC, ast_region::file, ast_region::func, HASH, ast_region::len, ast_region::lineno, malloc, ast_region::next, put_unaligned_uint32(), regions, reglock, and ast_region::which.
Referenced by __ast_asprintf(), __ast_calloc(), __ast_calloc_cache(), __ast_malloc(), __ast_realloc(), __ast_strdup(), __ast_strndup(), and __ast_vasprintf().
00108 { 00109 struct ast_region *reg; 00110 void *ptr = NULL; 00111 unsigned int *fence; 00112 int hash; 00113 00114 if (!(reg = malloc(size + sizeof(*reg) + sizeof(*fence)))) { 00115 astmm_log("Memory Allocation Failure - '%d' bytes in function %s " 00116 "at line %d of %s\n", (int) size, func, lineno, file); 00117 return NULL; 00118 } 00119 00120 ast_copy_string(reg->file, file, sizeof(reg->file)); 00121 ast_copy_string(reg->func, func, sizeof(reg->func)); 00122 reg->lineno = lineno; 00123 reg->len = size; 00124 reg->which = which; 00125 reg->cache = cache; 00126 ptr = reg->data; 00127 hash = HASH(ptr); 00128 reg->fence = FENCE_MAGIC; 00129 fence = (ptr + reg->len); 00130 put_unaligned_uint32(fence, FENCE_MAGIC); 00131 00132 ast_mutex_lock(®lock); 00133 reg->next = regions[hash]; 00134 regions[hash] = reg; 00135 ast_mutex_unlock(®lock); 00136 00137 return ptr; 00138 }
| int __ast_asprintf | ( | const char * | file, | |
| int | lineno, | |||
| const char * | func, | |||
| char ** | strp, | |||
| const char * | fmt, | |||
| ... | ||||
| ) |
Definition at line 285 of file astmm.c.
References __ast_alloc_region(), FUNC_ASPRINTF, and s.
00286 { 00287 int size; 00288 va_list ap, ap2; 00289 char s; 00290 00291 *strp = NULL; 00292 va_start(ap, fmt); 00293 va_copy(ap2, ap); 00294 size = vsnprintf(&s, 1, fmt, ap2); 00295 va_end(ap2); 00296 if (!(*strp = __ast_alloc_region(size + 1, FUNC_ASPRINTF, file, lineno, func, 0))) { 00297 va_end(ap); 00298 return -1; 00299 } 00300 vsnprintf(*strp, size + 1, fmt, ap); 00301 va_end(ap); 00302 00303 return size; 00304 }
| void* __ast_calloc | ( | size_t | nmemb, | |
| size_t | size, | |||
| const char * | file, | |||
| int | lineno, | |||
| const char * | func | |||
| ) |
Definition at line 199 of file astmm.c.
References __ast_alloc_region(), and FUNC_CALLOC.
Referenced by __ao2_alloc(), __ast_channel_alloc_ap(), __ast_datastore_alloc(), add_string_pool(), ast_hashtab_create(), ast_hashtab_dup(), ast_hashtab_insert_immediate_bucket(), ast_hashtab_resize(), ast_hashtab_start_traversal(), ast_hashtab_start_write_traversal(), ast_heap_create(), ast_var_assign(), and ast_variable_new().
00200 { 00201 void *ptr; 00202 00203 if ((ptr = __ast_alloc_region(size * nmemb, FUNC_CALLOC, file, lineno, func, 0))) 00204 memset(ptr, 0, size * nmemb); 00205 00206 return ptr; 00207 }
| void* __ast_calloc_cache | ( | size_t | nmemb, | |
| size_t | size, | |||
| const char * | file, | |||
| int | lineno, | |||
| const char * | func | |||
| ) |
Definition at line 209 of file astmm.c.
References __ast_alloc_region(), and FUNC_CALLOC.
00210 { 00211 void *ptr; 00212 00213 if ((ptr = __ast_alloc_region(size * nmemb, FUNC_CALLOC, file, lineno, func, 1))) 00214 memset(ptr, 0, size * nmemb); 00215 00216 return ptr; 00217 }
| void __ast_free | ( | void * | ptr, | |
| const char * | file, | |||
| int | lineno, | |||
| const char * | func | |||
| ) |
Definition at line 224 of file astmm.c.
References __ast_free_region().
00225 { 00226 __ast_free_region(ptr, file, lineno, func); 00227 }
| static void __ast_free_region | ( | void * | ptr, | |
| const char * | file, | |||
| int | lineno, | |||
| const char * | func | |||
| ) | [static] |
Definition at line 158 of file astmm.c.
References ast_mutex_lock(), ast_mutex_unlock(), astmm_log, ast_region::data, ast_region::fence, FENCE_MAGIC, ast_region::file, free, ast_region::func, get_unaligned_uint32(), HASH, ast_region::len, ast_region::lineno, ast_region::next, regions, and reglock.
Referenced by __ast_free(), and __ast_realloc().
00159 { 00160 int hash; 00161 struct ast_region *reg, *prev = NULL; 00162 unsigned int *fence; 00163 00164 if (!ptr) 00165 return; 00166 00167 hash = HASH(ptr); 00168 00169 ast_mutex_lock(®lock); 00170 for (reg = regions[hash]; reg; reg = reg->next) { 00171 if (reg->data == ptr) { 00172 if (prev) 00173 prev->next = reg->next; 00174 else 00175 regions[hash] = reg->next; 00176 break; 00177 } 00178 prev = reg; 00179 } 00180 ast_mutex_unlock(®lock); 00181 00182 if (reg) { 00183 fence = (unsigned int *)(reg->data + reg->len); 00184 if (reg->fence != FENCE_MAGIC) { 00185 astmm_log("WARNING: Low fence violation at %p, in %s of %s, " 00186 "line %d\n", reg->data, reg->func, reg->file, reg->lineno); 00187 } 00188 if (get_unaligned_uint32(fence) != FENCE_MAGIC) { 00189 astmm_log("WARNING: High fence violation at %p, in %s of %s, " 00190 "line %d\n", reg->data, reg->func, reg->file, reg->lineno); 00191 } 00192 free(reg); 00193 } else { 00194 astmm_log("WARNING: Freeing unused memory at %p, in %s of %s, line %d\n", 00195 ptr, func, file, lineno); 00196 } 00197 }
| void* __ast_malloc | ( | size_t | size, | |
| const char * | file, | |||
| int | lineno, | |||
| const char * | func | |||
| ) |
Definition at line 219 of file astmm.c.
References __ast_alloc_region(), and FUNC_MALLOC.
00220 { 00221 return __ast_alloc_region(size, FUNC_MALLOC, file, lineno, func, 0); 00222 }
| void __ast_mm_init | ( | void | ) |
Definition at line 481 of file astmm.c.
References ARRAY_LEN, ast_cli_register_multiple(), ast_config_AST_LOG_DIR, ast_log(), ast_verb, and LOG_ERROR.
Referenced by main().
00482 { 00483 char filename[PATH_MAX]; 00484 size_t pad = sizeof(struct ast_region) - offsetof(struct ast_region, data); 00485 00486 if (pad) { 00487 ast_log(LOG_ERROR, "struct ast_region has %d bytes of padding! This must be eliminated for low-fence checking to work properly!\n", (int) pad); 00488 } 00489 00490 ast_cli_register_multiple(cli_memory, ARRAY_LEN(cli_memory)); 00491 00492 snprintf(filename, sizeof(filename), "%s/mmlog", ast_config_AST_LOG_DIR); 00493 00494 ast_verb(1, "Asterisk Malloc Debugger Started (see %s))\n", filename); 00495 00496 if ((mmlog = fopen(filename, "a+"))) { 00497 fprintf(mmlog, "%ld - New session\n", (long)time(NULL)); 00498 fflush(mmlog); 00499 } 00500 }
| void* __ast_realloc | ( | void * | ptr, | |
| size_t | size, | |||
| const char * | file, | |||
| int | lineno, | |||
| const char * | func | |||
| ) |
Definition at line 229 of file astmm.c.
References __ast_alloc_region(), __ast_free_region(), __ast_sizeof_region(), astmm_log, FUNC_REALLOC, and len().
Referenced by grow_heap().
00230 { 00231 void *tmp; 00232 size_t len = 0; 00233 00234 if (ptr && !(len = __ast_sizeof_region(ptr))) { 00235 astmm_log("WARNING: Realloc of unalloced memory at %p, in %s of %s, " 00236 "line %d\n", ptr, func, file, lineno); 00237 return NULL; 00238 } 00239 00240 if (!(tmp = __ast_alloc_region(size, FUNC_REALLOC, file, lineno, func, 0))) 00241 return NULL; 00242 00243 if (len > size) 00244 len = size; 00245 if (ptr) { 00246 memcpy(tmp, ptr, len); 00247 __ast_free_region(ptr, file, lineno, func); 00248 } 00249 00250 return tmp; 00251 }
| static size_t __ast_sizeof_region | ( | void * | ptr | ) | [inline, static] |
Definition at line 140 of file astmm.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_region::data, HASH, ast_region::len, len(), ast_region::next, regions, and reglock.
Referenced by __ast_realloc().
00141 { 00142 int hash = HASH(ptr); 00143 struct ast_region *reg; 00144 size_t len = 0; 00145 00146 ast_mutex_lock(®lock); 00147 for (reg = regions[hash]; reg; reg = reg->next) { 00148 if (reg->data == ptr) { 00149 len = reg->len; 00150 break; 00151 } 00152 } 00153 ast_mutex_unlock(®lock); 00154 00155 return len; 00156 }
| char* __ast_strdup | ( | const char * | s, | |
| const char * | file, | |||
| int | lineno, | |||
| const char * | func | |||
| ) |
Definition at line 253 of file astmm.c.
References __ast_alloc_region(), FUNC_STRDUP, and len().
00254 { 00255 size_t len; 00256 void *ptr; 00257 00258 if (!s) 00259 return NULL; 00260 00261 len = strlen(s) + 1; 00262 if ((ptr = __ast_alloc_region(len, FUNC_STRDUP, file, lineno, func, 0))) 00263 strcpy(ptr, s); 00264 00265 return ptr; 00266 }
| char* __ast_strndup | ( | const char * | s, | |
| size_t | n, | |||
| const char * | file, | |||
| int | lineno, | |||
| const char * | func | |||
| ) |
Definition at line 268 of file astmm.c.
References __ast_alloc_region(), FUNC_STRNDUP, and len().
00269 { 00270 size_t len; 00271 void *ptr; 00272 00273 if (!s) 00274 return NULL; 00275 00276 len = strlen(s) + 1; 00277 if (len > n) 00278 len = n; 00279 if ((ptr = __ast_alloc_region(len, FUNC_STRNDUP, file, lineno, func, 0))) 00280 strcpy(ptr, s); 00281 00282 return ptr; 00283 }
| int __ast_vasprintf | ( | char ** | strp, | |
| const char * | fmt, | |||
| va_list | ap, | |||
| const char * | file, | |||
| int | lineno, | |||
| const char * | func | |||
| ) |
Definition at line 306 of file astmm.c.
References __ast_alloc_region(), FUNC_VASPRINTF, and s.
00307 { 00308 int size; 00309 va_list ap2; 00310 char s; 00311 00312 *strp = NULL; 00313 va_copy(ap2, ap); 00314 size = vsnprintf(&s, 1, fmt, ap2); 00315 va_end(ap2); 00316 if (!(*strp = __ast_alloc_region(size + 1, FUNC_VASPRINTF, file, lineno, func, 0))) { 00317 va_end(ap); 00318 return -1; 00319 } 00320 vsnprintf(*strp, size + 1, fmt, ap); 00321 00322 return size; 00323 }
| static char* handle_memory_show | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 325 of file astmm.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), astmm_log, ast_region::cache, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_region::data, ast_cli_args::fd, ast_region::fence, FENCE_MAGIC, ast_region::file, ast_region::func, get_unaligned_uint32(), ast_region::len, len(), ast_region::lineno, ast_region::next, regions, reglock, SOME_PRIME, and ast_cli_entry::usage.
00326 { 00327 char *fn = NULL; 00328 struct ast_region *reg; 00329 unsigned int x; 00330 unsigned int len = 0; 00331 unsigned int cache_len = 0; 00332 unsigned int count = 0; 00333 unsigned int *fence; 00334 00335 switch (cmd) { 00336 case CLI_INIT: 00337 e->command = "memory show allocations"; 00338 e->usage = 00339 "Usage: memory show allocations [<file>]\n" 00340 " Dumps a list of all segments of allocated memory, optionally\n" 00341 " limited to those from a specific file\n"; 00342 return NULL; 00343 case CLI_GENERATE: 00344 return NULL; 00345 } 00346 00347 00348 if (a->argc > 3) 00349 fn = a->argv[3]; 00350 00351 ast_mutex_lock(®lock); 00352 for (x = 0; x < SOME_PRIME; x++) { 00353 for (reg = regions[x]; reg; reg = reg->next) { 00354 if (!fn || !strcasecmp(fn, reg->file) || !strcasecmp(fn, "anomolies")) { 00355 fence = (unsigned int *)(reg->data + reg->len); 00356 if (reg->fence != FENCE_MAGIC) { 00357 astmm_log("WARNING: Low fence violation at %p, " 00358 "in %s of %s, line %d\n", reg->data, 00359 reg->func, reg->file, reg->lineno); 00360 } 00361 if (get_unaligned_uint32(fence) != FENCE_MAGIC) { 00362 astmm_log("WARNING: High fence violation at %p, in %s of %s, " 00363 "line %d\n", reg->data, reg->func, reg->file, reg->lineno); 00364 } 00365 } 00366 if (!fn || !strcasecmp(fn, reg->file)) { 00367 ast_cli(a->fd, "%10d bytes allocated%s in %20s at line %5d of %s\n", 00368 (int) reg->len, reg->cache ? " (cache)" : "", 00369 reg->func, reg->lineno, reg->file); 00370 len += reg->len; 00371 if (reg->cache) 00372 cache_len += reg->len; 00373 count++; 00374 } 00375 } 00376 } 00377 ast_mutex_unlock(®lock); 00378 00379 if (cache_len) 00380 ast_cli(a->fd, "%d bytes allocated (%d in caches) in %d allocations\n", len, cache_len, count); 00381 else 00382 ast_cli(a->fd, "%d bytes allocated in %d allocations\n", len, count); 00383 00384 return CLI_SUCCESS; 00385 }
| static char* handle_memory_show_summary | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 387 of file astmm.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_copy_string(), ast_mutex_lock(), ast_mutex_unlock(), ast_region::cache, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_region::file, ast_region::func, ast_region::len, len(), ast_region::next, regions, reglock, SOME_PRIME, and ast_cli_entry::usage.
00388 { 00389 char *fn = NULL; 00390 int x; 00391 struct ast_region *reg; 00392 unsigned int len = 0; 00393 unsigned int cache_len = 0; 00394 int count = 0; 00395 struct file_summary { 00396 char fn[80]; 00397 int len; 00398 int cache_len; 00399 int count; 00400 struct file_summary *next; 00401 } *list = NULL, *cur; 00402 00403 switch (cmd) { 00404 case CLI_INIT: 00405 e->command = "memory show summary"; 00406 e->usage = 00407 "Usage: memory show summary [<file>]\n" 00408 " Summarizes heap memory allocations by file, or optionally\n" 00409 "by function, if a file is specified\n"; 00410 return NULL; 00411 case CLI_GENERATE: 00412 return NULL; 00413 } 00414 00415 if (a->argc > 3) 00416 fn = a->argv[3]; 00417 00418 ast_mutex_lock(®lock); 00419 for (x = 0; x < SOME_PRIME; x++) { 00420 for (reg = regions[x]; reg; reg = reg->next) { 00421 if (fn && strcasecmp(fn, reg->file)) 00422 continue; 00423 00424 for (cur = list; cur; cur = cur->next) { 00425 if ((!fn && !strcmp(cur->fn, reg->file)) || (fn && !strcmp(cur->fn, reg->func))) 00426 break; 00427 } 00428 if (!cur) { 00429 cur = alloca(sizeof(*cur)); 00430 memset(cur, 0, sizeof(*cur)); 00431 ast_copy_string(cur->fn, fn ? reg->func : reg->file, sizeof(cur->fn)); 00432 cur->next = list; 00433 list = cur; 00434 } 00435 00436 cur->len += reg->len; 00437 if (reg->cache) 00438 cur->cache_len += reg->len; 00439 cur->count++; 00440 } 00441 } 00442 ast_mutex_unlock(®lock); 00443 00444 /* Dump the whole list */ 00445 for (cur = list; cur; cur = cur->next) { 00446 len += cur->len; 00447 cache_len += cur->cache_len; 00448 count += cur->count; 00449 if (cur->cache_len) { 00450 if (fn) { 00451 ast_cli(a->fd, "%10d bytes (%10d cache) in %d allocations in function '%s' of '%s'\n", 00452 cur->len, cur->cache_len, cur->count, cur->fn, fn); 00453 } else { 00454 ast_cli(a->fd, "%10d bytes (%10d cache) in %d allocations in file '%s'\n", 00455 cur->len, cur->cache_len, cur->count, cur->fn); 00456 } 00457 } else { 00458 if (fn) { 00459 ast_cli(a->fd, "%10d bytes in %d allocations in function '%s' of '%s'\n", 00460 cur->len, cur->count, cur->fn, fn); 00461 } else { 00462 ast_cli(a->fd, "%10d bytes in %d allocations in file '%s'\n", 00463 cur->len, cur->count, cur->fn); 00464 } 00465 } 00466 } 00467 00468 if (cache_len) 00469 ast_cli(a->fd, "%d bytes allocated (%d in caches) in %d allocations\n", len, cache_len, count); 00470 else 00471 ast_cli(a->fd, "%d bytes allocated in %d allocations\n", len, count); 00472 00473 return CLI_SUCCESS; 00474 }
struct ast_cli_entry cli_memory[] [static] |
{
AST_CLI_DEFINE(handle_memory_show, "Display outstanding memory allocations"),
AST_CLI_DEFINE(handle_memory_show_summary, "Summarize outstanding memory allocations"),
}
struct ast_region * regions[SOME_PRIME] [static] |
Referenced by __ast_alloc_region(), __ast_free_region(), __ast_sizeof_region(), handle_memory_show(), and handle_memory_show_summary().
ast_mutex_t reglock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Tracking this mutex will cause infinite recursion, as the mutex tracking code allocates memory
Definition at line 96 of file astmm.c.
Referenced by __ast_alloc_region(), __ast_free_region(), __ast_sizeof_region(), handle_memory_show(), and handle_memory_show_summary().
1.6.2