diff options
Diffstat (limited to 'lib/mem_tracker.c')
-rw-r--r-- | lib/mem_tracker.c | 590 |
1 files changed, 0 insertions, 590 deletions
diff --git a/lib/mem_tracker.c b/lib/mem_tracker.c deleted file mode 100644 index b468ad2a..00000000 --- a/lib/mem_tracker.c +++ /dev/null @@ -1,590 +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" - -/*============================================================================== - * Memory Tracker - */ -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 ; - -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 mem_next_index ; - -static struct mem_tracker mem ; - -uint32_t mem_base_count ; - -md_index* 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 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 -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 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* -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* bases_was = mem_bases ; - uint32_t count_was = mem_base_count ; - - mem_base_count += 256 * 1024 ; - mem_base_count |= 1 ; - mem_bases = calloc(mem_base_count, sizeof(md_index)) ; - - passert(mem_bases != NULL) ; - - if (bases_was == NULL) - passert(count_was == 0) ; - else - { - md_index* base = bases_was ; - md_index* new_base ; - md_index this ; - md_index 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 ; - } ; - - free(bases_was) ; - } ; -} ; - -static void -mem_md_make_descriptors(void) -{ - mem_descriptor md ; - md_index mdi ; - - mdi = mem_next_index ; - passert(mdi < md_index_max) ; - - mem_free_descriptors - = mem_page_table[(mdi >> md_i_index_bits) & md_page_mask] - = calloc(md_i_index_count, sizeof(struct mem_descriptor)) ; - - passert(mem_free_descriptors != NULL) ; - - 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* base ; - mem_descriptor md ; - md_index 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* base ; - mem_descriptor md, prev_md ; - md_index 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* base ; - mem_descriptor md, prev_md ; - md_index 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) * 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; -} ; |