Mon Aug 31 12:30:20 2015

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   0xfeedbabe
#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)
void ast_free_ptr (void *ptr)
void * ast_std_calloc (size_t nmemb, size_t size)
void ast_std_free (void *ptr)
void * ast_std_malloc (size_t size)
void * ast_std_realloc (void *ptr, size_t size)
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   0xfeedbabe

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

00204 {
00205    struct ast_region *reg;
00206    unsigned int *fence;
00207    int hash;
00208 
00209    if (!(reg = malloc(size + sizeof(*reg) + sizeof(*fence)))) {
00210       astmm_log("Memory Allocation Failure - '%d' bytes at %s %s() line %d\n",
00211          (int) size, file, func, lineno);
00212       return NULL;
00213    }
00214 
00215    reg->len = size;
00216    reg->cache = cache;
00217    reg->lineno = lineno;
00218    reg->which = which;
00219    ast_copy_string(reg->file, file, sizeof(reg->file));
00220    ast_copy_string(reg->func, func, sizeof(reg->func));
00221 
00222    /*
00223     * Init lower fence.
00224     *
00225     * We use the bytes just preceeding reg->data and not reg->fence
00226     * because there is likely to be padding between reg->fence and
00227     * reg->data for reg->data alignment.
00228     */
00229    fence = (unsigned int *) (reg->data - sizeof(*fence));
00230    *fence = FENCE_MAGIC;
00231 
00232    /* Init higher fence. */
00233    fence = (unsigned int *) (reg->data + reg->len);
00234    put_unaligned_uint32(fence, FENCE_MAGIC);
00235 
00236    hash = HASH(reg->data);
00237    ast_mutex_lock(&reglock);
00238    AST_LIST_NEXT(reg, node) = regions[hash];
00239    regions[hash] = reg;
00240    ast_mutex_unlock(&reglock);
00241 
00242    return reg->data;
00243 }

int __ast_asprintf ( const char *  file,
int  lineno,
const char *  func,
char **  strp,
const char *  fmt,
  ... 
)

Definition at line 609 of file astmm.c.

References __ast_alloc_region(), and FUNC_ASPRINTF.

00610 {
00611    int size;
00612    va_list ap, ap2;
00613    char s;
00614 
00615    *strp = NULL;
00616    va_start(ap, fmt);
00617    va_copy(ap2, ap);
00618    size = vsnprintf(&s, 1, fmt, ap2);
00619    va_end(ap2);
00620    if (!(*strp = __ast_alloc_region(size + 1, FUNC_ASPRINTF, file, lineno, func, 0))) {
00621       va_end(ap);
00622       return -1;
00623    }
00624    vsnprintf(*strp, size + 1, fmt, ap);
00625    va_end(ap);
00626 
00627    return size;
00628 }

void* __ast_calloc ( size_t  nmemb,
size_t  size,
const char *  file,
int  lineno,
const char *  func 
)

Definition at line 467 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().

00468 {
00469    void *ptr;
00470 
00471    ptr = __ast_alloc_region(size * nmemb, FUNC_CALLOC, file, lineno, func, 0);
00472    if (ptr) {
00473       memset(ptr, 0, size * nmemb);
00474    }
00475 
00476    return ptr;
00477 }

void* __ast_calloc_cache ( size_t  nmemb,
size_t  size,
const char *  file,
int  lineno,
const char *  func 
)

Definition at line 479 of file astmm.c.

References __ast_alloc_region(), and FUNC_CALLOC.

00480 {
00481    void *ptr;
00482 
00483    ptr = __ast_alloc_region(size * nmemb, FUNC_CALLOC, file, lineno, func, 1);
00484    if (ptr) {
00485       memset(ptr, 0, size * nmemb);
00486    }
00487 
00488    return ptr;
00489 }

void __ast_free ( void *  ptr,
const char *  file,
int  lineno,
const char *  func 
)

Definition at line 504 of file astmm.c.

References __ast_free_region().

00505 {
00506    __ast_free_region(ptr, file, lineno, func);
00507 }

static void __ast_free_region ( void *  ptr,
const char *  file,
int  lineno,
const char *  func 
) [static]

Definition at line 438 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().

00439 {
00440    struct ast_region *reg;
00441 
00442    if (!ptr) {
00443       return;
00444    }
00445 
00446    reg = region_remove(ptr);
00447    if (reg) {
00448       region_check_fences(reg);
00449 
00450       if (reg->len <= MINNOWS_MAX_SIZE) {
00451          region_free(&minnows, reg);
00452       } else {
00453          region_free(&whales, reg);
00454       }
00455    } else {
00456       /*
00457        * This memory region is not registered.  It could be because of
00458        * a double free or the memory block was not allocated by the
00459        * malloc debug code.
00460        */
00461       astmm_log("WARNING: Freeing unregistered memory %p by %s %s() line %d\n",
00462          ptr, file, func, lineno);
00463       my_do_crash();
00464    }
00465 }

void* __ast_malloc ( size_t  size,
const char *  file,
int  lineno,
const char *  func 
)

Definition at line 491 of file astmm.c.

References __ast_alloc_region(), FUNC_MALLOC, and MALLOC_FILLER.

Referenced by __ast_cc_config_params_init().

00492 {
00493    void *ptr;
00494 
00495    ptr = __ast_alloc_region(size, FUNC_MALLOC, file, lineno, func, 0);
00496    if (ptr) {
00497       /* Make sure that the malloced memory is not zero. */
00498       memset(ptr, MALLOC_FILLER, size);
00499    }
00500 
00501    return ptr;
00502 }

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 1395 of file astmm.c.

References mm_atexit_final().

Referenced by main().

01396 {
01397    atexit(mm_atexit_final);
01398 }

void __ast_mm_init_phase_2 ( void   ) 

Initialize malloc debug phase 2.

Returns:
Nothing

Definition at line 1414 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().

01415 {
01416    char filename[PATH_MAX];
01417 
01418    ast_cli_register_multiple(cli_memory, ARRAY_LEN(cli_memory));
01419 
01420    snprintf(filename, sizeof(filename), "%s/mmlog", ast_config_AST_LOG_DIR);
01421 
01422    ast_verb(1, "Asterisk Malloc Debugger Started (see %s))\n", filename);
01423 
01424    mmlog = fopen(filename, "a+");
01425    if (mmlog) {
01426       fprintf(mmlog, "%ld - New session\n", (long) time(NULL));
01427       fflush(mmlog);
01428    } else {
01429       ast_log(LOG_ERROR, "Could not open malloc debug log file: %s\n", filename);
01430    }
01431 
01432    ast_register_atexit(mm_atexit_ast);
01433 }

void* __ast_realloc ( void *  ptr,
size_t  size,
const char *  file,
int  lineno,
const char *  func 
)

Definition at line 527 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().

00528 {
00529    size_t len;
00530    struct ast_region *found;
00531    void *new_mem;
00532 
00533    if (ptr) {
00534       ast_mutex_lock(&reglock);
00535       found = region_find(ptr);
00536       if (!found) {
00537          ast_mutex_unlock(&reglock);
00538          astmm_log("WARNING: Realloc of unregistered memory %p by %s %s() line %d\n",
00539             ptr, file, func, lineno);
00540          my_do_crash();
00541          return NULL;
00542       }
00543       len = found->len;
00544       ast_mutex_unlock(&reglock);
00545    } else {
00546       found = NULL;
00547       len = 0;
00548    }
00549 
00550    if (!size) {
00551       __ast_free_region(ptr, file, lineno, func);
00552       return NULL;
00553    }
00554 
00555    new_mem = __ast_alloc_region(size, FUNC_REALLOC, file, lineno, func, 0);
00556    if (new_mem) {
00557       if (found) {
00558          /* Copy the old data to the new malloced memory. */
00559          if (size <= len) {
00560             memcpy(new_mem, ptr, size);
00561          } else {
00562             memcpy(new_mem, ptr, len);
00563             /* Make sure that the added memory is not zero. */
00564             memset(new_mem + len, MALLOC_FILLER, size - len);
00565          }
00566          __ast_free_region(ptr, file, lineno, func);
00567       } else {
00568          /* Make sure that the malloced memory is not zero. */
00569          memset(new_mem, MALLOC_FILLER, size);
00570       }
00571    }
00572 
00573    return new_mem;
00574 }

char* __ast_strdup ( const char *  s,
const char *  file,
int  lineno,
const char *  func 
)

Definition at line 576 of file astmm.c.

References __ast_alloc_region(), and FUNC_STRDUP.

00577 {
00578    size_t len;
00579    void *ptr;
00580 
00581    if (!s)
00582       return NULL;
00583 
00584    len = strlen(s) + 1;
00585    if ((ptr = __ast_alloc_region(len, FUNC_STRDUP, file, lineno, func, 0)))
00586       strcpy(ptr, s);
00587 
00588    return ptr;
00589 }

char* __ast_strndup ( const char *  s,
size_t  n,
const char *  file,
int  lineno,
const char *  func 
)

Definition at line 591 of file astmm.c.

References __ast_alloc_region(), and FUNC_STRNDUP.

00592 {
00593    size_t len;
00594    char *ptr;
00595 
00596    if (!s) {
00597       return NULL;
00598    }
00599 
00600    len = strnlen(s, n);
00601    if ((ptr = __ast_alloc_region(len + 1, FUNC_STRNDUP, file, lineno, func, 0))) {
00602       memcpy(ptr, s, len);
00603       ptr[len] = '\0';
00604    }
00605 
00606    return ptr;
00607 }

int __ast_vasprintf ( char **  strp,
const char *  fmt,
va_list  ap,
const char *  file,
int  lineno,
const char *  func 
)

Definition at line 630 of file astmm.c.

References __ast_alloc_region(), and FUNC_VASPRINTF.

00631 {
00632    int size;
00633    va_list ap2;
00634    char s;
00635 
00636    *strp = NULL;
00637    va_copy(ap2, ap);
00638    size = vsnprintf(&s, 1, fmt, ap2);
00639    va_end(ap2);
00640    if (!(*strp = __ast_alloc_region(size + 1, FUNC_VASPRINTF, file, lineno, func, 0))) {
00641       va_end(ap);
00642       return -1;
00643    }
00644    vsnprintf(*strp, size + 1, fmt, ap);
00645 
00646    return size;
00647 }

void ast_free_ptr ( void *  ptr  ) 
void* ast_std_calloc ( size_t  nmemb,
size_t  size 
)

Definition at line 165 of file astmm.c.

References calloc.

Referenced by ast_bt_get_symbols().

00166 {
00167    return calloc(nmemb, size);
00168 }

void ast_std_free ( void *  ptr  ) 

Definition at line 175 of file astmm.c.

References free.

Referenced by ao2_bt(), ast_backtrace(), ast_bt_get_symbols(), and complete_fn().

00176 {
00177    free(ptr);
00178 }

void* ast_std_malloc ( size_t  size  ) 

Definition at line 160 of file astmm.c.

References malloc.

00161 {
00162    return malloc(size);
00163 }

void* ast_std_realloc ( void *  ptr,
size_t  size 
)

Definition at line 170 of file astmm.c.

References realloc.

Referenced by ast_bt_get_symbols().

00171 {
00172    return realloc(ptr, size);
00173 }

static void freed_regions_flush ( struct ast_freed_regions freed  )  [static]

Definition at line 304 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().

00305 {
00306    int idx;
00307    struct ast_region *old;
00308 
00309    ast_mutex_lock(&reglock);
00310    for (idx = 0; idx < ARRAY_LEN(freed->regions); ++idx) {
00311       old = freed->regions[idx];
00312       freed->regions[idx] = NULL;
00313       if (old) {
00314          region_data_check(old);
00315          free(old);
00316       }
00317    }
00318    freed->index = 0;
00319    ast_mutex_unlock(&reglock);
00320 }

static char* handle_memory_atexit_list ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 649 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.

00650 {
00651    switch (cmd) {
00652    case CLI_INIT:
00653       e->command = "memory atexit list";
00654       e->usage =
00655          "Usage: memory atexit list {on|off}\n"
00656          "       Enable dumping a list of still allocated memory segments at exit.\n";
00657       return NULL;
00658    case CLI_GENERATE:
00659       if (a->pos == 3) {
00660          const char * const options[] = { "off", "on", NULL };
00661 
00662          return ast_cli_complete(a->word, options, a->n);
00663       }
00664       return NULL;
00665    }
00666 
00667    if (a->argc != 4) {
00668       return CLI_SHOWUSAGE;
00669    }
00670 
00671    if (ast_true(a->argv[3])) {
00672       atexit_list = 1;
00673    } else if (ast_false(a->argv[3])) {
00674       atexit_list = 0;
00675    } else {
00676       return CLI_SHOWUSAGE;
00677    }
00678 
00679    ast_cli(a->fd, "The atexit list is: %s\n", atexit_list ? "On" : "Off");
00680 
00681    return CLI_SUCCESS;
00682 }

static char* handle_memory_atexit_summary ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 684 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.

00685 {
00686    char buf[80];
00687 
00688    switch (cmd) {
00689    case CLI_INIT:
00690       e->command = "memory atexit summary";
00691       e->usage =
00692          "Usage: memory atexit summary {off|byline|byfunc|byfile}\n"
00693          "       Summary of still allocated memory segments at exit options.\n"
00694          "       off - Disable at exit summary.\n"
00695          "       byline - Enable at exit summary by file line number.\n"
00696          "       byfunc - Enable at exit summary by function name.\n"
00697          "       byfile - Enable at exit summary by file.\n"
00698          "\n"
00699          "       Note: byline, byfunc, and byfile are cumulative enables.\n";
00700       return NULL;
00701    case CLI_GENERATE:
00702       if (a->pos == 3) {
00703          const char * const options[] = { "off", "byline", "byfunc", "byfile", NULL };
00704 
00705          return ast_cli_complete(a->word, options, a->n);
00706       }
00707       return NULL;
00708    }
00709 
00710    if (a->argc != 4) {
00711       return CLI_SHOWUSAGE;
00712    }
00713 
00714    if (ast_false(a->argv[3])) {
00715       atexit_summary = SUMMARY_OFF;
00716    } else if (!strcasecmp(a->argv[3], "byline")) {
00717       atexit_summary |= SUMMARY_BY_LINE;
00718    } else if (!strcasecmp(a->argv[3], "byfunc")) {
00719       atexit_summary |= SUMMARY_BY_FUNC;
00720    } else if (!strcasecmp(a->argv[3], "byfile")) {
00721       atexit_summary |= SUMMARY_BY_FILE;
00722    } else {
00723       return CLI_SHOWUSAGE;
00724    }
00725 
00726    if (atexit_summary) {
00727       buf[0] = '\0';
00728       if (atexit_summary & SUMMARY_BY_LINE) {
00729          strcat(buf, "byline");
00730       }
00731       if (atexit_summary & SUMMARY_BY_FUNC) {
00732          if (buf[0]) {
00733             strcat(buf, " | ");
00734          }
00735          strcat(buf, "byfunc");
00736       }
00737       if (atexit_summary & SUMMARY_BY_FILE) {
00738          if (buf[0]) {
00739             strcat(buf, " | ");
00740          }
00741          strcat(buf, "byfile");
00742       }
00743    } else {
00744       strcpy(buf, "Off");
00745    }
00746    ast_cli(a->fd, "The atexit summary is: %s\n", buf);
00747 
00748    return CLI_SUCCESS;
00749 }

static char* handle_memory_show_allocations ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 751 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.

00752 {
00753    const char *fn = NULL;
00754    struct ast_region *reg;
00755    unsigned int idx;
00756    unsigned int len = 0;
00757    unsigned int cache_len = 0;
00758    unsigned int count = 0;
00759 
00760    switch (cmd) {
00761    case CLI_INIT:
00762       e->command = "memory show allocations";
00763       e->usage =
00764          "Usage: memory show allocations [<file>|anomalies]\n"
00765          "       Dumps a list of segments of allocated memory.\n"
00766          "       Defaults to listing all memory allocations.\n"
00767          "       <file> - Restricts output to memory allocated by the file.\n"
00768          "       anomalies - Only check for fence violations.\n";
00769       return NULL;
00770    case CLI_GENERATE:
00771       return NULL;
00772    }
00773 
00774    if (a->argc == 4) {
00775       fn = a->argv[3];
00776    } else if (a->argc != 3) {
00777       return CLI_SHOWUSAGE;
00778    }
00779 
00780    /* Look for historical misspelled option as well. */
00781    if (fn && (!strcasecmp(fn, "anomalies") || !strcasecmp(fn, "anomolies"))) {
00782       regions_check_all_fences();
00783       ast_cli(a->fd, "Anomaly check complete.\n");
00784       return CLI_SUCCESS;
00785    }
00786 
00787    ast_mutex_lock(&reglock);
00788    for (idx = 0; idx < ARRAY_LEN(regions); ++idx) {
00789       for (reg = regions[idx]; reg; reg = AST_LIST_NEXT(reg, node)) {
00790          if (fn && strcasecmp(fn, reg->file)) {
00791             continue;
00792          }
00793 
00794          region_check_fences(reg);
00795 
00796          ast_cli(a->fd, "%10u bytes allocated%s by %20s() line %5u of %s\n",
00797             (unsigned int) reg->len, reg->cache ? " (cache)" : "",
00798             reg->func, reg->lineno, reg->file);
00799 
00800          len += reg->len;
00801          if (reg->cache) {
00802             cache_len += reg->len;
00803          }
00804          ++count;
00805       }
00806    }
00807    ast_mutex_unlock(&reglock);
00808 
00809    if (cache_len) {
00810       ast_cli(a->fd, "%u bytes allocated (%u in caches) in %u allocations\n",
00811          len, cache_len, count);
00812    } else {
00813       ast_cli(a->fd, "%u bytes allocated in %u allocations\n", len, count);
00814    }
00815 
00816    return CLI_SUCCESS;
00817 }

static char* handle_memory_show_summary ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 819 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.

00820 {
00821 #define my_max(a, b) ((a) >= (b) ? (a) : (b))
00822 
00823    const char *fn = NULL;
00824    int idx;
00825    int cmp;
00826    struct ast_region *reg;
00827    unsigned int len = 0;
00828    unsigned int cache_len = 0;
00829    unsigned int count = 0;
00830    struct file_summary {
00831       struct file_summary *next;
00832       unsigned int len;
00833       unsigned int cache_len;
00834       unsigned int count;
00835       unsigned int lineno;
00836       char name[my_max(sizeof(reg->file), sizeof(reg->func))];
00837    } *list = NULL, *cur, **prev;
00838 
00839    switch (cmd) {
00840    case CLI_INIT:
00841       e->command = "memory show summary";
00842       e->usage =
00843          "Usage: memory show summary [<file>]\n"
00844          "       Summarizes heap memory allocations by file, or optionally\n"
00845          "       by line, if a file is specified.\n";
00846       return NULL;
00847    case CLI_GENERATE:
00848       return NULL;
00849    }
00850 
00851    if (a->argc == 4) {
00852       fn = a->argv[3];
00853    } else if (a->argc != 3) {
00854       return CLI_SHOWUSAGE;
00855    }
00856 
00857    ast_mutex_lock(&reglock);
00858    for (idx = 0; idx < ARRAY_LEN(regions); ++idx) {
00859       for (reg = regions[idx]; reg; reg = AST_LIST_NEXT(reg, node)) {
00860          if (fn) {
00861             if (strcasecmp(fn, reg->file)) {
00862                continue;
00863             }
00864 
00865             /* Sort list by func/lineno.  Find existing or place to insert. */
00866             for (prev = &list; (cur = *prev); prev = &cur->next) {
00867                cmp = strcmp(cur->name, reg->func);
00868                if (cmp < 0) {
00869                   continue;
00870                }
00871                if (cmp > 0) {
00872                   /* Insert before current */
00873                   cur = NULL;
00874                   break;
00875                }
00876                cmp = cur->lineno - reg->lineno;
00877                if (cmp < 0) {
00878                   continue;
00879                }
00880                if (cmp > 0) {
00881                   /* Insert before current */
00882                   cur = NULL;
00883                }
00884                break;
00885             }
00886          } else {
00887             /* Sort list by filename.  Find existing or place to insert. */
00888             for (prev = &list; (cur = *prev); prev = &cur->next) {
00889                cmp = strcmp(cur->name, reg->file);
00890                if (cmp < 0) {
00891                   continue;
00892                }
00893                if (cmp > 0) {
00894                   /* Insert before current */
00895                   cur = NULL;
00896                }
00897                break;
00898             }
00899          }
00900 
00901          if (!cur) {
00902             cur = ast_alloca(sizeof(*cur));
00903             memset(cur, 0, sizeof(*cur));
00904             cur->lineno = reg->lineno;
00905             ast_copy_string(cur->name, fn ? reg->func : reg->file, sizeof(cur->name));
00906 
00907             cur->next = *prev;
00908             *prev = cur;
00909          }
00910 
00911          cur->len += reg->len;
00912          if (reg->cache) {
00913             cur->cache_len += reg->len;
00914          }
00915          ++cur->count;
00916       }
00917    }
00918    ast_mutex_unlock(&reglock);
00919 
00920    /* Dump the whole list */
00921    for (cur = list; cur; cur = cur->next) {
00922       len += cur->len;
00923       cache_len += cur->cache_len;
00924       count += cur->count;
00925       if (cur->cache_len) {
00926          if (fn) {
00927             ast_cli(a->fd, "%10u bytes (%10u cache) in %10u allocations by %20s() line %5u of %s\n",
00928                cur->len, cur->cache_len, cur->count, cur->name, cur->lineno, fn);
00929          } else {
00930             ast_cli(a->fd, "%10u bytes (%10u cache) in %10u allocations in file %s\n",
00931                cur->len, cur->cache_len, cur->count, cur->name);
00932          }
00933       } else {
00934          if (fn) {
00935             ast_cli(a->fd, "%10u bytes in %10u allocations by %20s() line %5u of %s\n",
00936                cur->len, cur->count, cur->name, cur->lineno, fn);
00937          } else {
00938             ast_cli(a->fd, "%10u bytes in %10u allocations in file %s\n",
00939                cur->len, cur->count, cur->name);
00940          }
00941       }
00942    }
00943 
00944    if (cache_len) {
00945       ast_cli(a->fd, "%u bytes allocated (%u in caches) in %u allocations\n",
00946          len, cache_len, count);
00947    } else {
00948       ast_cli(a->fd, "%u bytes allocated in %u allocations\n", len, count);
00949    }
00950 
00951    return CLI_SUCCESS;
00952 }

static void mm_atexit_ast ( void   )  [static]

Definition at line 1404 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 1030 of file astmm.c.

References ast_region::data, ast_region::file, ast_region::len, and ast_region::lineno.

Referenced by mm_atexit_list_merge().

01031 {
01032    int cmp;
01033    ptrdiff_t cmp_ptr;
01034    ssize_t cmp_size;
01035 
01036    /* Sort by filename. */
01037    cmp = strcmp(left->file, right->file);
01038    if (cmp) {
01039       return cmp;
01040    }
01041 
01042    /* Sort by line number. */
01043    cmp = left->lineno - right->lineno;
01044    if (cmp) {
01045       return cmp;
01046    }
01047 
01048    /* Sort by allocated size. */
01049    cmp_size = left->len - right->len;
01050    if (cmp_size) {
01051       if (cmp_size < 0) {
01052          return -1;
01053       }
01054       return 1;
01055    }
01056 
01057    /* Sort by allocated pointers just because. */
01058    cmp_ptr = left->data - right->data;
01059    if (cmp_ptr) {
01060       if (cmp_ptr < 0) {
01061          return -1;
01062       }
01063       return 1;
01064    }
01065 
01066    return 0;
01067 }

static void mm_atexit_dump ( void   )  [static]

Definition at line 1322 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().

01323 {
01324    struct region_list alloced_atexit = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
01325    size_t length;
01326 
01327    length = mm_atexit_hash_list(&alloced_atexit);
01328    if (!length) {
01329       /* Wow!  This is amazing! */
01330       astmm_log("Exiting with all memory freed.\n");
01331       return;
01332    }
01333 
01334    mm_atexit_list_sort(&alloced_atexit, length);
01335 
01336    astmm_log("Exiting with the following memory not freed:\n");
01337    if (atexit_list) {
01338       mm_atexit_regions_list(&alloced_atexit);
01339    }
01340    if (atexit_summary) {
01341       mm_atexit_regions_summary(&alloced_atexit);
01342    }
01343 
01344    /*
01345     * Put the alloced list back into regions[].
01346     *
01347     * We have do do this because we can get called before all other
01348     * threads have terminated.
01349     */
01350    mm_atexit_hash_restore(&alloced_atexit);
01351 }

static void mm_atexit_final ( void   )  [static]

Definition at line 1357 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().

01358 {
01359    FILE *log;
01360 
01361    /* Only wait if we want atexit allocation dumps. */
01362    if (atexit_list || atexit_summary) {
01363       fprintf(stderr, "Waiting 10 seconds to let other threads die.\n");
01364       sleep(10);
01365    }
01366 
01367    regions_check_all_fences();
01368 
01369    /* Flush all delayed memory free circular arrays. */
01370    freed_regions_flush(&whales);
01371    freed_regions_flush(&minnows);
01372 
01373    /* Peform atexit allocation dumps. */
01374    if (atexit_list || atexit_summary) {
01375       ast_mutex_lock(&reglock);
01376       mm_atexit_dump();
01377       ast_mutex_unlock(&reglock);
01378    }
01379 
01380    /* Close the log file. */
01381    log = mmlog;
01382    mmlog = NULL;
01383    if (log) {
01384       fclose(log);
01385    }
01386 }

static size_t mm_atexit_hash_list ( struct region_list list  )  [static]

Definition at line 979 of file astmm.c.

References ARRAY_LEN, AST_LIST_INSERT_HEAD, AST_LIST_NEXT, and regions.

Referenced by mm_atexit_dump().

00980 {
00981    struct ast_region *reg;
00982    size_t total_length;
00983    int idx;
00984 
00985    total_length = 0;
00986    for (idx = 0; idx < ARRAY_LEN(regions); ++idx) {
00987       while ((reg = regions[idx])) {
00988          regions[idx] = AST_LIST_NEXT(reg, node);
00989          AST_LIST_NEXT(reg, node) = NULL;
00990          AST_LIST_INSERT_HEAD(list, reg, node);
00991          ++total_length;
00992       }
00993    }
00994    return total_length;
00995 }

static void mm_atexit_hash_restore ( struct region_list list  )  [static]

Definition at line 1007 of file astmm.c.

References AST_LIST_NEXT, AST_LIST_REMOVE_HEAD, ast_region::data, HASH, and regions.

Referenced by mm_atexit_dump().

01008 {
01009    struct ast_region *reg;
01010    int hash;
01011 
01012    while ((reg = AST_LIST_REMOVE_HEAD(list, node))) {
01013       hash = HASH(reg->data);
01014       AST_LIST_NEXT(reg, node) = regions[hash];
01015       regions[hash] = reg;
01016    }
01017 }

static void mm_atexit_list_merge ( struct region_list list,
struct region_list sub1,
struct region_list sub2 
) [static]

Definition at line 1079 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().

01080 {
01081    struct ast_region *reg;
01082 
01083    for (;;) {
01084       if (AST_LIST_EMPTY(sub1)) {
01085          /* The remaining sublist goes onto the list. */
01086          AST_LIST_APPEND_LIST(list, sub2, node);
01087          break;
01088       }
01089       if (AST_LIST_EMPTY(sub2)) {
01090          /* The remaining sublist goes onto the list. */
01091          AST_LIST_APPEND_LIST(list, sub1, node);
01092          break;
01093       }
01094 
01095       if (mm_atexit_cmp(AST_LIST_FIRST(sub1), AST_LIST_FIRST(sub2)) <= 0) {
01096          reg = AST_LIST_REMOVE_HEAD(sub1, node);
01097       } else {
01098          reg = AST_LIST_REMOVE_HEAD(sub2, node);
01099       }
01100       AST_LIST_INSERT_TAIL(list, reg, node);
01101    }
01102 }

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

01151 {
01152    /*! Semi-sorted merged list. */
01153    struct region_list merged = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
01154    /*! Sublists to merge. (Can only merge two sublists at this time.) */
01155    struct region_list sub[2] = {
01156       AST_LIST_HEAD_NOLOCK_INIT_VALUE,
01157       AST_LIST_HEAD_NOLOCK_INIT_VALUE
01158    };
01159    /*! Sublist size. */
01160    size_t size = 1;
01161    /*! Remaining elements in the list. */
01162    size_t remaining;
01163    /*! Number of sublist merge passes to process the list. */
01164    int passes;
01165 
01166    for (;;) {
01167       remaining = length;
01168 
01169       passes = 0;
01170       while (!AST_LIST_EMPTY(list)) {
01171          mm_atexit_list_split(list, sub, ARRAY_LEN(sub), size, &remaining);
01172          mm_atexit_list_merge(&merged, &sub[0], &sub[1]);
01173          ++passes;
01174       }
01175       AST_LIST_APPEND_LIST(list, &merged, node);
01176       if (passes <= 1) {
01177          /* The list is now sorted. */
01178          break;
01179       }
01180 
01181       /* Double the sublist size to remove for next round. */
01182       size <<= 1;
01183    }
01184 }

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 1116 of file astmm.c.

References AST_LIST_APPEND_LIST, AST_LIST_INSERT_TAIL, and AST_LIST_REMOVE_HEAD.

Referenced by mm_atexit_list_sort().

01117 {
01118    int idx;
01119 
01120    for (idx = 0; idx < num_lists; ++idx) {
01121       size_t count;
01122 
01123       if (*remaining < size) {
01124          /* The remaining source list goes onto the sublist. */
01125          AST_LIST_APPEND_LIST(&sub[idx], list, node);
01126          *remaining = 0;
01127          break;
01128       }
01129 
01130       /* Take a sublist off the beginning of the source list. */
01131       *remaining -= size;
01132       for (count = size; count--;) {
01133          struct ast_region *reg;
01134 
01135          reg = AST_LIST_REMOVE_HEAD(list, node);
01136          AST_LIST_INSERT_TAIL(&sub[idx], reg, node);
01137       }
01138    }
01139 }

static void mm_atexit_regions_list ( struct region_list alloced  )  [static]

Definition at line 1194 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().

01195 {
01196    struct ast_region *reg;
01197 
01198    AST_LIST_TRAVERSE(alloced, reg, node) {
01199       astmm_log("%s %s() line %u: %u bytes%s at %p\n",
01200          reg->file, reg->func, reg->lineno,
01201          (unsigned int) reg->len, reg->cache ? " (cache)" : "", reg->data);
01202    }
01203 }

static void mm_atexit_regions_summary ( struct region_list alloced  )  [static]

Definition at line 1213 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().

01214 {
01215    struct ast_region *reg;
01216    struct ast_region *next;
01217    struct {
01218       unsigned int count;
01219       unsigned int len;
01220       unsigned int cache_len;
01221    } by_line, by_func, by_file, total;
01222 
01223    by_line.count = 0;
01224    by_line.len = 0;
01225    by_line.cache_len = 0;
01226 
01227    by_func.count = 0;
01228    by_func.len = 0;
01229    by_func.cache_len = 0;
01230 
01231    by_file.count = 0;
01232    by_file.len = 0;
01233    by_file.cache_len = 0;
01234 
01235    total.count = 0;
01236    total.len = 0;
01237    total.cache_len = 0;
01238 
01239    AST_LIST_TRAVERSE(alloced, reg, node) {
01240       next = AST_LIST_NEXT(reg, node);
01241 
01242       ++by_line.count;
01243       by_line.len += reg->len;
01244       if (reg->cache) {
01245          by_line.cache_len += reg->len;
01246       }
01247       if (next && !strcmp(reg->file, next->file) && reg->lineno == next->lineno) {
01248          continue;
01249       }
01250       if (atexit_summary & SUMMARY_BY_LINE) {
01251          if (by_line.cache_len) {
01252             astmm_log("%10u bytes (%u in caches) in %u allocations. %s %s() line %u\n",
01253                by_line.len, by_line.cache_len, by_line.count, reg->file, reg->func, reg->lineno);
01254          } else {
01255             astmm_log("%10u bytes in %5u allocations. %s %s() line %u\n",
01256                by_line.len, by_line.count, reg->file, reg->func, reg->lineno);
01257          }
01258       }
01259 
01260       by_func.count += by_line.count;
01261       by_func.len += by_line.len;
01262       by_func.cache_len += by_line.cache_len;
01263       by_line.count = 0;
01264       by_line.len = 0;
01265       by_line.cache_len = 0;
01266       if (next && !strcmp(reg->file, next->file) && !strcmp(reg->func, next->func)) {
01267          continue;
01268       }
01269       if (atexit_summary & SUMMARY_BY_FUNC) {
01270          if (by_func.cache_len) {
01271             astmm_log("%10u bytes (%u in caches) in %u allocations. %s %s()\n",
01272                by_func.len, by_func.cache_len, by_func.count, reg->file, reg->func);
01273          } else {
01274             astmm_log("%10u bytes in %5u allocations. %s %s()\n",
01275                by_func.len, by_func.count, reg->file, reg->func);
01276          }
01277       }
01278 
01279       by_file.count += by_func.count;
01280       by_file.len += by_func.len;
01281       by_file.cache_len += by_func.cache_len;
01282       by_func.count = 0;
01283       by_func.len = 0;
01284       by_func.cache_len = 0;
01285       if (next && !strcmp(reg->file, next->file)) {
01286          continue;
01287       }
01288       if (atexit_summary & SUMMARY_BY_FILE) {
01289          if (by_file.cache_len) {
01290             astmm_log("%10u bytes (%u in caches) in %u allocations. %s\n",
01291                by_file.len, by_file.cache_len, by_file.count, reg->file);
01292          } else {
01293             astmm_log("%10u bytes in %5u allocations. %s\n",
01294                by_file.len, by_file.count, reg->file);
01295          }
01296       }
01297 
01298       total.count += by_file.count;
01299       total.len += by_file.len;
01300       total.cache_len += by_file.cache_len;
01301       by_file.count = 0;
01302       by_file.len = 0;
01303       by_file.cache_len = 0;
01304    }
01305 
01306    if (total.cache_len) {
01307       astmm_log("%u bytes (%u in caches) in %u allocations.\n",
01308          total.len, total.cache_len, total.count);
01309    } else {
01310       astmm_log("%u bytes in %u allocations.\n", total.len, total.count);
01311    }
01312 }

static void my_do_crash ( void   )  [static]

Definition at line 192 of file astmm.c.

References ast_do_crash().

Referenced by __ast_free_region(), __ast_realloc(), region_check_fences(), and region_data_check().

00193 {
00194    /*
00195     * Give the logger a chance to get the message out, just in case
00196     * we abort(), or Asterisk crashes due to whatever problem just
00197     * happened.
00198     */
00199    usleep(1);
00200    ast_do_crash();
00201 }

static void region_check_fences ( struct ast_region reg  )  [static]

Definition at line 395 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().

00396 {
00397    unsigned int *fence;
00398 
00399    /*
00400     * We use the bytes just preceeding reg->data and not reg->fence
00401     * because there is likely to be padding between reg->fence and
00402     * reg->data for reg->data alignment.
00403     */
00404    fence = (unsigned int *) (reg->data - sizeof(*fence));
00405    if (*fence != FENCE_MAGIC) {
00406       astmm_log("WARNING: Low fence violation of %p allocated at %s %s() line %d\n",
00407          reg->data, reg->file, reg->func, reg->lineno);
00408       my_do_crash();
00409    }
00410    fence = (unsigned int *) (reg->data + reg->len);
00411    if (get_unaligned_uint32(fence) != FENCE_MAGIC) {
00412       astmm_log("WARNING: High fence violation of %p allocated at %s %s() line %d\n",
00413          reg->data, reg->file, reg->func, reg->lineno);
00414       my_do_crash();
00415    }
00416 }

static void region_data_check ( struct ast_region reg  )  [static]

Definition at line 276 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().

00277 {
00278    void *end;
00279    unsigned int *pos;
00280 
00281    /*
00282     * Check the lower fence, the payload, and whatever amount of
00283     * the higher fence that falls into alignment with the payload.
00284     */
00285    end = reg->data + reg->len;
00286    for (pos = &reg->fence; (void *) pos <= end; ++pos) {
00287       if (*pos != FREED_MAGIC) {
00288          astmm_log("WARNING: Memory corrupted after free of %p allocated at %s %s() line %d\n",
00289             reg->data, reg->file, reg->func, reg->lineno);
00290          my_do_crash();
00291          break;
00292       }
00293    }
00294 }

static void region_data_wipe ( struct ast_region reg  )  [static]

Definition at line 253 of file astmm.c.

References ast_region::data, ast_region::fence, FREED_MAGIC, and ast_region::len.

Referenced by region_free().

00254 {
00255    void *end;
00256    unsigned int *pos;
00257 
00258    /*
00259     * Wipe the lower fence, the payload, and whatever amount of the
00260     * higher fence that falls into alignment with the payload.
00261     */
00262    end = reg->data + reg->len;
00263    for (pos = &reg->fence; (void *) pos <= end; ++pos) {
00264       *pos = FREED_MAGIC;
00265    }
00266 }

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

Definition at line 512 of file astmm.c.

References AST_LIST_NEXT, ast_region::data, HASH, and regions.

Referenced by __ast_realloc().

00513 {
00514    int hash;
00515    struct ast_region *reg;
00516 
00517    hash = HASH(ptr);
00518    for (reg = regions[hash]; reg; reg = AST_LIST_NEXT(reg, node)) {
00519       if (reg->data == ptr) {
00520          break;
00521       }
00522    }
00523 
00524    return reg;
00525 }

static void region_free ( struct ast_freed_regions freed,
struct ast_region reg 
) [static]

Definition at line 331 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().

00332 {
00333    struct ast_region *old;
00334 
00335    region_data_wipe(reg);
00336 
00337    ast_mutex_lock(&reglock);
00338    old = freed->regions[freed->index];
00339    freed->regions[freed->index] = reg;
00340 
00341    ++freed->index;
00342    if (ARRAY_LEN(freed->regions) <= freed->index) {
00343       freed->index = 0;
00344    }
00345    ast_mutex_unlock(&reglock);
00346 
00347    if (old) {
00348       region_data_check(old);
00349       free(old);
00350    }
00351 }

static struct ast_region* region_remove ( void *  ptr  )  [static, read]

Definition at line 362 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().

00363 {
00364    int hash;
00365    struct ast_region *reg;
00366    struct ast_region *prev = NULL;
00367 
00368    hash = HASH(ptr);
00369 
00370    ast_mutex_lock(&reglock);
00371    for (reg = regions[hash]; reg; reg = AST_LIST_NEXT(reg, node)) {
00372       if (reg->data == ptr) {
00373          if (prev) {
00374             AST_LIST_NEXT(prev, node) = AST_LIST_NEXT(reg, node);
00375          } else {
00376             regions[hash] = AST_LIST_NEXT(reg, node);
00377          }
00378          break;
00379       }
00380       prev = reg;
00381    }
00382    ast_mutex_unlock(&reglock);
00383 
00384    return reg;
00385 }

static void regions_check_all_fences ( void   )  [static]

Definition at line 424 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().

00425 {
00426    int idx;
00427    struct ast_region *reg;
00428 
00429    ast_mutex_lock(&reglock);
00430    for (idx = 0; idx < ARRAY_LEN(regions); ++idx) {
00431       for (reg = regions[idx]; reg; reg = AST_LIST_NEXT(reg, node)) {
00432          region_check_fences(reg);
00433       }
00434    }
00435    ast_mutex_unlock(&reglock);
00436 }


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 954 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 31 Aug 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1