summaryrefslogtreecommitdiffstats
path: root/lib/mem_tracker.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/mem_tracker.c')
-rw-r--r--lib/mem_tracker.c629
1 files changed, 0 insertions, 629 deletions
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;
-} ;