don't double define our own string functions on platforms that don't have them (issue...
[asterisk/asterisk.git] / astmm.c
diff --git a/astmm.c b/astmm.c
index 94e4555..6087f7f 100755 (executable)
--- a/astmm.c
+++ b/astmm.c
@@ -1,36 +1,40 @@
 /*
  * Asterisk -- A telephony toolkit for Linux.
  *
- * Channel Variables
+ * Memory Management
  * 
- * Copyright (C) 2002, Mark Spencer
+ * Copyright (C) 2002-2005, Mark Spencer
  *
- * Mark Spencer <markster@linux-support.net>
+ * Mark Spencer <markster@digium.com>
  *
  * This program is free software, distributed under the terms of
  * the GNU General Public License
  */
 
-
-
 #ifdef __AST_DEBUG_MALLOC
 
-#include <malloc.h>
 #include <stdio.h>
 #include <string.h>
-#include <pthread.h>
 #include <time.h>
-#include <asterisk/cli.h>
-#include <asterisk/logger.h>
-#include <asterisk/options.h>
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/cli.h"
+#include "asterisk/logger.h"
+#include "asterisk/options.h"
+#include "asterisk/lock.h"
+#include "asterisk/strings.h"
 
 #define SOME_PRIME 563
 
-#define FUNC_CALLOC            1
-#define FUNC_MALLOC            2
+#define FUNC_CALLOC    1
+#define FUNC_MALLOC    2
 #define FUNC_REALLOC   3
-#define FUNC_STRDUP            4
+#define FUNC_STRDUP    4
 #define FUNC_STRNDUP   5
+#define FUNC_VASPRINTF 6
 
 /* Undefine all our macros */
 #undef malloc
@@ -39,6 +43,7 @@
 #undef strdup
 #undef strndup
 #undef free
+#undef vasprintf
 
 static FILE *mmlog;
 
@@ -55,19 +60,20 @@ static struct ast_region {
 #define HASH(a) \
        (((unsigned long)(a)) % SOME_PRIME)
        
-static pthread_mutex_t reglock = PTHREAD_MUTEX_INITIALIZER;
+AST_MUTEX_DEFINE_STATIC(reglock);
+AST_MUTEX_DEFINE_STATIC(showmemorylock);
 
 static inline void *__ast_alloc_region(size_t size, int which, const char *file, int lineno, const char *func)
 {
        struct ast_region *reg;
-       void *ptr=NULL;
+       void *ptr = NULL;
        int hash;
        reg = malloc(size + sizeof(struct ast_region));
-       pthread_mutex_lock(&reglock);
+       ast_mutex_lock(&reglock);
        if (reg) {
-               strncpy(reg->file, file, sizeof(reg->file) - 1);
+               ast_copy_string(reg->file, file, sizeof(reg->file));
                reg->file[sizeof(reg->file) - 1] = '\0';
-               strncpy(reg->func, func, sizeof(reg->func) - 1);
+               ast_copy_string(reg->func, func, sizeof(reg->func));
                reg->func[sizeof(reg->func) - 1] = '\0';
                reg->lineno = lineno;
                reg->len = size;
@@ -77,7 +83,7 @@ static inline void *__ast_alloc_region(size_t size, int which, const char *file,
                reg->next = regions[hash];
                regions[hash] = reg;
        }
-       pthread_mutex_unlock(&reglock);
+       ast_mutex_unlock(&reglock);
        if (!reg) {
                fprintf(stderr, "Out of memory :(\n");
                if (mmlog) {
@@ -94,16 +100,16 @@ static inline size_t __ast_sizeof_region(void *ptr)
        struct ast_region *reg;
        size_t len = 0;
        
-       pthread_mutex_lock(&reglock);
+       ast_mutex_lock(&reglock);
        reg = regions[hash];
-       while(reg) {
+       while (reg) {
                if (reg->data == ptr) {
                        len = reg->len;
                        break;
                }
                reg = reg->next;
        }
-       pthread_mutex_unlock(&reglock);
+       ast_mutex_unlock(&reglock);
        return len;
 }
 
@@ -111,29 +117,27 @@ static void __ast_free_region(void *ptr, const char *file, int lineno, const cha
 {
        int hash = HASH(ptr);
        struct ast_region *reg, *prev = NULL;
-       pthread_mutex_lock(&reglock);
+       ast_mutex_lock(&reglock);
        reg = regions[hash];
-       while(reg) {
+       while (reg) {
                if (reg->data == ptr) {
-                       if (prev)
+                       if (prev) {
                                prev->next = reg->next;
-                       else
+                       } else {
                                regions[hash] = reg->next;
-
+                       }
                        break;
                }
                prev = reg;
                reg = reg->next;
        }
-       pthread_mutex_unlock(&reglock);
+       ast_mutex_unlock(&reglock);
        if (reg) {
                free(reg);
        } else {
-               fprintf(stderr, "WARNING: Freeing unused memory at %p, in %s of %s, line %d\n",
-                       ptr, func, file, lineno);
+               fprintf(stderr, "WARNING: Freeing unused memory at %p, in %s of %s, line %d\n", ptr, func, file, lineno);
                if (mmlog) {
-                       fprintf(mmlog, "%ld - WARNING: Freeing unused memory at %p, in %s of %s, line %d\n", time(NULL),
-                       ptr, func, file, lineno);
+                       fprintf(mmlog, "%ld - WARNING: Freeing unused memory at %p, in %s of %s, line %d\n", time(NULL), ptr, func, file, lineno);
                        fflush(mmlog);
                }
        }
@@ -161,15 +165,13 @@ void __ast_free(void *ptr, const char *file, int lineno, const char *func)
 void *__ast_realloc(void *ptr, size_t size, const char *file, int lineno, const char *func) 
 {
        void *tmp;
-       size_t len=0;
+       size_t len = 0;
        if (ptr) {
                len = __ast_sizeof_region(ptr);
                if (!len) {
-                       fprintf(stderr, "WARNING: Realloc of unalloced memory at %p, in %s of %s, line %d\n",
-                               ptr, func, file, lineno);
+                       fprintf(stderr, "WARNING: Realloc of unalloced memory at %p, in %s of %s, line %d\n", ptr, func, file, lineno);
                        if (mmlog) {
-                               fprintf(mmlog, "%ld - WARNING: Realloc of unalloced memory at %p, in %s of %s, line %d\n",
-                                       time(NULL), ptr, func, file, lineno);
+                               fprintf(mmlog, "%ld - WARNING: Realloc of unalloced memory at %p, in %s of %s, line %d\n", time(NULL), ptr, func, file, lineno);
                                fflush(mmlog);
                        }
                        return NULL;
@@ -209,30 +211,49 @@ char *__ast_strndup(const char *s, size_t n, const char *file, int lineno, const
        len = strlen(s) + 1;
        if (len > n)
                len = n;
-       ptr = __ast_alloc_region(len, FUNC_STRDUP, file, lineno, func);
+       ptr = __ast_alloc_region(len, FUNC_STRNDUP, file, lineno, func);
        if (ptr)
                strcpy(ptr, s);
        return ptr;
 }
 
+int __ast_vasprintf(char **strp, const char *fmt, va_list ap, const char *file, int lineno, const char *func) 
+{
+       int n, size = strlen(fmt) + 1;
+       if ((*strp = __ast_alloc_region(size, FUNC_VASPRINTF, file, lineno, func)) == NULL)
+               return -1; 
+       for (;;) {
+               n = vsnprintf(*strp, size, fmt, ap);
+               if (n > -1 && n < size)
+                       return n;
+               if (n > -1) {   /* glibc 2.1 */
+                       size = n+1;
+               } else {        /* glibc 2.0 */
+                       size *= 2;
+               }
+               if ((*strp = __ast_realloc(*strp, size, file, lineno, func)) == NULL)
+                       return -1;
+       }
+}
+
 static int handle_show_memory(int fd, int argc, char *argv[])
 {
        char *fn = NULL;
        int x;
        struct ast_region *reg;
-       unsigned int len=0;
+       unsigned int len = 0;
        int count = 0;
-       if (argc >3) 
+       if (argc > 3) 
                fn = argv[3];
 
        /* try to lock applications list ... */
-       pthread_mutex_lock(&reglock);
+       ast_mutex_lock(&showmemorylock);
 
-       for (x=0;x<SOME_PRIME;x++) {
+       for (x = 0; x < SOME_PRIME; x++) {
                reg = regions[x];
-               while(reg) {
+               while (reg) {
                        if (!fn || !strcasecmp(fn, reg->file)) {
-                               ast_cli(fd, "%10d bytes allocated in %20s at line %5d of %s\n", reg->len, reg->func, reg->lineno, reg->file);
+                               ast_cli(fd, "%10d bytes allocated in %20s at line %5d of %s\n", (int) reg->len, reg->func, reg->lineno, reg->file);
                                len += reg->len;
                                count++;
                        }
@@ -240,7 +261,7 @@ static int handle_show_memory(int fd, int argc, char *argv[])
                }
        }
        ast_cli(fd, "%d bytes allocated %d units total\n", len, count);
-       pthread_mutex_unlock(&reglock);
+       ast_mutex_unlock(&showmemorylock);
        return RESULT_SUCCESS;
 }
 
@@ -256,22 +277,22 @@ static int handle_show_memory_summary(int fd, int argc, char *argv[])
        char *fn = NULL;
        int x;
        struct ast_region *reg;
-       unsigned int len=0;
+       unsigned int len = 0;
        int count = 0;
        struct file_summary *list = NULL, *cur;
        
-       if (argc >3) 
+       if (argc > 3) 
                fn = argv[3];
 
        /* try to lock applications list ... */
-       pthread_mutex_lock(&reglock);
+       ast_mutex_lock(&reglock);
 
-       for (x=0;x<SOME_PRIME;x++) {
+       for (x = 0; x < SOME_PRIME; x++) {
                reg = regions[x];
-               while(reg) {
+               while (reg) {
                        if (!fn || !strcasecmp(fn, reg->file)) {
                                cur = list;
-                               while(cur) {
+                               while (cur) {
                                        if ((!fn && !strcmp(cur->fn, reg->file)) || (fn && !strcmp(cur->fn, reg->func)))
                                                break;
                                        cur = cur->next;
@@ -279,7 +300,7 @@ static int handle_show_memory_summary(int fd, int argc, char *argv[])
                                if (!cur) {
                                        cur = alloca(sizeof(struct file_summary));
                                        memset(cur, 0, sizeof(struct file_summary));
-                                       strncpy(cur->fn, fn ? reg->func : reg->file, sizeof(cur->fn) - 1);
+                                       ast_copy_string(cur->fn, fn ? reg->func : reg->file, sizeof(cur->fn));
                                        cur->next = list;
                                        list = cur;
                                }
@@ -289,17 +310,18 @@ static int handle_show_memory_summary(int fd, int argc, char *argv[])
                        reg = reg->next;
                }
        }
-       pthread_mutex_unlock(&reglock);
+       ast_mutex_unlock(&reglock);
        
        /* Dump the whole list */
-       while(list) {
+       while (list) {
                cur = list;
                len += list->len;
                count += list->count;
-               if (fn)
+               if (fn) {
                        ast_cli(fd, "%10d bytes in %5d allocations in function '%s' of '%s'\n", list->len, list->count, list->fn, fn);
-               else
+               } else {
                        ast_cli(fd, "%10d bytes in %5d allocations in file '%s'\n", list->len, list->count, list->fn);
+               }
                list = list->next;
 #if 0
                free(cur);
@@ -329,14 +351,16 @@ static struct ast_cli_entry show_memory_summary_cli =
        handle_show_memory_summary, "Summarize outstanding memory allocations",
        show_memory_summary_help };
 
-
 void __ast_mm_init(void)
 {
+       char filename[80] = "";
        ast_cli_register(&show_memory_allocations_cli);
        ast_cli_register(&show_memory_summary_cli);
-       mmlog = fopen("/var/log/asterisk/mmlog", "a+");
+       
+       snprintf(filename, sizeof(filename), "%s/mmlog", (char *)ast_config_AST_LOG_DIR);
+       mmlog = fopen(filename, "a+");
        if (option_verbose)
-               ast_verbose("Asterisk Malloc Debugger Started (see /var/log/asterisk/mmlog)\n");
+               ast_verbose("Asterisk Malloc Debugger Started (see %s))\n", filename);
        if (mmlog) {
                fprintf(mmlog, "%ld - New session\n", time(NULL));
                fflush(mmlog);