diff options
-rwxr-xr-x | configure.ac | 58 | ||||
-rw-r--r-- | lib/mem_tracker.c | 629 |
2 files changed, 48 insertions, 639 deletions
diff --git a/configure.ac b/configure.ac index 1efe342e..c2670fb7 100755 --- a/configure.ac +++ b/configure.ac @@ -53,13 +53,24 @@ dnl ------------ dnl Check CFLAGS dnl ------------ AC_ARG_WITH(cflags, -[ --with-cflags Set CFLAGS for use in compilation.]) +[ --with-cflags=FLAGS Set CFLAGS for use in compilation.]) if test "x$with_cflags" != "x" ; then CFLAGS="$with_cflags" ; cflags_specified=yes ; elif test -n "$CFLAGS" ; then cflags_specified=yes ; fi +dnl ------------- +dnl Check DEFINES +dnl ------------- +AC_ARG_WITH(defines, +[ --with-defines=DEFS Set DEFINES for use in compilation.]) +if test "x$with_defines" != "x" ; then + DEFINES="$with_defines" ; defines_specified=yes ; +elif test -n "$DEFINES" ; then + defines_specified=yes ; +fi + dnl -------------------- dnl Check CC and friends dnl -------------------- @@ -96,7 +107,7 @@ else fi dnl --------------------------------------------- -dnl If CLFAGS doesn\'t exist set default value +dnl If CFLAGS doesn\'t exist set default value dnl AC_PROG_CC will have set minimal default dnl already, eg "-O2 -g" for gcc, "-g" for others dnl (Wall is gcc specific... have to make sure @@ -128,7 +139,7 @@ if test "x${cflags_specified}" = "x" ; then CFLAGS="${CFLAGS} -Wbad-function-cast -Wwrite-strings" CFLAGS="${CFLAGS} -Wmissing-prototypes -Wmissing-declarations" CFLAGS="${CFLAGS} -Wchar-subscripts -Wcast-qual" - CFLAGS="${CFLAGS} -pthread -rdynamic" + CFLAGS="${CFLAGS} -pthread" # TODO: conditionally addd -Wpacked if handled AC_MSG_RESULT([gcc default]) ;; @@ -145,6 +156,27 @@ else fi dnl -------------- +dnl Append DEFINES +dnl -------------- + +AC_MSG_CHECKING([whether to append DEFINES]) +if test "x${defines_specified}" != "x" ; then + CFLAGS="${CFLAGS} ${DEFINES}" + AC_MSG_RESULT([appended ${DEFINES}]) +else + AC_MSG_RESULT([no]) +fi + +dnl ------------------- +dnl With MEMORY_TRACKER +dnl ------------------- +AC_ARG_WITH(memory_tracker, +[ --with-memory-tracker Set -DMEMORY_TRACKER]) +if test "x$with_memory_tracker" != "x" ; then + CFLAGS="$CFLAGS -DMEMORY_TRACKER" ; +fi + +dnl -------------- dnl Check programs dnl -------------- AC_PROG_INSTALL @@ -252,13 +284,15 @@ AC_ARG_ENABLE(capabilities, AC_ARG_ENABLE(gcc_ultra_verbose, [ --enable-gcc-ultra-verbose enable ultra verbose GCC warnings]) AC_ARG_ENABLE(linux24_tcp_md5, -[ --enable-linux24-tcp-md5 enable support for old, Linux-2.4 RFC2385 patch]) +[ --enable-linux24-tcp-md5 enable support for old, Linux-2.4 RFC2385 patch]) AC_ARG_ENABLE(gcc-rdynamic, -[ --enable-gcc-rdynamic enable gcc linking with -rdynamic for better backtraces]) +[ --enable-gcc-rdynamic enable gcc linking with -rdynamic for better backtraces]) +AC_ARG_ENABLE(gcc-debug, +[ --enable-gcc-debug enable gcc debug (-O0 -g3)]) AC_ARG_ENABLE(time-check, [ --disable-time-check disable slow thread warning messages]) AC_ARG_ENABLE(pcreposix, -[ --enable-pcreposix enable using PCRE Posix libs for regex functions]) +[ --enable-pcreposix enable using PCRE Posix libs for regex functions]) if test x"${enable_gcc_ultra_verbose}" = x"yes" ; then CFLAGS="${CFLAGS} -W -Wcast-qual -Wstrict-prototypes" @@ -267,6 +301,10 @@ if test x"${enable_gcc_ultra_verbose}" = x"yes" ; then CFLAGS="${CFLAGS} -Wpacked -Wpadded" fi +if test x"${enable_gcc_debug}" = x"yes" ; then + CFLAGS="${CFLAGS} -O0 -g3" +fi + if test x"${enable_gcc_rdynamic}" = x"yes" ; then LDFLAGS="${LDFLAGS} -rdynamic" fi @@ -1548,7 +1586,7 @@ echo " Quagga configuration -------------------- quagga version : ${PACKAGE_VERSION} -host operating system : ${host_os} +host operating system : ${host_os} source code location : ${srcdir} compiler : ${CC} compiler flags : ${CFLAGS} @@ -1558,9 +1596,9 @@ linker flags : ${LDFLAGS} ${LIBS} ${LIBCAP} ${LIBREADLINE} ${LIBM} state file directory : ${quagga_statedir} config file directory : `eval echo \`echo ${sysconfdir}\`` example directory : `eval echo \`echo ${exampledir}\`` -user to run as : ${enable_user} -group to run as : ${enable_group} -group for vty sockets : ${enable_vty_group} +user to run as : ${enable_user} +group to run as : ${enable_group} +group for vty sockets : ${enable_vty_group} config file mask : ${enable_configfile_mask} log file mask : ${enable_logfile_mask} diff --git a/lib/mem_tracker.c b/lib/mem_tracker.c deleted file mode 100644 index f188a13a..00000000 --- a/lib/mem_tracker.c +++ /dev/null @@ -1,629 +0,0 @@ -/* Memory Allocation Tracker - * Copyright (C) 2010 Chris Hall (GMCH), Highwayman - * - * This file is part of GNU Zebra. - * - * GNU Zebra is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * GNU Zebra is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include "vty.h" -#include <sys/mman.h> - -/*============================================================================== - * Memory Tracker - */ -typedef struct mem_region mem_region_t ; -typedef struct mem_region* mem_region ; -struct mem_region -{ - void* base ; - void* limit ; - - uint64_t allocated ; - - uint64_t used ; - uint64_t overhead ; -} ; - -typedef struct mem_descriptor mem_descriptor_t ; -typedef struct mem_descriptor* mem_descriptor ; -struct mem_descriptor -{ - void* addr ; - const char* name ; - - uint32_t next ; /* MS Type is encoded as MS 4 bits */ - uint32_t size ; /* LS Type is encoded as MS 4 bits */ -} ; - -typedef uint32_t md_index_t ; - -enum -{ - md_next_bits = 28, /* up to 256M allocated objects */ - md_next_mask = (1 << md_next_bits) - 1, - - md_index_max = md_next_mask + 1, - - md_size_bits = 28, /* up to 256M individual item */ - md_size_mask = (1 << md_size_bits) - 1, - - md_size_max = md_size_mask, - - md_next_type_bits = 32 - md_next_bits, - md_next_type_mask = (1 << md_next_type_bits) - 1, - md_size_type_bits = 32 - md_size_bits, - md_size_type_mask = (1 << md_size_type_bits) - 1, - - md_i_index_bits = 16, - md_i_index_count = 1 << md_i_index_bits, - md_i_index_mask = md_i_index_count - 1, - - md_page_bits = md_next_bits - md_i_index_bits, - md_page_count = 1 << md_page_bits, - md_page_mask = md_page_count - 1, -} ; - -CONFIRM(MTYPE_MAX < (1 << (md_next_type_bits + md_size_type_bits))) ; - -static struct mem_type_tracker -{ - struct mem_tracker mt[MTYPE_MAX] ; -} mem_type_tracker ; - -static mem_descriptor mem_page_table[md_page_count] ; - -static mem_descriptor mem_free_descriptors ; -static md_index_t mem_next_index ; - -static struct mem_tracker mem ; - -uint32_t mem_base_count ; - -md_index_t* mem_bases ; - -inline static void -mem_md_set_type(mem_descriptor md, enum MTYPE mtype) -{ - uint32_t t_ms ; - uint32_t t_ls ; - - t_ms = mtype >> md_size_type_bits ; - t_ls = mtype ; - - t_ms = (t_ms & md_next_type_mask) << md_next_bits ; - t_ls = (t_ls & md_size_type_mask) << md_size_bits ; - - md->next = (md->next & md_next_mask) | t_ms ; - md->size = (md->size & md_size_mask) | t_ls ; -} ; - -inline static void -mem_md_set_next(mem_descriptor md, md_index_t next) -{ - md->next = (md->next & ~md_next_mask) | (next & md_next_mask) ; -} ; - -inline static void -mem_md_set_size(mem_descriptor md, size_t size) -{ - md->size = (md->size & ~md_size_mask) | (size & md_size_mask) ; -} ; - -inline static uint8_t -mem_md_type(mem_descriptor md) -{ - return ( (md->next >> (md_next_bits - md_size_type_bits)) - & (md_next_type_mask << md_size_type_bits) ) - | ( (md->size >> md_size_bits) & md_size_type_mask ) ; -} ; - -inline static md_index_t -mem_md_next(mem_descriptor md) -{ - return md->next & md_next_mask ; -} ; - -inline static size_t -mem_md_size(mem_descriptor md) -{ - return md->size & md_size_mask ; -} ; - -inline static mem_descriptor -mem_md_ptr(md_index_t mdi) -{ - mem_descriptor page ; - - if (mdi == 0) - return NULL ; - - page = mem_page_table[(mdi >> md_i_index_bits) & md_page_mask] ; - passert(page != NULL) ; - return page + (mdi & md_i_index_mask) ; -} ; - -static void mem_md_make_bases(void) ; - -inline static md_index_t* -mem_md_base(void* address) -{ - if (mem_bases == NULL) - mem_md_make_bases() ; - - return mem_bases + ((uintptr_t)address % mem_base_count) ; -} ; - -static void -mem_md_make_bases(void) -{ - md_index_t* bases_was = mem_bases ; - uint32_t count_was = mem_base_count ; - - mem_base_count += 256 * 1024 ; - mem_base_count |= 1 ; - -#ifdef HAVE_MMAP - mem_bases = mmap(NULL, mem_base_count * sizeof(md_index_t), - PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) ; - passert(mem_bases != MAP_FAILED) ; -#else - mem_bases = malloc(mem_base_count * sizeof(md_index_t)) ; - passert(mem_bases != NULL) ; -#endif - - memset(mem_bases, 0, mem_base_count * sizeof(md_index_t)) ; - - if (bases_was == NULL) - passert(count_was == 0) ; - else - { - md_index_t* base = bases_was ; - md_index_t* new_base ; - md_index_t this ; - md_index_t next ; - mem_descriptor md ; - - while (count_was) - { - next = *base++ ; - while (next != 0) - { - this = next ; - md = mem_md_ptr(this) ; - next = mem_md_next(md) ; - - new_base = mem_md_base(md->addr) ; - mem_md_set_next(md, *new_base) ; - *new_base = this ; - } ; - --count_was ; - } ; - -#ifdef HAVE_MMAP - { - int rc = munmap(bases_was, count_was * sizeof(md_index_t)) ; - passert(rc >= 0) ; - } ; -#else - free(bases_was) ; -#endif - } ; -} ; - -static void -mem_md_make_descriptors(void) -{ - mem_descriptor md ; - md_index_t mdi ; - - mdi = mem_next_index ; - passert(mdi < md_index_max) ; - -#ifdef HAVE_MMAP - mem_free_descriptors = mmap(NULL, md_i_index_count * sizeof(mem_descriptor_t), - PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) ; - passert(mem_free_descriptors != MAP_FAILED) ; -#else - mem_free_descriptors = malloc(md_i_index_count * sizeof(mem_descriptor_t)) ; - passert(mem_free_descriptors != NULL) ; -#endif - - memset(mem_free_descriptors, 0, md_i_index_count * sizeof(mem_descriptor_t)) ; - - mem_page_table[(mdi >> md_i_index_bits) & md_page_mask] - = mem_free_descriptors ; - mem_next_index += md_i_index_count ; - - if (mdi == 0) - { - ++mem_free_descriptors ; /* don't use index == 0 */ - ++mdi ; - } ; - - md = mem_free_descriptors ; - while (mdi < mem_next_index) - { - md->addr = md + 1 ; /* point at next entry */ - md->next = mdi ; /* set to point at self */ - ++md ; - ++mdi ; - } ; - (md-1)->addr = NULL ; /* set end of list */ -} ; - -inline static void -mem_md_malloc(enum MTYPE mtype, void* address, size_t size, const char* name) -{ - mem_tracker mtt ; - md_index_t* base ; - mem_descriptor md ; - md_index_t mdi ; - - passert(size <= md_size_max) ; - - if (mem_free_descriptors == NULL) - mem_md_make_descriptors() ; - - md = mem_free_descriptors ; - mem_free_descriptors = md->addr ; - mdi = md->next ; - - if (mem.tracked_count >= (mem_base_count * 4)) - mem_md_make_bases() ; - - base = mem_md_base(address) ; - - md->addr = address ; - md->name = name ; - md->size = size ; - md->next = *base ; - mem_md_set_type(md, mtype) ; - - *base = mdi ; - - ++mem.malloc_count ; - ++mem.tracked_count ; - - mem.tracked_size += size ; - - if (mem.tracked_max_count < mem.tracked_count) - mem.tracked_max_count = mem.tracked_count ; - - if (mem.tracked_max_size < mem.tracked_size) - mem.tracked_max_size = mem.tracked_size ; - - mtt = &(mem_type_tracker.mt[mtype]) ; - - ++(mtt->malloc_count) ; - ++(mtt->tracked_count) ; - mtt->tracked_size += size ; - - if (mtt->tracked_max_count < mtt->tracked_count) - mtt->tracked_max_count = mtt->tracked_count ; - - if (mtt->tracked_max_size < mtt->tracked_size) - mtt->tracked_max_size = mtt->tracked_size ; -} ; - -inline static void -mem_md_free(enum MTYPE mtype, void* address) -{ - mem_tracker mtt ; - md_index_t* base ; - mem_descriptor md, prev_md ; - md_index_t this, next ; - - if (address == NULL) - return ; - - base = mem_md_base(address) ; - - prev_md = NULL ; - this = *base ; - while (this != 0) - { - md = mem_md_ptr(this) ; - next = mem_md_next(md) ; - - if (md->addr == address) - { - if (mem_md_type(md) != mtype) - zabort("memory type mismatch in free") ; - - ++mem.free_count ; - --mem.tracked_count ; - - mem.tracked_size -= mem_md_size(md) ; - - mtt = &(mem_type_tracker.mt[mtype]) ; - - ++(mtt->free_count) ; - --(mtt->tracked_count) ; - mtt->tracked_size -= mem_md_size(md) ; - - if (prev_md == NULL) - *base = next ; - else - mem_md_set_next(prev_md, next) ; - - md->addr = mem_free_descriptors ; - mem_free_descriptors = md ; - md->next = this ; - - return ; - } - else - { - prev_md = md ; - this = next ; - } ; - } ; - - zabort("Failed to find memory being freed") ; -} ; - -inline static void -mem_md_realloc(enum MTYPE mtype, void* old_address, void* new_address, - size_t size, const char* name) -{ - mem_tracker mtt ; - md_index_t* base ; - mem_descriptor md, prev_md ; - md_index_t this, next ; - - if (old_address == NULL) - { - mem_md_malloc(mtype, new_address, size, name) ; - return ; - } ; - - passert(size <= md_size_max) ; - - base = mem_md_base(old_address) ; - - prev_md = NULL ; - this = *base ; - while (this != 0) - { - md = mem_md_ptr(this) ; - next = mem_md_next(md) ; - - if (md->addr == old_address) - { - if (mem_md_type(md) != mtype) - zabort("memory type mismatch in realloc") ; - - ++mem.realloc_count ; - - mem.tracked_size += size - mem_md_size(md) ; - - if (mem.tracked_max_size < mem.tracked_size) - mem.tracked_max_size = mem.tracked_size ; - - mtt = &(mem_type_tracker.mt[mtype]) ; - - ++(mtt->realloc_count) ; - mtt->tracked_size += size - mem_md_size(md) ; - - if (mtt->tracked_max_size < mtt->tracked_size) - mtt->tracked_max_size = mtt->tracked_size ; - - md->name = name ; - mem_md_set_size(md, size) ; - - if (old_address == new_address) - return ; - - if (prev_md == NULL) - *base = next ; - else - mem_md_set_next(prev_md, next) ; - - base = mem_md_base(new_address) ; - mem_md_set_next(md, *base) ; - *base = this ; - - md->addr = new_address ; - - return ; - } - else - { - prev_md = md ; - this = next ; - } ; - } ; - - zabort("Failed to find memory being realloced") ; -} ; - -/*============================================================================== - * Memory Tracker Display - */ - -static const char* scale_d_tags [] = -{ - [0] = " " , - [1] = "k", - [2] = "m", - [3] = "g", -} ; - -static const char* scale_b_tags [] = -{ - [0] = " " , - [1] = "KiB", - [2] = "MiB", - [3] = "GiB", -} ; - -static char* -mem_show_commas(char* buff, size_t size, uint64_t val, const char* tag) -{ - char* p ; - const char* q ; - int n ; - - passert(size > 10) ; - - p = buff + size ; - *(--p) = '\0' ; - - q = tag + strlen(tag) ; - while ((p > buff) && (q > tag)) - *(--p) = *(--q) ; - - n = 3 ; - while (p > buff) - { - *(--p) = '0' + (val % 10) ; - val /= 10 ; - if (val == 0) - break ; - - if ((--n == 0) && (p > buff)) - { - *(--p) = ',' ; - n = 3 ; - } ; - } ; - - return p ; -} ; - -static char* -mem_show_count(char* buff, size_t size, uint64_t val, int scale) -{ - int i, r ; - - i = 0 ; - if (scale) - { - r = 0 ; - while ((i < 3) && (val >= 10000)) - { - r = (val % 1000) ; - val /= 1000 ; - ++i ; - } ; - if (r >= 500) { - val += 1 ; - if ((val == 10000) && (i < 3)) - { - val /= 1000 ; - ++i ; - } ; - } ; - } ; - - return mem_show_commas(buff, size, val, scale_d_tags[i]) ; -} ; - -static char* -mem_show_byte_count(char* buff, size_t size, uint64_t val, int scale) -{ - int i, r ; - - i = 0 ; - if (scale) - { - r = 0 ; - while ((i < 3) && (val >= 10000)) - { - r = (val % 1024) ; - val /= 1024 ; - ++i ; - } ; - if (r >= 512) { - val += 1 ; - if ((val == 10000) && (i < 3)) - { - val /= 1024 ; - ++i ; - } ; - } ; - } ; - - return mem_show_commas(buff, size, val, scale_b_tags[i]) ; -} ; - -static int -show_memory_tracker_summary(struct vty *vty) -{ - struct mem_tracker mt ; - enum { sbs = 100 } ; - char buf[sbs]; - size_t overhead ; - - LOCK ; - overhead = (sizeof(struct mem_descriptor) * mem_next_index) - + (sizeof(md_index_t) * mem_base_count) - + (sizeof(mem_descriptor) * md_page_count) ; - - mt = mem ; /* copy the overall memory information */ - UNLOCK ; - - vty_out (vty, "Memory Tracker Statistics:%s", VTY_NEWLINE); - vty_out (vty, " Current memory allocated: %10s%s", - mem_show_byte_count(buf, sbs, mt.tracked_size, 1), - VTY_NEWLINE); - vty_out (vty, " Current allocated objects: %8s%s", - mem_show_count (buf, sbs, mt.tracked_count, 1), - VTY_NEWLINE); - vty_out (vty, " Maximum memory allocated: %10s%s", - mem_show_byte_count(buf, sbs, mt.tracked_max_size, 1), - VTY_NEWLINE); - vty_out (vty, " Maximum allocated objects: %8s%s", - mem_show_count (buf, sbs, mt.tracked_max_count, 1), - VTY_NEWLINE); - vty_out (vty, " malloc/calloc call count: %8s%s", - mem_show_count (buf, sbs, mt.malloc_count, 1), - VTY_NEWLINE); - vty_out (vty, " realloc_call_count: %8s%s", - mem_show_count (buf, sbs, mt.realloc_count, 1), - VTY_NEWLINE); - vty_out (vty, " free call count: %8s%s", - mem_show_count (buf, sbs, mt.free_count, 1), - VTY_NEWLINE); - vty_out (vty, " Memory Tracker overhead: %10s%s", - mem_show_byte_count(buf, sbs, overhead, 1), - VTY_NEWLINE); - return 1; -} ; - -static int -show_memory_tracker_detail(struct vty *vty, struct mem_tracker* mt, - unsigned long alloc) -{ - enum { sbs = 100 } ; - char buf[sbs]; - - vty_out(vty, "%8s", mem_show_count(buf, sbs, mt->tracked_count, 1)) ; - vty_out(vty, "%10s", mem_show_byte_count(buf, sbs, mt->tracked_size, 1)) ; - vty_out(vty, "%8s", mem_show_count(buf, sbs, mt->tracked_max_count, 1)) ; - vty_out(vty, "%10s", mem_show_byte_count(buf, sbs, mt->tracked_max_size, 1)) ; - vty_out(vty, "%8s", mem_show_count(buf, sbs, mt->malloc_count, 1)) ; - vty_out(vty, "%8s", mem_show_count(buf, sbs, mt->realloc_count, 1)) ; - vty_out(vty, "%8s", mem_show_count(buf, sbs, mt->free_count, 1)) ; - - if (alloc != mt->tracked_count) - vty_out(vty, " %8s!!", mem_show_count(buf, sbs, alloc, 1)) ; - - return 1; -} ; |