Fri Nov 12 11:53:20 2010

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"
Include dependency graph for astmm.c:

Go to the source code of this file.

Data Structures

struct  ast_region

Defines

#define astmm_log(...)
#define FENCE_MAGIC   0xdeadbeef
#define HASH(a)   (((unsigned long)(a)) % SOME_PRIME)
#define SOME_PRIME   563

Enumerations

enum  func_type {
  FUNC_CALLOC = 1, FUNC_MALLOC, FUNC_REALLOC, FUNC_STRDUP,
  FUNC_STRNDUP, FUNC_VASPRINTF, FUNC_ASPRINTF
}

Functions

static void * __ast_alloc_region (size_t size, const enum func_type which, const char *file, int lineno, const char *func, unsigned int cache)
int __ast_asprintf (const char *file, int lineno, const char *func, char **strp, const char *fmt,...)
void * __ast_calloc (size_t nmemb, size_t size, const char *file, int lineno, const char *func)
void * __ast_calloc_cache (size_t nmemb, size_t size, const char *file, int lineno, const char *func)
void __ast_free (void *ptr, const char *file, int lineno, const char *func)
static void __ast_free_region (void *ptr, const char *file, int lineno, const char *func)
void * __ast_malloc (size_t size, const char *file, int lineno, const char *func)
void __ast_mm_init (void)
void * __ast_realloc (void *ptr, size_t size, const char *file, int lineno, const char *func)
static size_t __ast_sizeof_region (void *ptr)
char * __ast_strdup (const char *s, const char *file, int lineno, const char *func)
char * __ast_strndup (const char *s, size_t n, const char *file, int lineno, const char *func)
int __ast_vasprintf (char **strp, const char *fmt, va_list ap, const char *file, int lineno, const char *func)
static char * handle_memory_show (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_memory_show_summary (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)

Variables

static struct ast_cli_entry cli_memory []
static FILE * mmlog
static struct ast_regionregions [SOME_PRIME]
static ast_mutex_t reglock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )

Detailed Description

Memory Management.

Author:
Mark Spencer <markster@digium.com>

Definition in file astmm.c.


Define Documentation

#define astmm_log ( ...   ) 

Definition at line 98 of file astmm.c.

Referenced by __ast_alloc_region(), __ast_free_region(), __ast_realloc(), and handle_memory_show().

#define FENCE_MAGIC   0xdeadbeef

Definition at line 63 of file astmm.c.

Referenced by __ast_alloc_region(), __ast_free_region(), and handle_memory_show().

#define HASH (  )     (((unsigned long)(a)) % SOME_PRIME)

Definition at line 91 of file astmm.c.

Referenced by __ast_alloc_region(), __ast_free_region(), and __ast_sizeof_region().

#define SOME_PRIME   563

Definition at line 41 of file astmm.c.

Referenced by handle_memory_show(), and handle_memory_show_summary().


Enumeration Type Documentation

enum func_type
Enumerator:
FUNC_CALLOC 
FUNC_MALLOC 
FUNC_REALLOC 
FUNC_STRDUP 
FUNC_STRNDUP 
FUNC_VASPRINTF 
FUNC_ASPRINTF 

Definition at line 43 of file astmm.c.

00043                {
00044    FUNC_CALLOC = 1,
00045    FUNC_MALLOC,
00046    FUNC_REALLOC,
00047    FUNC_STRDUP,
00048    FUNC_STRNDUP,
00049    FUNC_VASPRINTF,
00050    FUNC_ASPRINTF
00051 };


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 
) [inline, static]

Definition at line 107 of file astmm.c.

References ast_copy_string(), ast_mutex_lock(), ast_mutex_unlock(), astmm_log, ast_region::cache, ast_region::data, ast_region::fence, FENCE_MAGIC, ast_region::file, ast_region::func, HASH, ast_region::len, ast_region::lineno, malloc, ast_region::next, put_unaligned_uint32(), regions, reglock, and ast_region::which.

Referenced by __ast_asprintf(), __ast_calloc(), __ast_calloc_cache(), __ast_malloc(), __ast_realloc(), __ast_strdup(), __ast_strndup(), and __ast_vasprintf().

00108 {
00109    struct ast_region *reg;
00110    void *ptr = NULL;
00111    unsigned int *fence;
00112    int hash;
00113 
00114    if (!(reg = malloc(size + sizeof(*reg) + sizeof(*fence)))) {
00115       astmm_log("Memory Allocation Failure - '%d' bytes in function %s "
00116            "at line %d of %s\n", (int) size, func, lineno, file);
00117       return NULL;
00118    }
00119 
00120    ast_copy_string(reg->file, file, sizeof(reg->file));
00121    ast_copy_string(reg->func, func, sizeof(reg->func));
00122    reg->lineno = lineno;
00123    reg->len = size;
00124    reg->which = which;
00125    reg->cache = cache;
00126    ptr = reg->data;
00127    hash = HASH(ptr);
00128    reg->fence = FENCE_MAGIC;
00129    fence = (ptr + reg->len);
00130    put_unaligned_uint32(fence, FENCE_MAGIC);
00131 
00132    ast_mutex_lock(&reglock);
00133    reg->next = regions[hash];
00134    regions[hash] = reg;
00135    ast_mutex_unlock(&reglock);
00136 
00137    return ptr;
00138 }

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

Definition at line 285 of file astmm.c.

References __ast_alloc_region(), FUNC_ASPRINTF, and s.

00286 {
00287    int size;
00288    va_list ap, ap2;
00289    char s;
00290 
00291    *strp = NULL;
00292    va_start(ap, fmt);
00293    va_copy(ap2, ap);
00294    size = vsnprintf(&s, 1, fmt, ap2);
00295    va_end(ap2);
00296    if (!(*strp = __ast_alloc_region(size + 1, FUNC_ASPRINTF, file, lineno, func, 0))) {
00297       va_end(ap);
00298       return -1;
00299    }
00300    vsnprintf(*strp, size + 1, fmt, ap);
00301    va_end(ap);
00302 
00303    return size;
00304 }

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

Definition at line 209 of file astmm.c.

References __ast_alloc_region(), and FUNC_CALLOC.

00210 {
00211    void *ptr;
00212 
00213    if ((ptr = __ast_alloc_region(size * nmemb, FUNC_CALLOC, file, lineno, func, 1))) 
00214       memset(ptr, 0, size * nmemb);
00215 
00216    return ptr;
00217 }

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

Definition at line 224 of file astmm.c.

References __ast_free_region().

00225 {
00226    __ast_free_region(ptr, file, lineno, func);
00227 }

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

Definition at line 158 of file astmm.c.

References ast_mutex_lock(), ast_mutex_unlock(), astmm_log, ast_region::data, ast_region::fence, FENCE_MAGIC, ast_region::file, free, ast_region::func, get_unaligned_uint32(), HASH, ast_region::len, ast_region::lineno, ast_region::next, regions, and reglock.

Referenced by __ast_free(), and __ast_realloc().

00159 {
00160    int hash;
00161    struct ast_region *reg, *prev = NULL;
00162    unsigned int *fence;
00163 
00164    if (!ptr)
00165       return;
00166 
00167    hash = HASH(ptr);
00168 
00169    ast_mutex_lock(&reglock);
00170    for (reg = regions[hash]; reg; reg = reg->next) {
00171       if (reg->data == ptr) {
00172          if (prev)
00173             prev->next = reg->next;
00174          else
00175             regions[hash] = reg->next;
00176          break;
00177       }
00178       prev = reg;
00179    }
00180    ast_mutex_unlock(&reglock);
00181 
00182    if (reg) {
00183       fence = (unsigned int *)(reg->data + reg->len);
00184       if (reg->fence != FENCE_MAGIC) {
00185          astmm_log("WARNING: Low fence violation at %p, in %s of %s, "
00186             "line %d\n", reg->data, reg->func, reg->file, reg->lineno);
00187       }
00188       if (get_unaligned_uint32(fence) != FENCE_MAGIC) {
00189          astmm_log("WARNING: High fence violation at %p, in %s of %s, "
00190             "line %d\n", reg->data, reg->func, reg->file, reg->lineno);
00191       }
00192       free(reg);
00193    } else {
00194       astmm_log("WARNING: Freeing unused memory at %p, in %s of %s, line %d\n",  
00195          ptr, func, file, lineno);
00196    }
00197 }

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

Definition at line 219 of file astmm.c.

References __ast_alloc_region(), and FUNC_MALLOC.

00220 {
00221    return __ast_alloc_region(size, FUNC_MALLOC, file, lineno, func, 0);
00222 }

void __ast_mm_init ( void   ) 

Definition at line 481 of file astmm.c.

References ARRAY_LEN, ast_cli_register_multiple(), ast_config_AST_LOG_DIR, ast_log(), ast_verb, and LOG_ERROR.

Referenced by main().

00482 {
00483    char filename[PATH_MAX];
00484    size_t pad = sizeof(struct ast_region) - offsetof(struct ast_region, data);
00485 
00486    if (pad) {
00487       ast_log(LOG_ERROR, "struct ast_region has %d bytes of padding! This must be eliminated for low-fence checking to work properly!\n", (int) pad);
00488    }
00489 
00490    ast_cli_register_multiple(cli_memory, ARRAY_LEN(cli_memory));
00491    
00492    snprintf(filename, sizeof(filename), "%s/mmlog", ast_config_AST_LOG_DIR);
00493    
00494    ast_verb(1, "Asterisk Malloc Debugger Started (see %s))\n", filename);
00495    
00496    if ((mmlog = fopen(filename, "a+"))) {
00497       fprintf(mmlog, "%ld - New session\n", (long)time(NULL));
00498       fflush(mmlog);
00499    }
00500 }

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

Definition at line 229 of file astmm.c.

References __ast_alloc_region(), __ast_free_region(), __ast_sizeof_region(), astmm_log, FUNC_REALLOC, and len().

Referenced by grow_heap().

00230 {
00231    void *tmp;
00232    size_t len = 0;
00233 
00234    if (ptr && !(len = __ast_sizeof_region(ptr))) {
00235       astmm_log("WARNING: Realloc of unalloced memory at %p, in %s of %s, "
00236          "line %d\n", ptr, func, file, lineno);
00237       return NULL;
00238    }
00239 
00240    if (!(tmp = __ast_alloc_region(size, FUNC_REALLOC, file, lineno, func, 0)))
00241       return NULL;
00242 
00243    if (len > size)
00244       len = size;
00245    if (ptr) {
00246       memcpy(tmp, ptr, len);
00247       __ast_free_region(ptr, file, lineno, func);
00248    }
00249    
00250    return tmp;
00251 }

static size_t __ast_sizeof_region ( void *  ptr  )  [inline, static]

Definition at line 140 of file astmm.c.

References ast_mutex_lock(), ast_mutex_unlock(), ast_region::data, HASH, ast_region::len, len(), ast_region::next, regions, and reglock.

Referenced by __ast_realloc().

00141 {
00142    int hash = HASH(ptr);
00143    struct ast_region *reg;
00144    size_t len = 0;
00145    
00146    ast_mutex_lock(&reglock);
00147    for (reg = regions[hash]; reg; reg = reg->next) {
00148       if (reg->data == ptr) {
00149          len = reg->len;
00150          break;
00151       }
00152    }
00153    ast_mutex_unlock(&reglock);
00154 
00155    return len;
00156 }

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

Definition at line 253 of file astmm.c.

References __ast_alloc_region(), FUNC_STRDUP, and len().

00254 {
00255    size_t len;
00256    void *ptr;
00257 
00258    if (!s)
00259       return NULL;
00260 
00261    len = strlen(s) + 1;
00262    if ((ptr = __ast_alloc_region(len, FUNC_STRDUP, file, lineno, func, 0)))
00263       strcpy(ptr, s);
00264 
00265    return ptr;
00266 }

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

Definition at line 268 of file astmm.c.

References __ast_alloc_region(), FUNC_STRNDUP, and len().

00269 {
00270    size_t len;
00271    void *ptr;
00272 
00273    if (!s)
00274       return NULL;
00275 
00276    len = strlen(s) + 1;
00277    if (len > n)
00278       len = n;
00279    if ((ptr = __ast_alloc_region(len, FUNC_STRNDUP, file, lineno, func, 0)))
00280       strcpy(ptr, s);
00281 
00282    return ptr;
00283 }

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

Definition at line 306 of file astmm.c.

References __ast_alloc_region(), FUNC_VASPRINTF, and s.

00307 {
00308    int size;
00309    va_list ap2;
00310    char s;
00311 
00312    *strp = NULL;
00313    va_copy(ap2, ap);
00314    size = vsnprintf(&s, 1, fmt, ap2);
00315    va_end(ap2);
00316    if (!(*strp = __ast_alloc_region(size + 1, FUNC_VASPRINTF, file, lineno, func, 0))) {
00317       va_end(ap);
00318       return -1;
00319    }
00320    vsnprintf(*strp, size + 1, fmt, ap);
00321 
00322    return size;
00323 }

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

Definition at line 325 of file astmm.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), astmm_log, ast_region::cache, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_region::data, ast_cli_args::fd, ast_region::fence, FENCE_MAGIC, ast_region::file, ast_region::func, get_unaligned_uint32(), ast_region::len, len(), ast_region::lineno, ast_region::next, regions, reglock, SOME_PRIME, and ast_cli_entry::usage.

00326 {
00327    char *fn = NULL;
00328    struct ast_region *reg;
00329    unsigned int x;
00330    unsigned int len = 0;
00331    unsigned int cache_len = 0;
00332    unsigned int count = 0;
00333    unsigned int *fence;
00334 
00335    switch (cmd) {
00336    case CLI_INIT:
00337       e->command = "memory show allocations";
00338       e->usage =
00339          "Usage: memory show allocations [<file>]\n"
00340          "       Dumps a list of all segments of allocated memory, optionally\n"
00341          "       limited to those from a specific file\n";
00342       return NULL;
00343    case CLI_GENERATE:
00344       return NULL;
00345    }
00346 
00347 
00348    if (a->argc > 3)
00349       fn = a->argv[3];
00350 
00351    ast_mutex_lock(&reglock);
00352    for (x = 0; x < SOME_PRIME; x++) {
00353       for (reg = regions[x]; reg; reg = reg->next) {
00354          if (!fn || !strcasecmp(fn, reg->file) || !strcasecmp(fn, "anomolies")) {
00355             fence = (unsigned int *)(reg->data + reg->len);
00356             if (reg->fence != FENCE_MAGIC) {
00357                astmm_log("WARNING: Low fence violation at %p, "
00358                   "in %s of %s, line %d\n", reg->data, 
00359                   reg->func, reg->file, reg->lineno);
00360             }
00361             if (get_unaligned_uint32(fence) != FENCE_MAGIC) {
00362                astmm_log("WARNING: High fence violation at %p, in %s of %s, "
00363                   "line %d\n", reg->data, reg->func, reg->file, reg->lineno);
00364             }
00365          }
00366          if (!fn || !strcasecmp(fn, reg->file)) {
00367             ast_cli(a->fd, "%10d bytes allocated%s in %20s at line %5d of %s\n", 
00368                (int) reg->len, reg->cache ? " (cache)" : "", 
00369                reg->func, reg->lineno, reg->file);
00370             len += reg->len;
00371             if (reg->cache)
00372                cache_len += reg->len;
00373             count++;
00374          }
00375       }
00376    }
00377    ast_mutex_unlock(&reglock);
00378    
00379    if (cache_len)
00380       ast_cli(a->fd, "%d bytes allocated (%d in caches) in %d allocations\n", len, cache_len, count);
00381    else
00382       ast_cli(a->fd, "%d bytes allocated in %d allocations\n", len, count);
00383    
00384    return CLI_SUCCESS;
00385 }

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

Definition at line 387 of file astmm.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_copy_string(), ast_mutex_lock(), ast_mutex_unlock(), ast_region::cache, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_region::file, ast_region::func, ast_region::len, len(), ast_region::next, regions, reglock, SOME_PRIME, and ast_cli_entry::usage.

00388 {
00389    char *fn = NULL;
00390    int x;
00391    struct ast_region *reg;
00392    unsigned int len = 0;
00393    unsigned int cache_len = 0;
00394    int count = 0;
00395    struct file_summary {
00396       char fn[80];
00397       int len;
00398       int cache_len;
00399       int count;
00400       struct file_summary *next;
00401    } *list = NULL, *cur;
00402    
00403    switch (cmd) {
00404    case CLI_INIT:
00405       e->command = "memory show summary";
00406       e->usage =
00407          "Usage: memory show summary [<file>]\n"
00408          "       Summarizes heap memory allocations by file, or optionally\n"
00409          "by function, if a file is specified\n";
00410       return NULL;
00411    case CLI_GENERATE:
00412       return NULL;
00413    }
00414 
00415    if (a->argc > 3) 
00416       fn = a->argv[3];
00417 
00418    ast_mutex_lock(&reglock);
00419    for (x = 0; x < SOME_PRIME; x++) {
00420       for (reg = regions[x]; reg; reg = reg->next) {
00421          if (fn && strcasecmp(fn, reg->file))
00422             continue;
00423 
00424          for (cur = list; cur; cur = cur->next) {
00425             if ((!fn && !strcmp(cur->fn, reg->file)) || (fn && !strcmp(cur->fn, reg->func)))
00426                break;
00427          }
00428          if (!cur) {
00429             cur = alloca(sizeof(*cur));
00430             memset(cur, 0, sizeof(*cur));
00431             ast_copy_string(cur->fn, fn ? reg->func : reg->file, sizeof(cur->fn));
00432             cur->next = list;
00433             list = cur;
00434          }
00435 
00436          cur->len += reg->len;
00437          if (reg->cache)
00438             cur->cache_len += reg->len;
00439          cur->count++;
00440       }
00441    }
00442    ast_mutex_unlock(&reglock);
00443    
00444    /* Dump the whole list */
00445    for (cur = list; cur; cur = cur->next) {
00446       len += cur->len;
00447       cache_len += cur->cache_len;
00448       count += cur->count;
00449       if (cur->cache_len) {
00450          if (fn) {
00451             ast_cli(a->fd, "%10d bytes (%10d cache) in %d allocations in function '%s' of '%s'\n", 
00452                cur->len, cur->cache_len, cur->count, cur->fn, fn);
00453          } else {
00454             ast_cli(a->fd, "%10d bytes (%10d cache) in %d allocations in file '%s'\n", 
00455                cur->len, cur->cache_len, cur->count, cur->fn);
00456          }
00457       } else {
00458          if (fn) {
00459             ast_cli(a->fd, "%10d bytes in %d allocations in function '%s' of '%s'\n", 
00460                cur->len, cur->count, cur->fn, fn);
00461          } else {
00462             ast_cli(a->fd, "%10d bytes in %d allocations in file '%s'\n", 
00463                cur->len, cur->count, cur->fn);
00464          }
00465       }
00466    }
00467 
00468    if (cache_len)
00469       ast_cli(a->fd, "%d bytes allocated (%d in caches) in %d allocations\n", len, cache_len, count);
00470    else
00471       ast_cli(a->fd, "%d bytes allocated in %d allocations\n", len, count);
00472 
00473    return CLI_SUCCESS;
00474 }


Variable Documentation

struct ast_cli_entry cli_memory[] [static]
Initial value:
 {
   AST_CLI_DEFINE(handle_memory_show, "Display outstanding memory allocations"),
   AST_CLI_DEFINE(handle_memory_show_summary, "Summarize outstanding memory allocations"),
}

Definition at line 476 of file astmm.c.

FILE* mmlog [static]

Definition at line 65 of file astmm.c.

struct ast_region * regions[SOME_PRIME] [static]
ast_mutex_t reglock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static]

Tracking this mutex will cause infinite recursion, as the mutex tracking code allocates memory

Definition at line 96 of file astmm.c.

Referenced by __ast_alloc_region(), __ast_free_region(), __ast_sizeof_region(), handle_memory_show(), and handle_memory_show_summary().


Generated by  doxygen 1.6.2