Tue Aug 20 16:34:47 2013

Asterisk developer's documentation


astmm.c File Reference

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_regionregion_find (void *ptr)
static void region_free (struct ast_freed_regions *freed, struct ast_region *reg)
static struct ast_regionregion_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_regionregions [SOME_PRIME]
static ast_mutex_t reglock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 0 }
static struct ast_freed_regions whales

Detailed Description

Memory Management.

Author:
Mark Spencer <markster@digium.com>
Richard Mudgett <rmudgett@digium.com>

Definition in file astmm.c.


Define Documentation

#define astmm_log ( ...   ) 
#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

Number of freed regions to keep around to delay actually freeing them.

Definition at line 112 of file astmm.c.

#define HASH (  )     (((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,
 )     ((a) >= (b) ? (a) : (b))
#define SOME_PRIME   1567

The larger the number the faster memory can be freed. However, more memory then is used for the regions[] hash table.

Definition at line 51 of file astmm.c.


Enumeration Type Documentation

enum func_type
Enumerator:
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 };

Enumerator:
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 };


Function Documentation

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(&reglock);
00213    AST_LIST_NEXT(reg, node) = regions[hash];
00214    regions[hash] = reg;
00215    ast_mutex_unlock(&reglock);
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.

Note:
Must be called first thing in main().
Returns:
Nothing

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.

Returns:
Nothing

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(&reglock);
00510       found = region_find(ptr);
00511       if (!found) {
00512          ast_mutex_unlock(&reglock);
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(&reglock);
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(&reglock);
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(&reglock);
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(&reglock);
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(&reglock);
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(&reglock);
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(&reglock);
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().

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(&reglock);
01351       mm_atexit_dump();
01352       ast_mutex_unlock(&reglock);
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 = &reg->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 = &reg->fence; (void *) pos <= end; ++pos) {
00239       *pos = FREED_MAGIC;
00240    }
00241 }

static struct ast_region* region_find ( void *  ptr  )  [static, read]
Note:
reglock must be locked before calling.

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(&reglock);
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(&reglock);
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(&reglock);
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(&reglock);
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(&reglock);
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(&reglock);
00411 }


Variable Documentation

int atexit_list [static]

Nonzero if the unfreed regions are listed at exit.

Definition at line 143 of file astmm.c.

Summary options of unfreed regions at exit.

Definition at line 141 of file astmm.c.

struct ast_cli_entry cli_memory[] [static]

Definition at line 929 of file astmm.c.

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().

FILE* mmlog [static]

Definition at line 77 of file astmm.c.

struct ast_region* regions[SOME_PRIME] [static]
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().


Generated on 20 Aug 2013 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1