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_freed_regions |
struct | ast_region |
struct | region_list |
Defines | |
#define | astmm_log(...) |
#define | FENCE_MAGIC 0xdeadbeef |
#define | FREED_MAGIC 0xdeaddead |
#define | FREED_MAX_COUNT 1500 |
#define | HASH(a) (((unsigned long)(a)) % ARRAY_LEN(regions)) |
#define | MALLOC_FILLER 0x55 |
#define | MINNOWS_MAX_SIZE 50 |
#define | my_max(a, b) ((a) >= (b) ? (a) : (b)) |
#define | SOME_PRIME 1567 |
Enumerations | |
enum | func_type { FUNC_CALLOC = 1, FUNC_MALLOC, FUNC_REALLOC, FUNC_STRDUP, FUNC_STRNDUP, FUNC_VASPRINTF, FUNC_ASPRINTF } |
enum | summary_opts { SUMMARY_OFF, SUMMARY_BY_LINE = (1 << 0), SUMMARY_BY_FUNC = (1 << 1), SUMMARY_BY_FILE = (1 << 2) } |
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_phase_1 (void) |
Initialize malloc debug phase 1. | |
void | __ast_mm_init_phase_2 (void) |
Initialize malloc debug phase 2. | |
void * | __ast_realloc (void *ptr, size_t size, const char *file, int lineno, const char *func) |
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 void | freed_regions_flush (struct ast_freed_regions *freed) |
static char * | handle_memory_atexit_list (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_memory_atexit_summary (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_memory_show_allocations (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) |
static void | mm_atexit_ast (void) |
static int | mm_atexit_cmp (struct ast_region *left, struct ast_region *right) |
static void | mm_atexit_dump (void) |
static void | mm_atexit_final (void) |
static size_t | mm_atexit_hash_list (struct region_list *list) |
static void | mm_atexit_hash_restore (struct region_list *list) |
static void | mm_atexit_list_merge (struct region_list *list, struct region_list *sub1, struct region_list *sub2) |
static void | mm_atexit_list_sort (struct region_list *list, size_t length) |
static void | mm_atexit_list_split (struct region_list *list, struct region_list sub[], size_t num_lists, size_t size, size_t *remaining) |
static void | mm_atexit_regions_list (struct region_list *alloced) |
static void | mm_atexit_regions_summary (struct region_list *alloced) |
static void | my_do_crash (void) |
static void | region_check_fences (struct ast_region *reg) |
static void | region_data_check (struct ast_region *reg) |
static void | region_data_wipe (struct ast_region *reg) |
static struct ast_region * | region_find (void *ptr) |
static void | region_free (struct ast_freed_regions *freed, struct ast_region *reg) |
static struct ast_region * | region_remove (void *ptr) |
static void | regions_check_all_fences (void) |
Variables | |
static int | atexit_list |
static enum summary_opts | atexit_summary |
static struct ast_cli_entry | cli_memory [] |
static struct ast_freed_regions | minnows |
static FILE * | mmlog |
static struct ast_region * | regions [SOME_PRIME] |
static ast_mutex_t | reglock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 0 } |
static struct ast_freed_regions | whales |
Memory Management.
Definition in file astmm.c.
#define astmm_log | ( | ... | ) |
Definition at line 151 of file astmm.c.
Referenced by __ast_alloc_region(), __ast_free_region(), __ast_realloc(), mm_atexit_dump(), mm_atexit_regions_list(), mm_atexit_regions_summary(), region_check_fences(), and region_data_check().
#define FENCE_MAGIC 0xdeadbeef |
Allocated memory high/low fence overwrite check.
Definition at line 73 of file astmm.c.
Referenced by __ast_alloc_region(), and region_check_fences().
#define FREED_MAGIC 0xdeaddead |
Freed memory wipe filler.
Definition at line 74 of file astmm.c.
Referenced by region_data_check(), and region_data_wipe().
#define FREED_MAX_COUNT 1500 |
#define HASH | ( | a | ) | (((unsigned long)(a)) % ARRAY_LEN(regions)) |
Definition at line 145 of file astmm.c.
Referenced by __ast_alloc_region(), mm_atexit_hash_restore(), region_find(), and region_remove().
#define MALLOC_FILLER 0x55 |
Malloced memory filler. Must not be zero.
Definition at line 75 of file astmm.c.
Referenced by __ast_malloc(), and __ast_realloc().
#define MINNOWS_MAX_SIZE 50 |
Maximum size of a minnow block
Definition at line 115 of file astmm.c.
Referenced by __ast_free_region().
#define my_max | ( | a, | |||
b | ) | ((a) >= (b) ? (a) : (b)) |
Referenced by handle_memory_show_summary().
#define SOME_PRIME 1567 |
enum func_type |
FUNC_CALLOC | |
FUNC_MALLOC | |
FUNC_REALLOC | |
FUNC_STRDUP | |
FUNC_STRNDUP | |
FUNC_VASPRINTF | |
FUNC_ASPRINTF |
Definition at line 53 of file astmm.c.
00053 { 00054 FUNC_CALLOC = 1, 00055 FUNC_MALLOC, 00056 FUNC_REALLOC, 00057 FUNC_STRDUP, 00058 FUNC_STRNDUP, 00059 FUNC_VASPRINTF, 00060 FUNC_ASPRINTF 00061 };
enum summary_opts |
SUMMARY_OFF |
No summary at exit. |
SUMMARY_BY_LINE |
Bit set if summary by line at exit. |
SUMMARY_BY_FUNC |
Bit set if summary by function at exit. |
SUMMARY_BY_FILE |
Bit set if summary by file at exit. |
Definition at line 129 of file astmm.c.
00129 { 00130 /*! No summary at exit. */ 00131 SUMMARY_OFF, 00132 /*! Bit set if summary by line at exit. */ 00133 SUMMARY_BY_LINE = (1 << 0), 00134 /*! Bit set if summary by function at exit. */ 00135 SUMMARY_BY_FUNC = (1 << 1), 00136 /*! Bit set if summary by file at exit. */ 00137 SUMMARY_BY_FILE = (1 << 2), 00138 };
static void* __ast_alloc_region | ( | size_t | size, | |
const enum func_type | which, | |||
const char * | file, | |||
int | lineno, | |||
const char * | func, | |||
unsigned int | cache | |||
) | [static] |
Definition at line 178 of file astmm.c.
References ast_copy_string(), AST_LIST_NEXT, ast_mutex_lock, ast_mutex_unlock, astmm_log, ast_region::cache, ast_region::data, FENCE_MAGIC, ast_region::file, ast_region::func, HASH, ast_region::len, ast_region::lineno, malloc, 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().
00179 { 00180 struct ast_region *reg; 00181 unsigned int *fence; 00182 int hash; 00183 00184 if (!(reg = malloc(size + sizeof(*reg) + sizeof(*fence)))) { 00185 astmm_log("Memory Allocation Failure - '%d' bytes at %s %s() line %d\n", 00186 (int) size, file, func, lineno); 00187 return NULL; 00188 } 00189 00190 reg->len = size; 00191 reg->cache = cache; 00192 reg->lineno = lineno; 00193 reg->which = which; 00194 ast_copy_string(reg->file, file, sizeof(reg->file)); 00195 ast_copy_string(reg->func, func, sizeof(reg->func)); 00196 00197 /* 00198 * Init lower fence. 00199 * 00200 * We use the bytes just preceeding reg->data and not reg->fence 00201 * because there is likely to be padding between reg->fence and 00202 * reg->data for reg->data alignment. 00203 */ 00204 fence = (unsigned int *) (reg->data - sizeof(*fence)); 00205 *fence = FENCE_MAGIC; 00206 00207 /* Init higher fence. */ 00208 fence = (unsigned int *) (reg->data + reg->len); 00209 put_unaligned_uint32(fence, FENCE_MAGIC); 00210 00211 hash = HASH(reg->data); 00212 ast_mutex_lock(®lock); 00213 AST_LIST_NEXT(reg, node) = regions[hash]; 00214 regions[hash] = reg; 00215 ast_mutex_unlock(®lock); 00216 00217 return reg->data; 00218 }
int __ast_asprintf | ( | const char * | file, | |
int | lineno, | |||
const char * | func, | |||
char ** | strp, | |||
const char * | fmt, | |||
... | ||||
) |
Definition at line 584 of file astmm.c.
References __ast_alloc_region(), and FUNC_ASPRINTF.
00585 { 00586 int size; 00587 va_list ap, ap2; 00588 char s; 00589 00590 *strp = NULL; 00591 va_start(ap, fmt); 00592 va_copy(ap2, ap); 00593 size = vsnprintf(&s, 1, fmt, ap2); 00594 va_end(ap2); 00595 if (!(*strp = __ast_alloc_region(size + 1, FUNC_ASPRINTF, file, lineno, func, 0))) { 00596 va_end(ap); 00597 return -1; 00598 } 00599 vsnprintf(*strp, size + 1, fmt, ap); 00600 va_end(ap); 00601 00602 return size; 00603 }
void* __ast_calloc | ( | size_t | nmemb, | |
size_t | size, | |||
const char * | file, | |||
int | lineno, | |||
const char * | func | |||
) |
Definition at line 442 of file astmm.c.
References __ast_alloc_region(), and FUNC_CALLOC.
Referenced by __ast_calloc_with_stringfields(), __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(), ast_variable_new(), and internal_ao2_alloc().
00443 { 00444 void *ptr; 00445 00446 ptr = __ast_alloc_region(size * nmemb, FUNC_CALLOC, file, lineno, func, 0); 00447 if (ptr) { 00448 memset(ptr, 0, size * nmemb); 00449 } 00450 00451 return ptr; 00452 }
void* __ast_calloc_cache | ( | size_t | nmemb, | |
size_t | size, | |||
const char * | file, | |||
int | lineno, | |||
const char * | func | |||
) |
Definition at line 454 of file astmm.c.
References __ast_alloc_region(), and FUNC_CALLOC.
00455 { 00456 void *ptr; 00457 00458 ptr = __ast_alloc_region(size * nmemb, FUNC_CALLOC, file, lineno, func, 1); 00459 if (ptr) { 00460 memset(ptr, 0, size * nmemb); 00461 } 00462 00463 return ptr; 00464 }
void __ast_free | ( | void * | ptr, | |
const char * | file, | |||
int | lineno, | |||
const char * | func | |||
) |
Definition at line 479 of file astmm.c.
References __ast_free_region().
00480 { 00481 __ast_free_region(ptr, file, lineno, func); 00482 }
static void __ast_free_region | ( | void * | ptr, | |
const char * | file, | |||
int | lineno, | |||
const char * | func | |||
) | [static] |
Definition at line 413 of file astmm.c.
References astmm_log, ast_region::len, minnows, MINNOWS_MAX_SIZE, my_do_crash(), region_check_fences(), region_free(), region_remove(), and whales.
Referenced by __ast_free(), and __ast_realloc().
00414 { 00415 struct ast_region *reg; 00416 00417 if (!ptr) { 00418 return; 00419 } 00420 00421 reg = region_remove(ptr); 00422 if (reg) { 00423 region_check_fences(reg); 00424 00425 if (reg->len <= MINNOWS_MAX_SIZE) { 00426 region_free(&minnows, reg); 00427 } else { 00428 region_free(&whales, reg); 00429 } 00430 } else { 00431 /* 00432 * This memory region is not registered. It could be because of 00433 * a double free or the memory block was not allocated by the 00434 * malloc debug code. 00435 */ 00436 astmm_log("WARNING: Freeing unregistered memory %p by %s %s() line %d\n", 00437 ptr, file, func, lineno); 00438 my_do_crash(); 00439 } 00440 }
void* __ast_malloc | ( | size_t | size, | |
const char * | file, | |||
int | lineno, | |||
const char * | func | |||
) |
Definition at line 466 of file astmm.c.
References __ast_alloc_region(), FUNC_MALLOC, and MALLOC_FILLER.
Referenced by __ast_cc_config_params_init().
00467 { 00468 void *ptr; 00469 00470 ptr = __ast_alloc_region(size, FUNC_MALLOC, file, lineno, func, 0); 00471 if (ptr) { 00472 /* Make sure that the malloced memory is not zero. */ 00473 memset(ptr, MALLOC_FILLER, size); 00474 } 00475 00476 return ptr; 00477 }
void __ast_mm_init_phase_1 | ( | void | ) |
Initialize malloc debug phase 1.
Definition at line 1370 of file astmm.c.
References mm_atexit_final().
Referenced by main().
01371 { 01372 atexit(mm_atexit_final); 01373 }
void __ast_mm_init_phase_2 | ( | void | ) |
Initialize malloc debug phase 2.
Definition at line 1389 of file astmm.c.
References ARRAY_LEN, ast_cli_register_multiple(), ast_config_AST_LOG_DIR, ast_log(), ast_register_atexit(), ast_verb, LOG_ERROR, and mm_atexit_ast().
Referenced by main().
01390 { 01391 char filename[PATH_MAX]; 01392 01393 ast_cli_register_multiple(cli_memory, ARRAY_LEN(cli_memory)); 01394 01395 snprintf(filename, sizeof(filename), "%s/mmlog", ast_config_AST_LOG_DIR); 01396 01397 ast_verb(1, "Asterisk Malloc Debugger Started (see %s))\n", filename); 01398 01399 mmlog = fopen(filename, "a+"); 01400 if (mmlog) { 01401 fprintf(mmlog, "%ld - New session\n", (long) time(NULL)); 01402 fflush(mmlog); 01403 } else { 01404 ast_log(LOG_ERROR, "Could not open malloc debug log file: %s\n", filename); 01405 } 01406 01407 ast_register_atexit(mm_atexit_ast); 01408 }
void* __ast_realloc | ( | void * | ptr, | |
size_t | size, | |||
const char * | file, | |||
int | lineno, | |||
const char * | func | |||
) |
Definition at line 502 of file astmm.c.
References __ast_alloc_region(), __ast_free_region(), ast_mutex_lock, ast_mutex_unlock, astmm_log, FUNC_REALLOC, ast_region::len, MALLOC_FILLER, my_do_crash(), region_find(), and reglock.
Referenced by grow_heap().
00503 { 00504 size_t len; 00505 struct ast_region *found; 00506 void *new_mem; 00507 00508 if (ptr) { 00509 ast_mutex_lock(®lock); 00510 found = region_find(ptr); 00511 if (!found) { 00512 ast_mutex_unlock(®lock); 00513 astmm_log("WARNING: Realloc of unregistered memory %p by %s %s() line %d\n", 00514 ptr, file, func, lineno); 00515 my_do_crash(); 00516 return NULL; 00517 } 00518 len = found->len; 00519 ast_mutex_unlock(®lock); 00520 } else { 00521 found = NULL; 00522 len = 0; 00523 } 00524 00525 if (!size) { 00526 __ast_free_region(ptr, file, lineno, func); 00527 return NULL; 00528 } 00529 00530 new_mem = __ast_alloc_region(size, FUNC_REALLOC, file, lineno, func, 0); 00531 if (new_mem) { 00532 if (found) { 00533 /* Copy the old data to the new malloced memory. */ 00534 if (size <= len) { 00535 memcpy(new_mem, ptr, size); 00536 } else { 00537 memcpy(new_mem, ptr, len); 00538 /* Make sure that the added memory is not zero. */ 00539 memset(new_mem + len, MALLOC_FILLER, size - len); 00540 } 00541 __ast_free_region(ptr, file, lineno, func); 00542 } else { 00543 /* Make sure that the malloced memory is not zero. */ 00544 memset(new_mem, MALLOC_FILLER, size); 00545 } 00546 } 00547 00548 return new_mem; 00549 }
char* __ast_strdup | ( | const char * | s, | |
const char * | file, | |||
int | lineno, | |||
const char * | func | |||
) |
Definition at line 551 of file astmm.c.
References __ast_alloc_region(), and FUNC_STRDUP.
00552 { 00553 size_t len; 00554 void *ptr; 00555 00556 if (!s) 00557 return NULL; 00558 00559 len = strlen(s) + 1; 00560 if ((ptr = __ast_alloc_region(len, FUNC_STRDUP, file, lineno, func, 0))) 00561 strcpy(ptr, s); 00562 00563 return ptr; 00564 }
char* __ast_strndup | ( | const char * | s, | |
size_t | n, | |||
const char * | file, | |||
int | lineno, | |||
const char * | func | |||
) |
Definition at line 566 of file astmm.c.
References __ast_alloc_region(), and FUNC_STRNDUP.
00567 { 00568 size_t len; 00569 char *ptr; 00570 00571 if (!s) { 00572 return NULL; 00573 } 00574 00575 len = strnlen(s, n); 00576 if ((ptr = __ast_alloc_region(len + 1, FUNC_STRNDUP, file, lineno, func, 0))) { 00577 memcpy(ptr, s, len); 00578 ptr[len] = '\0'; 00579 } 00580 00581 return ptr; 00582 }
int __ast_vasprintf | ( | char ** | strp, | |
const char * | fmt, | |||
va_list | ap, | |||
const char * | file, | |||
int | lineno, | |||
const char * | func | |||
) |
Definition at line 605 of file astmm.c.
References __ast_alloc_region(), and FUNC_VASPRINTF.
00606 { 00607 int size; 00608 va_list ap2; 00609 char s; 00610 00611 *strp = NULL; 00612 va_copy(ap2, ap); 00613 size = vsnprintf(&s, 1, fmt, ap2); 00614 va_end(ap2); 00615 if (!(*strp = __ast_alloc_region(size + 1, FUNC_VASPRINTF, file, lineno, func, 0))) { 00616 va_end(ap); 00617 return -1; 00618 } 00619 vsnprintf(*strp, size + 1, fmt, ap); 00620 00621 return size; 00622 }
static void freed_regions_flush | ( | struct ast_freed_regions * | freed | ) | [static] |
Definition at line 279 of file astmm.c.
References ARRAY_LEN, ast_mutex_lock, ast_mutex_unlock, free, ast_freed_regions::index, region_data_check(), ast_freed_regions::regions, and reglock.
Referenced by mm_atexit_final().
00280 { 00281 int idx; 00282 struct ast_region *old; 00283 00284 ast_mutex_lock(®lock); 00285 for (idx = 0; idx < ARRAY_LEN(freed->regions); ++idx) { 00286 old = freed->regions[idx]; 00287 freed->regions[idx] = NULL; 00288 if (old) { 00289 region_data_check(old); 00290 free(old); 00291 } 00292 } 00293 freed->index = 0; 00294 ast_mutex_unlock(®lock); 00295 }
static char* handle_memory_atexit_list | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 624 of file astmm.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_cli_complete(), ast_false(), ast_true(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_cli_args::n, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
00625 { 00626 switch (cmd) { 00627 case CLI_INIT: 00628 e->command = "memory atexit list"; 00629 e->usage = 00630 "Usage: memory atexit list {on|off}\n" 00631 " Enable dumping a list of still allocated memory segments at exit.\n"; 00632 return NULL; 00633 case CLI_GENERATE: 00634 if (a->pos == 3) { 00635 const char * const options[] = { "off", "on", NULL }; 00636 00637 return ast_cli_complete(a->word, options, a->n); 00638 } 00639 return NULL; 00640 } 00641 00642 if (a->argc != 4) { 00643 return CLI_SHOWUSAGE; 00644 } 00645 00646 if (ast_true(a->argv[3])) { 00647 atexit_list = 1; 00648 } else if (ast_false(a->argv[3])) { 00649 atexit_list = 0; 00650 } else { 00651 return CLI_SHOWUSAGE; 00652 } 00653 00654 ast_cli(a->fd, "The atexit list is: %s\n", atexit_list ? "On" : "Off"); 00655 00656 return CLI_SUCCESS; 00657 }
static char* handle_memory_atexit_summary | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 659 of file astmm.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_cli_complete(), ast_false(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_cli_args::n, ast_cli_args::pos, SUMMARY_BY_FILE, SUMMARY_BY_FUNC, SUMMARY_BY_LINE, SUMMARY_OFF, ast_cli_entry::usage, and ast_cli_args::word.
00660 { 00661 char buf[80]; 00662 00663 switch (cmd) { 00664 case CLI_INIT: 00665 e->command = "memory atexit summary"; 00666 e->usage = 00667 "Usage: memory atexit summary {off|byline|byfunc|byfile}\n" 00668 " Summary of still allocated memory segments at exit options.\n" 00669 " off - Disable at exit summary.\n" 00670 " byline - Enable at exit summary by file line number.\n" 00671 " byfunc - Enable at exit summary by function name.\n" 00672 " byfile - Enable at exit summary by file.\n" 00673 "\n" 00674 " Note: byline, byfunc, and byfile are cumulative enables.\n"; 00675 return NULL; 00676 case CLI_GENERATE: 00677 if (a->pos == 3) { 00678 const char * const options[] = { "off", "byline", "byfunc", "byfile", NULL }; 00679 00680 return ast_cli_complete(a->word, options, a->n); 00681 } 00682 return NULL; 00683 } 00684 00685 if (a->argc != 4) { 00686 return CLI_SHOWUSAGE; 00687 } 00688 00689 if (ast_false(a->argv[3])) { 00690 atexit_summary = SUMMARY_OFF; 00691 } else if (!strcasecmp(a->argv[3], "byline")) { 00692 atexit_summary |= SUMMARY_BY_LINE; 00693 } else if (!strcasecmp(a->argv[3], "byfunc")) { 00694 atexit_summary |= SUMMARY_BY_FUNC; 00695 } else if (!strcasecmp(a->argv[3], "byfile")) { 00696 atexit_summary |= SUMMARY_BY_FILE; 00697 } else { 00698 return CLI_SHOWUSAGE; 00699 } 00700 00701 if (atexit_summary) { 00702 buf[0] = '\0'; 00703 if (atexit_summary & SUMMARY_BY_LINE) { 00704 strcat(buf, "byline"); 00705 } 00706 if (atexit_summary & SUMMARY_BY_FUNC) { 00707 if (buf[0]) { 00708 strcat(buf, " | "); 00709 } 00710 strcat(buf, "byfunc"); 00711 } 00712 if (atexit_summary & SUMMARY_BY_FILE) { 00713 if (buf[0]) { 00714 strcat(buf, " | "); 00715 } 00716 strcat(buf, "byfile"); 00717 } 00718 } else { 00719 strcpy(buf, "Off"); 00720 } 00721 ast_cli(a->fd, "The atexit summary is: %s\n", buf); 00722 00723 return CLI_SUCCESS; 00724 }
static char* handle_memory_show_allocations | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 726 of file astmm.c.
References ast_cli_args::argc, ast_cli_args::argv, ARRAY_LEN, ast_cli(), AST_LIST_NEXT, ast_mutex_lock, ast_mutex_unlock, ast_region::cache, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_region::file, ast_region::func, ast_region::len, ast_region::lineno, region_check_fences(), regions, regions_check_all_fences(), reglock, and ast_cli_entry::usage.
00727 { 00728 const char *fn = NULL; 00729 struct ast_region *reg; 00730 unsigned int idx; 00731 unsigned int len = 0; 00732 unsigned int cache_len = 0; 00733 unsigned int count = 0; 00734 00735 switch (cmd) { 00736 case CLI_INIT: 00737 e->command = "memory show allocations"; 00738 e->usage = 00739 "Usage: memory show allocations [<file>|anomalies]\n" 00740 " Dumps a list of segments of allocated memory.\n" 00741 " Defaults to listing all memory allocations.\n" 00742 " <file> - Restricts output to memory allocated by the file.\n" 00743 " anomalies - Only check for fence violations.\n"; 00744 return NULL; 00745 case CLI_GENERATE: 00746 return NULL; 00747 } 00748 00749 if (a->argc == 4) { 00750 fn = a->argv[3]; 00751 } else if (a->argc != 3) { 00752 return CLI_SHOWUSAGE; 00753 } 00754 00755 /* Look for historical misspelled option as well. */ 00756 if (fn && (!strcasecmp(fn, "anomalies") || !strcasecmp(fn, "anomolies"))) { 00757 regions_check_all_fences(); 00758 ast_cli(a->fd, "Anomaly check complete.\n"); 00759 return CLI_SUCCESS; 00760 } 00761 00762 ast_mutex_lock(®lock); 00763 for (idx = 0; idx < ARRAY_LEN(regions); ++idx) { 00764 for (reg = regions[idx]; reg; reg = AST_LIST_NEXT(reg, node)) { 00765 if (fn && strcasecmp(fn, reg->file)) { 00766 continue; 00767 } 00768 00769 region_check_fences(reg); 00770 00771 ast_cli(a->fd, "%10u bytes allocated%s by %20s() line %5u of %s\n", 00772 (unsigned int) reg->len, reg->cache ? " (cache)" : "", 00773 reg->func, reg->lineno, reg->file); 00774 00775 len += reg->len; 00776 if (reg->cache) { 00777 cache_len += reg->len; 00778 } 00779 ++count; 00780 } 00781 } 00782 ast_mutex_unlock(®lock); 00783 00784 if (cache_len) { 00785 ast_cli(a->fd, "%u bytes allocated (%u in caches) in %u allocations\n", 00786 len, cache_len, count); 00787 } else { 00788 ast_cli(a->fd, "%u bytes allocated in %u allocations\n", len, count); 00789 } 00790 00791 return CLI_SUCCESS; 00792 }
static char* handle_memory_show_summary | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 794 of file astmm.c.
References ast_cli_args::argc, ast_cli_args::argv, ARRAY_LEN, ast_alloca, ast_cli(), ast_copy_string(), AST_LIST_NEXT, ast_mutex_lock, ast_mutex_unlock, ast_region::cache, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_region::file, ast_region::func, ast_region::len, ast_region::lineno, my_max, name, ast_region::next, regions, reglock, and ast_cli_entry::usage.
00795 { 00796 #define my_max(a, b) ((a) >= (b) ? (a) : (b)) 00797 00798 const char *fn = NULL; 00799 int idx; 00800 int cmp; 00801 struct ast_region *reg; 00802 unsigned int len = 0; 00803 unsigned int cache_len = 0; 00804 unsigned int count = 0; 00805 struct file_summary { 00806 struct file_summary *next; 00807 unsigned int len; 00808 unsigned int cache_len; 00809 unsigned int count; 00810 unsigned int lineno; 00811 char name[my_max(sizeof(reg->file), sizeof(reg->func))]; 00812 } *list = NULL, *cur, **prev; 00813 00814 switch (cmd) { 00815 case CLI_INIT: 00816 e->command = "memory show summary"; 00817 e->usage = 00818 "Usage: memory show summary [<file>]\n" 00819 " Summarizes heap memory allocations by file, or optionally\n" 00820 " by line, if a file is specified.\n"; 00821 return NULL; 00822 case CLI_GENERATE: 00823 return NULL; 00824 } 00825 00826 if (a->argc == 4) { 00827 fn = a->argv[3]; 00828 } else if (a->argc != 3) { 00829 return CLI_SHOWUSAGE; 00830 } 00831 00832 ast_mutex_lock(®lock); 00833 for (idx = 0; idx < ARRAY_LEN(regions); ++idx) { 00834 for (reg = regions[idx]; reg; reg = AST_LIST_NEXT(reg, node)) { 00835 if (fn) { 00836 if (strcasecmp(fn, reg->file)) { 00837 continue; 00838 } 00839 00840 /* Sort list by func/lineno. Find existing or place to insert. */ 00841 for (prev = &list; (cur = *prev); prev = &cur->next) { 00842 cmp = strcmp(cur->name, reg->func); 00843 if (cmp < 0) { 00844 continue; 00845 } 00846 if (cmp > 0) { 00847 /* Insert before current */ 00848 cur = NULL; 00849 break; 00850 } 00851 cmp = cur->lineno - reg->lineno; 00852 if (cmp < 0) { 00853 continue; 00854 } 00855 if (cmp > 0) { 00856 /* Insert before current */ 00857 cur = NULL; 00858 } 00859 break; 00860 } 00861 } else { 00862 /* Sort list by filename. Find existing or place to insert. */ 00863 for (prev = &list; (cur = *prev); prev = &cur->next) { 00864 cmp = strcmp(cur->name, reg->file); 00865 if (cmp < 0) { 00866 continue; 00867 } 00868 if (cmp > 0) { 00869 /* Insert before current */ 00870 cur = NULL; 00871 } 00872 break; 00873 } 00874 } 00875 00876 if (!cur) { 00877 cur = ast_alloca(sizeof(*cur)); 00878 memset(cur, 0, sizeof(*cur)); 00879 cur->lineno = reg->lineno; 00880 ast_copy_string(cur->name, fn ? reg->func : reg->file, sizeof(cur->name)); 00881 00882 cur->next = *prev; 00883 *prev = cur; 00884 } 00885 00886 cur->len += reg->len; 00887 if (reg->cache) { 00888 cur->cache_len += reg->len; 00889 } 00890 ++cur->count; 00891 } 00892 } 00893 ast_mutex_unlock(®lock); 00894 00895 /* Dump the whole list */ 00896 for (cur = list; cur; cur = cur->next) { 00897 len += cur->len; 00898 cache_len += cur->cache_len; 00899 count += cur->count; 00900 if (cur->cache_len) { 00901 if (fn) { 00902 ast_cli(a->fd, "%10u bytes (%10u cache) in %10u allocations by %20s() line %5u of %s\n", 00903 cur->len, cur->cache_len, cur->count, cur->name, cur->lineno, fn); 00904 } else { 00905 ast_cli(a->fd, "%10u bytes (%10u cache) in %10u allocations in file %s\n", 00906 cur->len, cur->cache_len, cur->count, cur->name); 00907 } 00908 } else { 00909 if (fn) { 00910 ast_cli(a->fd, "%10u bytes in %10u allocations by %20s() line %5u of %s\n", 00911 cur->len, cur->count, cur->name, cur->lineno, fn); 00912 } else { 00913 ast_cli(a->fd, "%10u bytes in %10u allocations in file %s\n", 00914 cur->len, cur->count, cur->name); 00915 } 00916 } 00917 } 00918 00919 if (cache_len) { 00920 ast_cli(a->fd, "%u bytes allocated (%u in caches) in %u allocations\n", 00921 len, cache_len, count); 00922 } else { 00923 ast_cli(a->fd, "%u bytes allocated in %u allocations\n", len, count); 00924 } 00925 00926 return CLI_SUCCESS; 00927 }
static void mm_atexit_ast | ( | void | ) | [static] |
Definition at line 1379 of file astmm.c.
References ARRAY_LEN, and ast_cli_unregister_multiple().
Referenced by __ast_mm_init_phase_2().
01380 { 01381 ast_cli_unregister_multiple(cli_memory, ARRAY_LEN(cli_memory)); 01382 }
static int mm_atexit_cmp | ( | struct ast_region * | left, | |
struct ast_region * | right | |||
) | [static] |
Definition at line 1005 of file astmm.c.
References ast_region::data, ast_region::file, ast_region::len, and ast_region::lineno.
Referenced by mm_atexit_list_merge().
01006 { 01007 int cmp; 01008 ptrdiff_t cmp_ptr; 01009 ssize_t cmp_size; 01010 01011 /* Sort by filename. */ 01012 cmp = strcmp(left->file, right->file); 01013 if (cmp) { 01014 return cmp; 01015 } 01016 01017 /* Sort by line number. */ 01018 cmp = left->lineno - right->lineno; 01019 if (cmp) { 01020 return cmp; 01021 } 01022 01023 /* Sort by allocated size. */ 01024 cmp_size = left->len - right->len; 01025 if (cmp_size) { 01026 if (cmp_size < 0) { 01027 return -1; 01028 } 01029 return 1; 01030 } 01031 01032 /* Sort by allocated pointers just because. */ 01033 cmp_ptr = left->data - right->data; 01034 if (cmp_ptr) { 01035 if (cmp_ptr < 0) { 01036 return -1; 01037 } 01038 return 1; 01039 } 01040 01041 return 0; 01042 }
static void mm_atexit_dump | ( | void | ) | [static] |
Definition at line 1297 of file astmm.c.
References AST_LIST_HEAD_NOLOCK_INIT_VALUE, astmm_log, mm_atexit_hash_list(), mm_atexit_hash_restore(), mm_atexit_list_sort(), mm_atexit_regions_list(), and mm_atexit_regions_summary().
Referenced by mm_atexit_final().
01298 { 01299 struct region_list alloced_atexit = AST_LIST_HEAD_NOLOCK_INIT_VALUE; 01300 size_t length; 01301 01302 length = mm_atexit_hash_list(&alloced_atexit); 01303 if (!length) { 01304 /* Wow! This is amazing! */ 01305 astmm_log("Exiting with all memory freed.\n"); 01306 return; 01307 } 01308 01309 mm_atexit_list_sort(&alloced_atexit, length); 01310 01311 astmm_log("Exiting with the following memory not freed:\n"); 01312 if (atexit_list) { 01313 mm_atexit_regions_list(&alloced_atexit); 01314 } 01315 if (atexit_summary) { 01316 mm_atexit_regions_summary(&alloced_atexit); 01317 } 01318 01319 /* 01320 * Put the alloced list back into regions[]. 01321 * 01322 * We have do do this because we can get called before all other 01323 * threads have terminated. 01324 */ 01325 mm_atexit_hash_restore(&alloced_atexit); 01326 }
static void mm_atexit_final | ( | void | ) | [static] |
Definition at line 1332 of file astmm.c.
References ast_mutex_lock, ast_mutex_unlock, freed_regions_flush(), minnows, mm_atexit_dump(), regions_check_all_fences(), reglock, and whales.
Referenced by __ast_mm_init_phase_1().
01333 { 01334 FILE *log; 01335 01336 /* Only wait if we want atexit allocation dumps. */ 01337 if (atexit_list || atexit_summary) { 01338 fprintf(stderr, "Waiting 10 seconds to let other threads die.\n"); 01339 sleep(10); 01340 } 01341 01342 regions_check_all_fences(); 01343 01344 /* Flush all delayed memory free circular arrays. */ 01345 freed_regions_flush(&whales); 01346 freed_regions_flush(&minnows); 01347 01348 /* Peform atexit allocation dumps. */ 01349 if (atexit_list || atexit_summary) { 01350 ast_mutex_lock(®lock); 01351 mm_atexit_dump(); 01352 ast_mutex_unlock(®lock); 01353 } 01354 01355 /* Close the log file. */ 01356 log = mmlog; 01357 mmlog = NULL; 01358 if (log) { 01359 fclose(log); 01360 } 01361 }
static size_t mm_atexit_hash_list | ( | struct region_list * | list | ) | [static] |
Definition at line 954 of file astmm.c.
References ARRAY_LEN, AST_LIST_INSERT_HEAD, AST_LIST_NEXT, and regions.
Referenced by mm_atexit_dump().
00955 { 00956 struct ast_region *reg; 00957 size_t total_length; 00958 int idx; 00959 00960 total_length = 0; 00961 for (idx = 0; idx < ARRAY_LEN(regions); ++idx) { 00962 while ((reg = regions[idx])) { 00963 regions[idx] = AST_LIST_NEXT(reg, node); 00964 AST_LIST_NEXT(reg, node) = NULL; 00965 AST_LIST_INSERT_HEAD(list, reg, node); 00966 ++total_length; 00967 } 00968 } 00969 return total_length; 00970 }
static void mm_atexit_hash_restore | ( | struct region_list * | list | ) | [static] |
Definition at line 982 of file astmm.c.
References AST_LIST_NEXT, AST_LIST_REMOVE_HEAD, ast_region::data, HASH, and regions.
Referenced by mm_atexit_dump().
00983 { 00984 struct ast_region *reg; 00985 int hash; 00986 00987 while ((reg = AST_LIST_REMOVE_HEAD(list, node))) { 00988 hash = HASH(reg->data); 00989 AST_LIST_NEXT(reg, node) = regions[hash]; 00990 regions[hash] = reg; 00991 } 00992 }
static void mm_atexit_list_merge | ( | struct region_list * | list, | |
struct region_list * | sub1, | |||
struct region_list * | sub2 | |||
) | [static] |
Definition at line 1054 of file astmm.c.
References AST_LIST_APPEND_LIST, AST_LIST_EMPTY, AST_LIST_FIRST, AST_LIST_INSERT_TAIL, AST_LIST_REMOVE_HEAD, and mm_atexit_cmp().
Referenced by mm_atexit_list_sort().
01055 { 01056 struct ast_region *reg; 01057 01058 for (;;) { 01059 if (AST_LIST_EMPTY(sub1)) { 01060 /* The remaining sublist goes onto the list. */ 01061 AST_LIST_APPEND_LIST(list, sub2, node); 01062 break; 01063 } 01064 if (AST_LIST_EMPTY(sub2)) { 01065 /* The remaining sublist goes onto the list. */ 01066 AST_LIST_APPEND_LIST(list, sub1, node); 01067 break; 01068 } 01069 01070 if (mm_atexit_cmp(AST_LIST_FIRST(sub1), AST_LIST_FIRST(sub2)) <= 0) { 01071 reg = AST_LIST_REMOVE_HEAD(sub1, node); 01072 } else { 01073 reg = AST_LIST_REMOVE_HEAD(sub2, node); 01074 } 01075 AST_LIST_INSERT_TAIL(list, reg, node); 01076 } 01077 }
static void mm_atexit_list_sort | ( | struct region_list * | list, | |
size_t | length | |||
) | [static] |
Semi-sorted merged list.
Sublists to merge. (Can only merge two sublists at this time.)
Sublist size.
Remaining elements in the list.
Number of sublist merge passes to process the list.
Definition at line 1125 of file astmm.c.
References ARRAY_LEN, AST_LIST_APPEND_LIST, AST_LIST_EMPTY, AST_LIST_HEAD_NOLOCK_INIT_VALUE, mm_atexit_list_merge(), and mm_atexit_list_split().
Referenced by mm_atexit_dump().
01126 { 01127 /*! Semi-sorted merged list. */ 01128 struct region_list merged = AST_LIST_HEAD_NOLOCK_INIT_VALUE; 01129 /*! Sublists to merge. (Can only merge two sublists at this time.) */ 01130 struct region_list sub[2] = { 01131 AST_LIST_HEAD_NOLOCK_INIT_VALUE, 01132 AST_LIST_HEAD_NOLOCK_INIT_VALUE 01133 }; 01134 /*! Sublist size. */ 01135 size_t size = 1; 01136 /*! Remaining elements in the list. */ 01137 size_t remaining; 01138 /*! Number of sublist merge passes to process the list. */ 01139 int passes; 01140 01141 for (;;) { 01142 remaining = length; 01143 01144 passes = 0; 01145 while (!AST_LIST_EMPTY(list)) { 01146 mm_atexit_list_split(list, sub, ARRAY_LEN(sub), size, &remaining); 01147 mm_atexit_list_merge(&merged, &sub[0], &sub[1]); 01148 ++passes; 01149 } 01150 AST_LIST_APPEND_LIST(list, &merged, node); 01151 if (passes <= 1) { 01152 /* The list is now sorted. */ 01153 break; 01154 } 01155 01156 /* Double the sublist size to remove for next round. */ 01157 size <<= 1; 01158 } 01159 }
static void mm_atexit_list_split | ( | struct region_list * | list, | |
struct region_list | sub[], | |||
size_t | num_lists, | |||
size_t | size, | |||
size_t * | remaining | |||
) | [static] |
Definition at line 1091 of file astmm.c.
References AST_LIST_APPEND_LIST, AST_LIST_INSERT_TAIL, and AST_LIST_REMOVE_HEAD.
Referenced by mm_atexit_list_sort().
01092 { 01093 int idx; 01094 01095 for (idx = 0; idx < num_lists; ++idx) { 01096 size_t count; 01097 01098 if (*remaining < size) { 01099 /* The remaining source list goes onto the sublist. */ 01100 AST_LIST_APPEND_LIST(&sub[idx], list, node); 01101 *remaining = 0; 01102 break; 01103 } 01104 01105 /* Take a sublist off the beginning of the source list. */ 01106 *remaining -= size; 01107 for (count = size; count--;) { 01108 struct ast_region *reg; 01109 01110 reg = AST_LIST_REMOVE_HEAD(list, node); 01111 AST_LIST_INSERT_TAIL(&sub[idx], reg, node); 01112 } 01113 } 01114 }
static void mm_atexit_regions_list | ( | struct region_list * | alloced | ) | [static] |
Definition at line 1169 of file astmm.c.
References AST_LIST_TRAVERSE, astmm_log, ast_region::cache, ast_region::data, ast_region::file, ast_region::func, ast_region::len, and ast_region::lineno.
Referenced by mm_atexit_dump().
01170 { 01171 struct ast_region *reg; 01172 01173 AST_LIST_TRAVERSE(alloced, reg, node) { 01174 astmm_log("%s %s() line %u: %u bytes%s at %p\n", 01175 reg->file, reg->func, reg->lineno, 01176 (unsigned int) reg->len, reg->cache ? " (cache)" : "", reg->data); 01177 } 01178 }
static void mm_atexit_regions_summary | ( | struct region_list * | alloced | ) | [static] |
Definition at line 1188 of file astmm.c.
References AST_LIST_NEXT, AST_LIST_TRAVERSE, astmm_log, ast_region::cache, ast_region::file, ast_region::func, ast_region::len, ast_region::lineno, ast_region::next, SUMMARY_BY_FILE, SUMMARY_BY_FUNC, SUMMARY_BY_LINE, and total.
Referenced by mm_atexit_dump().
01189 { 01190 struct ast_region *reg; 01191 struct ast_region *next; 01192 struct { 01193 unsigned int count; 01194 unsigned int len; 01195 unsigned int cache_len; 01196 } by_line, by_func, by_file, total; 01197 01198 by_line.count = 0; 01199 by_line.len = 0; 01200 by_line.cache_len = 0; 01201 01202 by_func.count = 0; 01203 by_func.len = 0; 01204 by_func.cache_len = 0; 01205 01206 by_file.count = 0; 01207 by_file.len = 0; 01208 by_file.cache_len = 0; 01209 01210 total.count = 0; 01211 total.len = 0; 01212 total.cache_len = 0; 01213 01214 AST_LIST_TRAVERSE(alloced, reg, node) { 01215 next = AST_LIST_NEXT(reg, node); 01216 01217 ++by_line.count; 01218 by_line.len += reg->len; 01219 if (reg->cache) { 01220 by_line.cache_len += reg->len; 01221 } 01222 if (next && !strcmp(reg->file, next->file) && reg->lineno == next->lineno) { 01223 continue; 01224 } 01225 if (atexit_summary & SUMMARY_BY_LINE) { 01226 if (by_line.cache_len) { 01227 astmm_log("%10u bytes (%u in caches) in %u allocations. %s %s() line %u\n", 01228 by_line.len, by_line.cache_len, by_line.count, reg->file, reg->func, reg->lineno); 01229 } else { 01230 astmm_log("%10u bytes in %5u allocations. %s %s() line %u\n", 01231 by_line.len, by_line.count, reg->file, reg->func, reg->lineno); 01232 } 01233 } 01234 01235 by_func.count += by_line.count; 01236 by_func.len += by_line.len; 01237 by_func.cache_len += by_line.cache_len; 01238 by_line.count = 0; 01239 by_line.len = 0; 01240 by_line.cache_len = 0; 01241 if (next && !strcmp(reg->file, next->file) && !strcmp(reg->func, next->func)) { 01242 continue; 01243 } 01244 if (atexit_summary & SUMMARY_BY_FUNC) { 01245 if (by_func.cache_len) { 01246 astmm_log("%10u bytes (%u in caches) in %u allocations. %s %s()\n", 01247 by_func.len, by_func.cache_len, by_func.count, reg->file, reg->func); 01248 } else { 01249 astmm_log("%10u bytes in %5u allocations. %s %s()\n", 01250 by_func.len, by_func.count, reg->file, reg->func); 01251 } 01252 } 01253 01254 by_file.count += by_func.count; 01255 by_file.len += by_func.len; 01256 by_file.cache_len += by_func.cache_len; 01257 by_func.count = 0; 01258 by_func.len = 0; 01259 by_func.cache_len = 0; 01260 if (next && !strcmp(reg->file, next->file)) { 01261 continue; 01262 } 01263 if (atexit_summary & SUMMARY_BY_FILE) { 01264 if (by_file.cache_len) { 01265 astmm_log("%10u bytes (%u in caches) in %u allocations. %s\n", 01266 by_file.len, by_file.cache_len, by_file.count, reg->file); 01267 } else { 01268 astmm_log("%10u bytes in %5u allocations. %s\n", 01269 by_file.len, by_file.count, reg->file); 01270 } 01271 } 01272 01273 total.count += by_file.count; 01274 total.len += by_file.len; 01275 total.cache_len += by_file.cache_len; 01276 by_file.count = 0; 01277 by_file.len = 0; 01278 by_file.cache_len = 0; 01279 } 01280 01281 if (total.cache_len) { 01282 astmm_log("%u bytes (%u in caches) in %u allocations.\n", 01283 total.len, total.cache_len, total.count); 01284 } else { 01285 astmm_log("%u bytes in %u allocations.\n", total.len, total.count); 01286 } 01287 }
static void my_do_crash | ( | void | ) | [static] |
Definition at line 167 of file astmm.c.
References ast_do_crash().
Referenced by __ast_free_region(), __ast_realloc(), region_check_fences(), and region_data_check().
00168 { 00169 /* 00170 * Give the logger a chance to get the message out, just in case 00171 * we abort(), or Asterisk crashes due to whatever problem just 00172 * happened. 00173 */ 00174 usleep(1); 00175 ast_do_crash(); 00176 }
static void region_check_fences | ( | struct ast_region * | reg | ) | [static] |
Definition at line 370 of file astmm.c.
References astmm_log, ast_region::data, FENCE_MAGIC, ast_region::file, ast_region::func, get_unaligned_uint32(), ast_region::len, ast_region::lineno, and my_do_crash().
Referenced by __ast_free_region(), handle_memory_show_allocations(), and regions_check_all_fences().
00371 { 00372 unsigned int *fence; 00373 00374 /* 00375 * We use the bytes just preceeding reg->data and not reg->fence 00376 * because there is likely to be padding between reg->fence and 00377 * reg->data for reg->data alignment. 00378 */ 00379 fence = (unsigned int *) (reg->data - sizeof(*fence)); 00380 if (*fence != FENCE_MAGIC) { 00381 astmm_log("WARNING: Low fence violation of %p allocated at %s %s() line %d\n", 00382 reg->data, reg->file, reg->func, reg->lineno); 00383 my_do_crash(); 00384 } 00385 fence = (unsigned int *) (reg->data + reg->len); 00386 if (get_unaligned_uint32(fence) != FENCE_MAGIC) { 00387 astmm_log("WARNING: High fence violation of %p allocated at %s %s() line %d\n", 00388 reg->data, reg->file, reg->func, reg->lineno); 00389 my_do_crash(); 00390 } 00391 }
static void region_data_check | ( | struct ast_region * | reg | ) | [static] |
Definition at line 251 of file astmm.c.
References astmm_log, ast_region::data, ast_region::fence, ast_region::file, FREED_MAGIC, ast_region::func, ast_region::len, ast_region::lineno, and my_do_crash().
Referenced by freed_regions_flush(), and region_free().
00252 { 00253 void *end; 00254 unsigned int *pos; 00255 00256 /* 00257 * Check the lower fence, the payload, and whatever amount of 00258 * the higher fence that falls into alignment with the payload. 00259 */ 00260 end = reg->data + reg->len; 00261 for (pos = ®->fence; (void *) pos <= end; ++pos) { 00262 if (*pos != FREED_MAGIC) { 00263 astmm_log("WARNING: Memory corrupted after free of %p allocated at %s %s() line %d\n", 00264 reg->data, reg->file, reg->func, reg->lineno); 00265 my_do_crash(); 00266 break; 00267 } 00268 } 00269 }
static void region_data_wipe | ( | struct ast_region * | reg | ) | [static] |
Definition at line 228 of file astmm.c.
References ast_region::data, ast_region::fence, FREED_MAGIC, and ast_region::len.
Referenced by region_free().
00229 { 00230 void *end; 00231 unsigned int *pos; 00232 00233 /* 00234 * Wipe the lower fence, the payload, and whatever amount of the 00235 * higher fence that falls into alignment with the payload. 00236 */ 00237 end = reg->data + reg->len; 00238 for (pos = ®->fence; (void *) pos <= end; ++pos) { 00239 *pos = FREED_MAGIC; 00240 } 00241 }
static struct ast_region* region_find | ( | void * | ptr | ) | [static, read] |
Definition at line 487 of file astmm.c.
References AST_LIST_NEXT, ast_region::data, HASH, and regions.
Referenced by __ast_realloc().
00488 { 00489 int hash; 00490 struct ast_region *reg; 00491 00492 hash = HASH(ptr); 00493 for (reg = regions[hash]; reg; reg = AST_LIST_NEXT(reg, node)) { 00494 if (reg->data == ptr) { 00495 break; 00496 } 00497 } 00498 00499 return reg; 00500 }
static void region_free | ( | struct ast_freed_regions * | freed, | |
struct ast_region * | reg | |||
) | [static] |
Definition at line 306 of file astmm.c.
References ARRAY_LEN, ast_mutex_lock, ast_mutex_unlock, free, ast_freed_regions::index, region_data_check(), region_data_wipe(), ast_freed_regions::regions, and reglock.
Referenced by __ast_free_region().
00307 { 00308 struct ast_region *old; 00309 00310 region_data_wipe(reg); 00311 00312 ast_mutex_lock(®lock); 00313 old = freed->regions[freed->index]; 00314 freed->regions[freed->index] = reg; 00315 00316 ++freed->index; 00317 if (ARRAY_LEN(freed->regions) <= freed->index) { 00318 freed->index = 0; 00319 } 00320 ast_mutex_unlock(®lock); 00321 00322 if (old) { 00323 region_data_check(old); 00324 free(old); 00325 } 00326 }
static struct ast_region* region_remove | ( | void * | ptr | ) | [static, read] |
Definition at line 337 of file astmm.c.
References AST_LIST_NEXT, ast_mutex_lock, ast_mutex_unlock, ast_region::data, HASH, regions, and reglock.
Referenced by __ast_free_region().
00338 { 00339 int hash; 00340 struct ast_region *reg; 00341 struct ast_region *prev = NULL; 00342 00343 hash = HASH(ptr); 00344 00345 ast_mutex_lock(®lock); 00346 for (reg = regions[hash]; reg; reg = AST_LIST_NEXT(reg, node)) { 00347 if (reg->data == ptr) { 00348 if (prev) { 00349 AST_LIST_NEXT(prev, node) = AST_LIST_NEXT(reg, node); 00350 } else { 00351 regions[hash] = AST_LIST_NEXT(reg, node); 00352 } 00353 break; 00354 } 00355 prev = reg; 00356 } 00357 ast_mutex_unlock(®lock); 00358 00359 return reg; 00360 }
static void regions_check_all_fences | ( | void | ) | [static] |
Definition at line 399 of file astmm.c.
References ARRAY_LEN, AST_LIST_NEXT, ast_mutex_lock, ast_mutex_unlock, region_check_fences(), regions, and reglock.
Referenced by handle_memory_show_allocations(), and mm_atexit_final().
00400 { 00401 int idx; 00402 struct ast_region *reg; 00403 00404 ast_mutex_lock(®lock); 00405 for (idx = 0; idx < ARRAY_LEN(regions); ++idx) { 00406 for (reg = regions[idx]; reg; reg = AST_LIST_NEXT(reg, node)) { 00407 region_check_fences(reg); 00408 } 00409 } 00410 ast_mutex_unlock(®lock); 00411 }
int atexit_list [static] |
enum summary_opts atexit_summary [static] |
struct ast_cli_entry cli_memory[] [static] |
struct ast_freed_regions minnows [static] |
Small memory blocks that have been freed.
Definition at line 127 of file astmm.c.
Referenced by __ast_free_region(), and mm_atexit_final().
struct ast_region* regions[SOME_PRIME] [static] |
Hash table of lists of active allocated memory regions.
Definition at line 109 of file astmm.c.
Referenced by __ast_alloc_region(), handle_memory_show_allocations(), handle_memory_show_summary(), mm_atexit_hash_list(), mm_atexit_hash_restore(), region_find(), region_remove(), and regions_check_all_fences().
ast_mutex_t reglock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 0 } [static] |
Tracking this mutex will cause infinite recursion, as the mutex tracking code allocates memory
Definition at line 149 of file astmm.c.
Referenced by __ast_alloc_region(), __ast_realloc(), freed_regions_flush(), handle_memory_show_allocations(), handle_memory_show_summary(), mm_atexit_final(), region_free(), region_remove(), and regions_check_all_fences().
struct ast_freed_regions whales [static] |
Large memory blocks that have been freed.
Definition at line 125 of file astmm.c.
Referenced by __ast_free_region(), and mm_atexit_final().