From c4f6175e9b11585496bde1c8cc0691be2ca3c845 Mon Sep 17 00:00:00 2001 From: Stefan Mititelu Date: Fri, 19 Jun 2015 11:55:51 +0300 Subject: [PATCH] kex: per module memory debugging Kex module updated to also give some details about memory used by each module. Changed f_*, q_* and tlsf_* memory stubs to also include the module name. Added 2 new memory API functions(for each of the memory algos) which will iterate throughout the memory fragments and agregate the memory size used by each function in order to print it. Tested with MEMMNG=0,1,2 and MEMDBG=0,1. Updated doku. --- events.c | 25 +++ events.h | 4 + mem/f_malloc.c | 130 ++++++++++++---- mem/f_malloc.h | 26 +++- mem/memapi.h | 21 ++- mem/pkg.c | 2 + mem/pkg.h | 8 +- mem/q_malloc.c | 125 +++++++++++---- mem/q_malloc.h | 23 ++- mem/shm.c | 2 + mem/shm.h | 15 +- mem/shm_mem.c | 2 +- mem/shm_mem.h | 20 +-- mem/src_loc.h | 2 +- mem/tlsf_malloc.c | 111 +++++++++---- mem/tlsf_malloc.h | 20 ++- modules/ctl/binrpc_run.c | 12 +- modules/kex/doc/kex_admin.xml | 76 +++++++++ modules/kex/kex_mod.c | 7 + modules/kex/mod_stats.c | 282 ++++++++++++++++++++++++++++++++++ modules/kex/mod_stats.h | 37 +++++ 21 files changed, 816 insertions(+), 134 deletions(-) create mode 100644 modules/kex/mod_stats.c create mode 100644 modules/kex/mod_stats.h diff --git a/events.c b/events.c index 5312e7a5ba7..3b0d651147c 100644 --- a/events.c +++ b/events.c @@ -165,6 +165,15 @@ int sr_event_register_cb(int type, sr_event_cb_f f) _sr_events_list.rcv_nosip = f; else return -1; break; + case SREV_MODULE_PKG_STATS: + if(_sr_events_list.mod_update_pkg_stats==0) + _sr_events_list.mod_update_pkg_stats = f; + else return -1; + case SREV_MODULE_SHM_STATS: + if(_sr_events_list.mod_update_shm_stats==0) + _sr_events_list.mod_update_shm_stats = f; + else return -1; + break; default: return -1; } @@ -284,6 +293,18 @@ int sr_event_exec(int type, void *data) ret = _sr_events_list.rcv_nosip(data); return ret; } else return 1; + case SREV_MODULE_PKG_STATS: + if(unlikely(_sr_events_list.mod_update_pkg_stats!=0)) + { + ret = _sr_events_list.mod_update_pkg_stats(data); + return ret; + } else return 1; + case SREV_MODULE_SHM_STATS: + if(unlikely(_sr_events_list.mod_update_shm_stats!=0)) + { + ret = _sr_events_list.mod_update_shm_stats(data); + return ret; + } else return 1; default: return -1; } @@ -319,6 +340,10 @@ int sr_event_enabled(int type) return (_sr_events_list.stun_in!=0)?1:0; case SREV_RCV_NOSIP: return (_sr_events_list.rcv_nosip!=0)?1:0; + case SREV_MODULE_PKG_STATS: + return (_sr_events_list.mod_update_pkg_stats!=0)?1:0; + case SREV_MODULE_SHM_STATS: + return (_sr_events_list.mod_update_shm_stats!=0)?1:0; } return 0; } diff --git a/events.h b/events.h index 821845366d8..4443a7933c7 100644 --- a/events.h +++ b/events.h @@ -34,6 +34,8 @@ #define SREV_TCP_WS_FRAME_IN 10 #define SREV_TCP_WS_FRAME_OUT 11 #define SREV_STUN_IN 12 +#define SREV_MODULE_PKG_STATS 13 +#define SREV_MODULE_SHM_STATS 14 #define SREV_CB_LIST_SIZE 3 @@ -52,6 +54,8 @@ typedef struct sr_event_cb { sr_event_cb_f tcp_ws_frame_out; sr_event_cb_f stun_in; sr_event_cb_f rcv_nosip; + sr_event_cb_f mod_update_pkg_stats; + sr_event_cb_f mod_update_shm_stats; } sr_event_cb_t; void sr_event_cb_init(void); diff --git a/mem/f_malloc.c b/mem/f_malloc.c index da13e565e50..59f809eced5 100644 --- a/mem/f_malloc.c +++ b/mem/f_malloc.c @@ -265,7 +265,8 @@ static inline #ifdef DBG_F_MALLOC void fm_split_frag(struct fm_block* qm, struct fm_frag* frag, unsigned long size, - const char* file, const char* func, unsigned int line) + const char* file, const char* func, unsigned int line, + const char* mname) #else void fm_split_frag(struct fm_block* qm, struct fm_frag* frag, unsigned long size) @@ -291,6 +292,7 @@ void fm_split_frag(struct fm_block* qm, struct fm_frag* frag, n->file=file; n->func="frag. from fm_split_frag"; n->line=line; + n->mname=mname; #endif n->check=ST_CHECK_PATTERN; /* reinsert n in free list*/ @@ -419,8 +421,8 @@ struct fm_frag* fm_search_defrag(struct fm_block* qm, unsigned long size) * \return address of allocated memory */ #ifdef DBG_F_MALLOC -void* fm_malloc(void* qmp, unsigned long size, - const char* file, const char* func, unsigned int line) +void* fm_malloc(void* qmp, unsigned long size, const char* file, + const char* func, unsigned int line, const char* mname) #else void* fm_malloc(void* qmp, unsigned long size) #endif @@ -496,7 +498,7 @@ void* fm_malloc(void* qmp, unsigned long size) /*see if use full frag or split it in two*/ #ifdef DBG_F_MALLOC - fm_split_frag(qm, frag, size, file, func, line); + fm_split_frag(qm, frag, size, file, func, line, mname); #else fm_split_frag(qm, frag, size); #endif @@ -506,6 +508,7 @@ void* fm_malloc(void* qmp, unsigned long size) #ifdef DBG_F_MALLOC frag->file=file; frag->func=func; + frag->mname=mname; frag->line=line; MDBG("fm_malloc(%p, %lu) returns address %p \n", qm, size, (char*)frag+sizeof(struct fm_frag)); @@ -557,8 +560,8 @@ static void fm_join_frag(struct fm_block* qm, struct fm_frag* f) * \param p freed memory */ #ifdef DBG_F_MALLOC -void fm_free(void* qmp, void* p, const char* file, const char* func, - unsigned int line) +void fm_free(void* qmp, void* p, const char* file, const char* func, + unsigned int line, const char* mname) #else void fm_free(void* qmp, void* p) #endif @@ -602,6 +605,7 @@ void fm_free(void* qmp, void* p) f->file=file; f->func=func; f->line=line; + f->mname=mname; #endif #ifdef MEM_JOIN_FREE if(unlikely(cfg_get(core, core_cfg, mem_join)!=0)) @@ -622,7 +626,8 @@ void fm_free(void* qmp, void* p) */ #ifdef DBG_F_MALLOC void* fm_realloc(void* qmp, void* p, unsigned long size, - const char* file, const char* func, unsigned int line) + const char* file, const char* func, unsigned int line, + const char *mname) #else void* fm_realloc(void* qmp, void* p, unsigned long size) #endif @@ -648,7 +653,7 @@ void* fm_realloc(void* qmp, void* p, unsigned long size) if (size==0) { if (p) #ifdef DBG_F_MALLOC - fm_free(qm, p, file, func, line); + fm_free(qm, p, file, func, line, mname); #else fm_free(qm, p); #endif @@ -656,7 +661,7 @@ void* fm_realloc(void* qmp, void* p, unsigned long size) } if (p==0) #ifdef DBG_F_MALLOC - return fm_malloc(qm, size, file, func, line); + return fm_malloc(qm, size, file, func, line, mname); #else return fm_malloc(qm, size); #endif @@ -671,7 +676,7 @@ void* fm_realloc(void* qmp, void* p, unsigned long size) /* shrink */ #ifdef DBG_F_MALLOC MDBG("fm_realloc: shrinking from %lu to %lu\n", f->size, size); - fm_split_frag(qm, f, size, file, "frag. from fm_realloc", line); + fm_split_frag(qm, f, size, file, "frag. from fm_realloc", line, mname); #else fm_split_frag(qm, f, size); #endif @@ -695,7 +700,7 @@ void* fm_realloc(void* qmp, void* p, unsigned long size) if (f->size > size){ #ifdef DBG_F_MALLOC fm_split_frag(qm, f, size, file, "fragm. from fm_realloc", - line); + line, mname); #else fm_split_frag(qm, f, size); #endif @@ -703,7 +708,7 @@ void* fm_realloc(void* qmp, void* p, unsigned long size) }else{ /* could not join => realloc */ #ifdef DBG_F_MALLOC - ptr=fm_malloc(qm, size, file, func, line); + ptr=fm_malloc(qm, size, file, func, line, mname); #else ptr=fm_malloc(qm, size); #endif @@ -712,7 +717,7 @@ void* fm_realloc(void* qmp, void* p, unsigned long size) memcpy(ptr, p, orig_size); } #ifdef DBG_F_MALLOC - fm_free(qm, p, file, func, line); + fm_free(qm, p, file, func, line, mname); #else fm_free(qm, p); #endif @@ -873,17 +878,6 @@ unsigned long fm_available(void* qmp) #ifdef DBG_F_MALLOC -typedef struct _mem_counter{ - const char *file; - const char *func; - unsigned long line; - - unsigned long size; - int count; - - struct _mem_counter *next; -} mem_counter; - static mem_counter* get_mem_counter(mem_counter **root,struct fm_frag* f) { mem_counter *x; @@ -897,6 +891,7 @@ static mem_counter* get_mem_counter(mem_counter **root,struct fm_frag* f) x->file = f->file; x->func = f->func; x->line = f->line; + x->mname = f->mname; x->count = 0; x->size = 0; x->next = *root; @@ -947,9 +942,60 @@ void fm_sums(void* qmp) } LOG_(DEFAULT_FACILITY, memlog, "fm_status: ", "-----------------------------\n"); + +} + + +void fm_mod_get_stats(void *qmp, void **fm_rootp) +{ + if (!fm_rootp) { + return ; + } + + LM_DBG("get fm memory statistics\n"); + + struct fm_block *qm = (struct fm_block *) qmp; + mem_counter **fm_root = (mem_counter **) fm_rootp; + struct fm_frag* f; + int i; + mem_counter *x; + + if (!qm) return ; + + /* update fragment detail list */ + for (f=qm->first_frag, i=0; (char*)f<(char*)qm->last_frag; + f=FRAG_NEXT(f), i++){ + if (f->is_free==0){ + x = get_mem_counter(fm_root,f); + x->count++; + x->size+=f->size; + } + } + + return ; +} + +void fm_mod_free_stats(void *fm_rootp) +{ + if (!fm_rootp) { + return ; + } + + LM_DBG("free fm memory statistics\n"); + + mem_counter *root = (mem_counter *) fm_rootp; + mem_counter *new, *old; + new = root; + old = root; + + while (new) { + old = new; + new = new->next; + free(old); + } } #else -void fm_sums(void* qmp) +void fm_sums(void *qmp) { struct fm_block* qm; int memlog; @@ -959,6 +1005,18 @@ void fm_sums(void* qmp) LOG_(DEFAULT_FACILITY, memlog, "fm_sums: ", "not available (%p)\n", qm); return; } + +void fm_mod_get_stats(void *qmp, void **fm_rootp) +{ + LM_WARN("Enable DBG_F_MALLOC for getting statistics\n"); + return ; +} + +void fm_mod_free_stats(void *fm_rootp) +{ + LM_WARN("Enable DBG_F_MALLOC for freeing statistics\n"); + return ; +} #endif /* DBG_F_MALLOC */ @@ -1009,6 +1067,8 @@ int fm_malloc_init_pkg_manager(void) ma.xavailable = fm_available; ma.xsums = fm_sums; ma.xdestroy = fm_malloc_destroy_pkg_manager; + ma.xstats = fm_mod_get_stats; + ma.xfstats = fm_mod_free_stats; return pkg_init_api(&ma); } @@ -1021,38 +1081,38 @@ static struct fm_block *_fm_shm_block = 0; /*SHM wrappers to sync the access to memory block*/ #ifdef DBG_F_MALLOC void* fm_shm_malloc(void* qmp, unsigned long size, - const char* file, const char* func, unsigned int line) + const char* file, const char* func, unsigned int line, const char* mname) { void *r; shm_lock(); - r = fm_malloc(qmp, size, file, func, line); + r = fm_malloc(qmp, size, file, func, line, mname); shm_unlock(); return r; } void* fm_shm_realloc(void* qmp, void* p, unsigned long size, - const char* file, const char* func, unsigned int line) + const char* file, const char* func, unsigned int line, const char* mname) { void *r; shm_lock(); - r = fm_realloc(qmp, p, size, file, func, line); + r = fm_realloc(qmp, p, size, file, func, line, mname); shm_unlock(); return r; } void* fm_shm_resize(void* qmp, void* p, unsigned long size, - const char* file, const char* func, unsigned int line) + const char* file, const char* func, unsigned int line, const char* mname) { void *r; shm_lock(); - if(p) fm_free(qmp, p, file, func, line); - r = fm_malloc(qmp, size, file, func, line); + if(p) fm_free(qmp, p, file, func, line, mname); + r = fm_malloc(qmp, size, file, func, line, mname); shm_unlock(); return r; } void fm_shm_free(void* qmp, void* p, const char* file, const char* func, - unsigned int line) + unsigned int line, const char* mname) { shm_lock(); - fm_free(qmp, p, file, func, line); + fm_free(qmp, p, file, func, line, mname); shm_unlock(); } #else @@ -1158,6 +1218,8 @@ int fm_malloc_init_shm_manager(void) ma.xavailable = fm_shm_available; ma.xsums = fm_shm_sums; ma.xdestroy = fm_malloc_destroy_shm_manager; + ma.xstats = fm_mod_get_stats; + ma.xfstats = fm_mod_free_stats; if(shm_init_api(&ma)<0) { LM_ERR("cannot initialize the core shm api\n"); diff --git a/mem/f_malloc.h b/mem/f_malloc.h index 9344ea07a18..cf6f56b277f 100644 --- a/mem/f_malloc.h +++ b/mem/f_malloc.h @@ -86,6 +86,7 @@ struct fm_frag{ #ifdef DBG_F_MALLOC const char* file; const char* func; + const char* mname; unsigned long line; #endif unsigned int check; @@ -134,7 +135,8 @@ struct fm_block* fm_malloc_init(char* address, unsigned long size, int type); */ #ifdef DBG_F_MALLOC void* fm_malloc(void* qmp, unsigned long size, - const char* file, const char* func, unsigned int line); + const char* file, const char* func, unsigned int line, + const char* mname); #else void* fm_malloc(void* qmp, unsigned long size); #endif @@ -148,8 +150,8 @@ void* fm_malloc(void* qmp, unsigned long size); * \param p freed memory */ #ifdef DBG_F_MALLOC -void fm_free(void* qmp, void* p, const char* file, const char* func, - unsigned int line); +void fm_free(void* qmp, void* p, const char* file, const char* func, + unsigned int line, const char* mname); #else void fm_free(void* qmp, void* p); #endif @@ -165,8 +167,8 @@ void fm_free(void* qmp, void* p); * \return reallocated memory block */ #ifdef DBG_F_MALLOC -void* fm_realloc(void* qmp, void* p, unsigned long size, - const char* file, const char* func, unsigned int line); +void* fm_realloc(void* qmp, void* p, unsigned long size, + const char* file, const char* func, unsigned int line, const char *mname); #else void* fm_realloc(void* qmp, void* p, unsigned long size); #endif @@ -204,6 +206,20 @@ unsigned long fm_available(void* qmp); * \param qm memory block */ void fm_sums(void* qmp); +void fm_mod_get_stats(void* qm, void **fm_root); +void fm_mod_free_stats(void *root); + +typedef struct _mem_counter{ + const char *file; + const char *func; + const char *mname; + unsigned long line; + + unsigned long size; + int count; + + struct _mem_counter *next; +} mem_counter; #endif #endif diff --git a/mem/memapi.h b/mem/memapi.h index e1b78a0e92e..9f918f3ae73 100644 --- a/mem/memapi.h +++ b/mem/memapi.h @@ -27,13 +27,13 @@ #ifdef DBG_SR_MEMORY typedef void* (*sr_malloc_f)(void* mbp, unsigned long size, - const char* file, const char* func, unsigned int line); -typedef void (*sr_free_f)(void* mbp, void* p, const char* file, const char* func, - unsigned int line); + const char* file, const char* func, unsigned int line, const char* mname); +typedef void (*sr_free_f)(void* mbp, void* p, const char* file, const char* func, + unsigned int line, const char* mname); typedef void* (*sr_realloc_f)(void* mbp, void* p, unsigned long size, - const char* file, const char* func, unsigned int line); + const char* file, const char* func, unsigned int line, const char* mname); typedef void* (*sr_resize_f)(void* mbp, void* p, unsigned long size, - const char* file, const char* func, unsigned int line); + const char* file, const char* func, unsigned int line, const char* mname); #else /*DBG_SR_MEMORY*/ @@ -51,6 +51,9 @@ typedef void (*sr_mem_sums_f)(void* mbp); typedef void (*sr_mem_destroy_f)(void); +typedef void (*sr_mem_mod_get_stats_f)(void* mbp, void **p); +typedef void (*sr_mem_mod_free_stats_f)(void* mbp); + /*private memory api*/ typedef struct sr_pkg_api { /*memory manager name - soft copy*/ @@ -75,6 +78,10 @@ typedef struct sr_pkg_api { sr_mem_sums_f xsums; /*memory destroy manager*/ sr_mem_destroy_f xdestroy; + /*memory stats per module*/ + sr_mem_mod_get_stats_f xstats; + /*memory stats free per module*/ + sr_mem_mod_free_stats_f xfstats; } sr_pkg_api_t; /*shared memory api*/ @@ -107,6 +114,10 @@ typedef struct sr_shm_api { sr_mem_sums_f xsums; /*memory destroy manager*/ sr_mem_destroy_f xdestroy; + /*memory stats per module*/ + sr_mem_mod_get_stats_f xstats; + /*memory stats free per module*/ + sr_mem_mod_free_stats_f xfstats; } sr_shm_api_t; #endif diff --git a/mem/pkg.c b/mem/pkg.c index f7543277314..a4f0906efbc 100644 --- a/mem/pkg.c +++ b/mem/pkg.c @@ -46,6 +46,8 @@ int pkg_init_api(sr_pkg_api_t *ap) _pkg_root.xavailable = ap->xavailable; _pkg_root.xsums = ap->xsums; _pkg_root.xdestroy = ap->xdestroy; + _pkg_root.xstats = ap->xstats; + _pkg_root.xfstats = ap->xfstats; return 0; } diff --git a/mem/pkg.h b/mem/pkg.h index dd062bb21f4..82e430a0110 100644 --- a/mem/pkg.h +++ b/mem/pkg.h @@ -28,11 +28,11 @@ extern sr_pkg_api_t _pkg_root; #ifdef DBG_SR_MEMORY # define pkg_malloc(s) _pkg_root.xmalloc(_pkg_root.mem_block, (s), _SRC_LOC_, \ - _SRC_FUNCTION_, _SRC_LINE_) + _SRC_FUNCTION_, _SRC_LINE_, _SRC_MODULE_) # define pkg_free(p) _pkg_root.xfree(_pkg_root.mem_block, (p), _SRC_LOC_, \ - _SRC_FUNCTION_, _SRC_LINE_) + _SRC_FUNCTION_, _SRC_LINE_, _SRC_MODULE_) # define pkg_realloc(p, s) _pkg_root.xrealloc(_pkg_root.mem_block, (p), (s), \ - _SRC_LOC_, _SRC_FUNCTION_, _SRC_LINE_) + _SRC_LOC_, _SRC_FUNCTION_, _SRC_LINE_, _SRC_MODULE_) #else # define pkg_malloc(s) _pkg_root.xmalloc(_pkg_root.mem_block, (s)) # define pkg_realloc(p, s) _pkg_root.xrealloc(_pkg_root.mem_block, (p), (s)) @@ -43,6 +43,8 @@ extern sr_pkg_api_t _pkg_root; # define pkg_info(mi) _pkg_root.xinfo(_pkg_root.mem_block, mi) # define pkg_available() _pkg_root.xavailable(_pkg_root.mem_block) # define pkg_sums() _pkg_root.xsums(_pkg_root.mem_block) +# define pkg_mod_get_stats(x) _pkg_root.xstats(_pkg_root.mem_block, x) +# define pkg_mod_free_stats(x) _pkg_root.xfstats(x) int pkg_init_api(sr_pkg_api_t *ap); int pkg_init_manager(char *name); diff --git a/mem/q_malloc.c b/mem/q_malloc.c index 46b0c3add45..982682880f8 100644 --- a/mem/q_malloc.c +++ b/mem/q_malloc.c @@ -294,7 +294,7 @@ static inline struct qm_frag* qm_find_free(struct qm_block* qm, static inline #ifdef DBG_QM_MALLOC int split_frag(struct qm_block* qm, struct qm_frag* f, unsigned long new_size, - const char* file, const char* func, unsigned int line) + const char* file, const char* func, unsigned int line, const char *mname) #else int split_frag(struct qm_block* qm, struct qm_frag* f, unsigned long new_size) #endif @@ -326,6 +326,7 @@ int split_frag(struct qm_block* qm, struct qm_frag* f, unsigned long new_size) n->file=file; n->func=func; n->line=line; + n->mname=mname; n->check=ST_CHECK_PATTERN; #endif /* reinsert n in free list*/ @@ -341,7 +342,8 @@ int split_frag(struct qm_block* qm, struct qm_frag* f, unsigned long new_size) #ifdef DBG_QM_MALLOC void* qm_malloc(void* qmp, unsigned long size, - const char* file, const char* func, unsigned int line) + const char* file, const char* func, unsigned int line, + const char *mname) #else void* qm_malloc(void* qmp, unsigned long size) #endif @@ -384,7 +386,7 @@ void* qm_malloc(void* qmp, unsigned long size) qm->ffrags--; /* we ignore split return */ #ifdef DBG_QM_MALLOC - split_frag(qm, f, size, file, "fragm. from qm_malloc", line); + split_frag(qm, f, size, file, "fragm. from qm_malloc", line, mname); #else split_frag(qm, f, size); #endif @@ -395,6 +397,7 @@ void* qm_malloc(void* qmp, unsigned long size) #ifdef DBG_QM_MALLOC f->file=file; f->func=func; + f->mname=mname; f->line=line; f->check=ST_CHECK_PATTERN; /* FRAG_END(f)->check1=END_CHECK_PATTERN1; @@ -416,8 +419,8 @@ void* qm_malloc(void* qmp, unsigned long size) #ifdef DBG_QM_MALLOC -void qm_free(void* qmp, void* p, const char* file, const char* func, - unsigned int line) +void qm_free(void* qmp, void* p, const char* file, const char* func, + unsigned int line, const char *mname) #else void qm_free(void* qmp, void* p) #endif @@ -525,6 +528,7 @@ void qm_free(void* qmp, void* p) #ifdef DBG_QM_MALLOC f->file=file; f->func=func; + f->mname=mname; f->line=line; #endif qm_insert_free(qm, f); @@ -539,7 +543,8 @@ void qm_free(void* qmp, void* p) #ifdef DBG_QM_MALLOC void* qm_realloc(void* qmp, void* p, unsigned long size, - const char* file, const char* func, unsigned int line) + const char* file, const char* func, unsigned int line, + const char *mname) #else void* qm_realloc(void* qmp, void* p, unsigned long size) #endif @@ -566,7 +571,7 @@ void* qm_realloc(void* qmp, void* p, unsigned long size) if (size==0) { if (p) #ifdef DBG_QM_MALLOC - qm_free(qm, p, file, func, line); + qm_free(qm, p, file, func, line, mname); #else qm_free(qm, p); #endif @@ -574,7 +579,7 @@ void* qm_realloc(void* qmp, void* p, unsigned long size) } if (p==0) #ifdef DBG_QM_MALLOC - return qm_malloc(qm, size, file, func, line); + return qm_malloc(qm, size, file, func, line, mname); #else return qm_malloc(qm, size); #endif @@ -596,7 +601,7 @@ void* qm_realloc(void* qmp, void* p, unsigned long size) /* shrink */ #ifdef DBG_QM_MALLOC MDBG("qm_realloc: shrinking from %lu to %lu\n", f->size, size); - if(split_frag(qm, f, size, file, "fragm. from qm_realloc", line)!=0){ + if(split_frag(qm, f, size, file, "fragm. from qm_realloc", line, mname)!=0){ MDBG("qm_realloc : shrinked successful\n"); #else if(split_frag(qm, f, size)!=0){ @@ -631,7 +636,7 @@ void* qm_realloc(void* qmp, void* p, unsigned long size) if (f->size > size ){ #ifdef DBG_QM_MALLOC split_frag(qm, f, size, file, "fragm. from qm_realloc", - line); + line, mname); #else split_frag(qm, f, size); #endif @@ -641,7 +646,7 @@ void* qm_realloc(void* qmp, void* p, unsigned long size) }else{ /* could not join => realloc */ #ifdef DBG_QM_MALLOC - ptr=qm_malloc(qm, size, file, func, line); + ptr=qm_malloc(qm, size, file, func, line, mname); #else ptr=qm_malloc(qm, size); #endif @@ -650,7 +655,7 @@ void* qm_realloc(void* qmp, void* p, unsigned long size) memcpy(ptr, p, orig_size); } #ifdef DBG_QM_MALLOC - qm_free(qm, p, file, func, line); + qm_free(qm, p, file, func, line, mname); #else qm_free(qm, p); #endif @@ -848,16 +853,6 @@ unsigned long qm_available(void* qmp) #ifdef DBG_QM_MALLOC -typedef struct _mem_counter{ - const char *file; - const char *func; - unsigned long line; - - unsigned long size; - int count; - - struct _mem_counter *next; -} mem_counter; static mem_counter* get_mem_counter(mem_counter **root, struct qm_frag* f) { @@ -870,6 +865,7 @@ static mem_counter* get_mem_counter(mem_counter **root, struct qm_frag* f) x = malloc(sizeof(mem_counter)); x->file = f->file; x->func = f->func; + x->mname= f->mname; x->line = f->line; x->count = 0; x->size = 0; @@ -919,10 +915,71 @@ void qm_sums(void* qmp) LOG_(DEFAULT_FACILITY, memlog, "qm_sums: ", "-----------------------------\n"); } + +void qm_mod_get_stats(void *qmp, void **qm_rootp) +{ + if (!qm_rootp) { + return ; + } + + LM_DBG("get qm memory statistics\n"); + + struct qm_block *qm = (struct qm_block *) qmp; + mem_counter **qm_root = (mem_counter **) qm_rootp; + struct qm_frag* f; + int i; + mem_counter *x; + + if (!qm) return ; + + /* update fragment detail list */ + for (f=qm->first_frag, i=0; (char*)f<(char*)qm->last_frag_end; + f=FRAG_NEXT(f), i++){ + if (! f->u.is_free){ + x = get_mem_counter(qm_root,f); + x->count++; + x->size+=f->size; + } + } + + return ; +} + +void qm_mod_free_stats(void *qm_rootp) +{ + if (!qm_rootp) { + return ; + } + + LM_DBG("free qm memory statistics\n"); + + mem_counter *root = (mem_counter *) qm_rootp; + mem_counter *new, *old; + new = root; + old = root; + + while (new) { + old = new; + new = new->next; + free(old); + } +} #else -void qm_sums(void* qm) +void qm_sums(void *qmp) +{ + return; +} + +void qm_mod_get_stats(void *qmp, void **qm_rootp) +{ + LM_WARN("Enable DBG_QM_MALLOC for getting statistics\n"); + return; +} + +void qm_mod_free_stats(void *qm_rootp) { + LM_WARN("Enable DBG_QM_MALLOC for freeing statistics\n"); return; } #endif /* DBG_QM_MALLOC */ @@ -975,6 +1032,8 @@ int qm_malloc_init_pkg_manager(void) ma.xavailable = qm_available; ma.xsums = qm_sums; ma.xdestroy = qm_malloc_destroy_pkg_manager; + ma.xstats = qm_mod_get_stats; + ma.xfstats = qm_mod_free_stats; return pkg_init_api(&ma); } @@ -987,38 +1046,38 @@ static struct qm_block *_qm_shm_block = 0; /*SHM wrappers to sync the access to memory block*/ #ifdef DBG_QM_MALLOC void* qm_shm_malloc(void* qmp, unsigned long size, - const char* file, const char* func, unsigned int line) + const char* file, const char* func, unsigned int line, const char* mname) { void *r; shm_lock(); - r = qm_malloc(qmp, size, file, func, line); + r = qm_malloc(qmp, size, file, func, line, mname); shm_unlock(); return r; } void* qm_shm_realloc(void* qmp, void* p, unsigned long size, - const char* file, const char* func, unsigned int line) + const char* file, const char* func, unsigned int line, const char* mname) { void *r; shm_lock(); - r = qm_realloc(qmp, p, size, file, func, line); + r = qm_realloc(qmp, p, size, file, func, line, mname); shm_unlock(); return r; } void* qm_shm_resize(void* qmp, void* p, unsigned long size, - const char* file, const char* func, unsigned int line) + const char* file, const char* func, unsigned int line, const char* mname) { void *r; shm_lock(); - if(p) qm_free(qmp, p, file, func, line); - r = qm_malloc(qmp, size, file, func, line); + if(p) qm_free(qmp, p, file, func, line, mname); + r = qm_malloc(qmp, size, file, func, line, mname); shm_unlock(); return r; } void qm_shm_free(void* qmp, void* p, const char* file, const char* func, - unsigned int line) + unsigned int line, const char* mname) { shm_lock(); - qm_free(qmp, p, file, func, line); + qm_free(qmp, p, file, func, line, mname); shm_unlock(); } #else @@ -1124,6 +1183,8 @@ int qm_malloc_init_shm_manager(void) ma.xavailable = qm_shm_available; ma.xsums = qm_shm_sums; ma.xdestroy = qm_malloc_destroy_shm_manager; + ma.xstats = qm_mod_get_stats; + ma.xfstats = qm_mod_free_stats; if(shm_init_api(&ma)<0) { LM_ERR("cannot initialize the core shm api\n"); diff --git a/mem/q_malloc.h b/mem/q_malloc.h index e2333c42ff7..10a768e0f2f 100644 --- a/mem/q_malloc.h +++ b/mem/q_malloc.h @@ -77,6 +77,7 @@ struct qm_frag{ #ifdef DBG_QM_MALLOC const char* file; const char* func; + const char* mname; unsigned long line; unsigned long check; #endif @@ -128,20 +129,20 @@ struct qm_block* qm_malloc_init(char* address, unsigned long size, int type); #ifdef DBG_QM_MALLOC void* qm_malloc(void*, unsigned long size, const char* file, - const char* func, unsigned int line); + const char* func, unsigned int line, const char* mname); #else void* qm_malloc(void*, unsigned long size); #endif #ifdef DBG_QM_MALLOC -void qm_free(void*, void* p, const char* file, const char* func, - unsigned int line); +void qm_free(void*, void* p, const char* file, const char* func, + unsigned int line, const char* mname); #else void qm_free(void*, void* p); #endif #ifdef DBG_QM_MALLOC void* qm_realloc(void*, void* p, unsigned long size, - const char* file, const char* func, unsigned int line); + const char* file, const char* func, unsigned int line, const char *mname); #else void* qm_realloc(void*, void* p, unsigned long size); #endif @@ -154,6 +155,20 @@ void qm_info(void*, struct mem_info*); unsigned long qm_available(void* qm); void qm_sums(void* qm); +void qm_mod_get_stats(void *qm, void **qm_root); +void qm_mod_free_stats(void *root); + +typedef struct _mem_counter{ + const char *file; + const char *func; + const char *mname; + unsigned long line; + + unsigned long size; + int count; + + struct _mem_counter *next; +} mem_counter; #endif #endif diff --git a/mem/shm.c b/mem/shm.c index df8e13e4877..94a99150e91 100644 --- a/mem/shm.c +++ b/mem/shm.c @@ -221,6 +221,8 @@ int shm_init_api(sr_shm_api_t *ap) _shm_root.xavailable = ap->xavailable; _shm_root.xsums = ap->xsums; _shm_root.xdestroy = ap->xdestroy; + _shm_root.xstats = ap->xstats; + _shm_root.xfstats = ap->xfstats; return 0; } diff --git a/mem/shm.h b/mem/shm.h index 47d11df2e23..cbf4c3a77be 100644 --- a/mem/shm.h +++ b/mem/shm.h @@ -49,17 +49,17 @@ extern sr_shm_api_t _shm_root; #ifdef DBG_SR_MEMORY # define shm_malloc(s) _shm_root.xmalloc(_shm_root.mem_block, (s), _SRC_LOC_, \ - _SRC_FUNCTION_, _SRC_LINE_) + _SRC_FUNCTION_, _SRC_LINE_, _SRC_MODULE_) # define shm_malloc_unsafe(s) _shm_root.xmalloc_unsafe(_shm_root.mem_block, (s), _SRC_LOC_, \ - _SRC_FUNCTION_, _SRC_LINE_) + _SRC_FUNCTION_, _SRC_LINE_, _SRC_MODULE_) # define shm_realloc(p, s) _shm_root.xrealloc(_shm_root.mem_block, (p), (s), \ - _SRC_LOC_, _SRC_FUNCTION_, _SRC_LINE_) + _SRC_LOC_, _SRC_FUNCTION_, _SRC_LINE_, _SRC_MODULE_) # define shm_resize(p, s) _shm_root.xresize(_shm_root.mem_block, (p), (s), \ - _SRC_LOC_, _SRC_FUNCTION_, _SRC_LINE_) + _SRC_LOC_, _SRC_FUNCTION_, _SRC_LINE_, _SRC_MODULE_) # define shm_free(p) _shm_root.xfree(_shm_root.mem_block, (p), _SRC_LOC_, \ - _SRC_FUNCTION_, _SRC_LINE_) + _SRC_FUNCTION_, _SRC_LINE_, _SRC_MODULE_) # define shm_free_unsafe(p) _shm_root.xfree_unsafe(_shm_root.mem_block, (p), _SRC_LOC_, \ - _SRC_FUNCTION_, _SRC_LINE_) + _SRC_FUNCTION_, _SRC_LINE_, _SRC_MODULE_) #else # define shm_malloc(s) _shm_root.xmalloc(_shm_root.mem_block, (s)) # define shm_malloc_unsafe(s) _shm_root.xmalloc_unsafe(_shm_root.mem_block, (s)) @@ -73,6 +73,9 @@ extern sr_shm_api_t _shm_root; # define shm_info(mi) _shm_root.xinfo(_shm_root.mem_block, mi) # define shm_available() _shm_root.xavailable(_shm_root.mem_block) # define shm_sums() _shm_root.xsums(_shm_root.mem_block) +# define shm_mod_get_stats(x) _shm_root.xstats(_shm_root.mem_block, x) +# define shm_mod_free_stats(x) _shm_root.xfstats(x) + void* shm_core_get_pool(void); int shm_init_api(sr_shm_api_t *ap); diff --git a/mem/shm_mem.c b/mem/shm_mem.c index 8395cfdeeab..f2800b0a3f3 100644 --- a/mem/shm_mem.c +++ b/mem/shm_mem.c @@ -94,7 +94,7 @@ inline static void* sh_realloc(void* p, unsigned int size) #ifdef DBG_QM_MALLOC void* _shm_resize( void* p, unsigned int s, const char* file, const char* func, - int line) + int line, const char *mname) #else void* _shm_resize( void* p , unsigned int s) #endif diff --git a/mem/shm_mem.h b/mem/shm_mem.h index 35d6503019b..f170bd97500 100644 --- a/mem/shm_mem.h +++ b/mem/shm_mem.h @@ -211,41 +211,41 @@ void shm_mem_destroy(void); #include "src_loc.h" #define shm_malloc_unsafe(_size ) \ - MY_MALLOC(shm_block, (_size), _SRC_LOC_, _SRC_FUNCTION_, _SRC_LINE_ ) + MY_MALLOC(shm_block, (_size), _SRC_LOC_, _SRC_FUNCTION_, _SRC_LINE_, _SRC_MODULE_) inline static void* _shm_malloc(unsigned int size, - const char *file, const char *function, int line ) + const char *file, const char *function, int line, const char *mname) { void *p; shm_lock(); - p=MY_MALLOC(shm_block, size, file, function, line ); + p=MY_MALLOC(shm_block, size, file, function, line, mname); shm_unlock(); return p; } inline static void* _shm_realloc(void *ptr, unsigned int size, - const char* file, const char* function, int line ) + const char* file, const char* function, int line, const char *mname) { void *p; shm_lock(); - p=MY_REALLOC(shm_block, ptr, size, file, function, line); + p=MY_REALLOC(shm_block, ptr, size, file, function, line, mname); shm_unlock(); return p; } #define shm_malloc( _size ) _shm_malloc((_size), \ - _SRC_LOC_, _SRC_FUNCTION_, _SRC_LINE_ ) + _SRC_LOC_, _SRC_FUNCTION_, _SRC_LINE_ , _SRC_MODULE_) #define shm_realloc( _ptr, _size ) _shm_realloc( (_ptr), (_size), \ - _SRC_LOC_, _SRC_FUNCTION_, _SRC_LINE_ ) + _SRC_LOC_, _SRC_FUNCTION_, _SRC_LINE_, _SRC_MODULE_) #define shm_free_unsafe( _p ) \ - MY_FREE( shm_block, (_p), _SRC_LOC_, _SRC_FUNCTION_, _SRC_LINE_ ) + MY_FREE( shm_block, (_p), _SRC_LOC_, _SRC_FUNCTION_, _SRC_LINE_, _SRC_MODULE_) #define shm_free(_p) \ do { \ @@ -257,9 +257,9 @@ do { \ void* _shm_resize(void* ptr, unsigned int size, const char* f, const char* fn, - int line); + int line, const char *mname); #define shm_resize(_p, _s ) _shm_resize((_p), (_s), \ - _SRC_LOC_, _SRC_FUNCTION_, _SRC_LINE_ ) + _SRC_LOC_, _SRC_FUNCTION_, _SRC_LINE_, _SRC_MODULE_) /*#define shm_resize(_p, _s ) shm_realloc( (_p), (_s))*/ diff --git a/mem/src_loc.h b/mem/src_loc.h index 33c2df695c5..af004464857 100644 --- a/mem/src_loc.h +++ b/mem/src_loc.h @@ -68,7 +68,7 @@ # ifdef MOD_NAME # define _SRC_MODULE_ MOD_NAME # else -# define _SRC_MODULE_ "" +# define _SRC_MODULE_ "core" # endif /* MOD_NAME */ #endif /* _SRC_MODULE_ */ diff --git a/mem/tlsf_malloc.c b/mem/tlsf_malloc.c index edf6a69ecd3..c5b2b640172 100644 --- a/mem/tlsf_malloc.c +++ b/mem/tlsf_malloc.c @@ -108,6 +108,7 @@ tlsf_static_assert(ALIGN_SIZE == SMALL_BLOCK_SIZE / SL_INDEX_COUNT); typedef struct { const char* file; const char* func; + const char* mname; unsigned int line; } alloc_info_t; #endif @@ -598,7 +599,7 @@ static block_header_t* block_locate_free(control_t* control, size_t size) } #ifdef DBG_TLSF_MALLOC static void* block_prepare_used(control_t* control, block_header_t* block, size_t size, - const char *file, const char *function, unsigned long line) + const char *file, const char *function, unsigned long line, const char *mname) #else static void* block_prepare_used(control_t* control, block_header_t* block, size_t size) #endif @@ -617,6 +618,7 @@ static void* block_prepare_used(control_t* control, block_header_t* block, size_ block->alloc_info.file = file; block->alloc_info.func = function; block->alloc_info.line = line; + block->alloc_info.mname = mname; #endif } return p; @@ -952,7 +954,7 @@ pool_t tlsf_get_pool(tlsf_t tlsf) #ifdef DBG_TLSF_MALLOC void* tlsf_malloc(tlsf_t tlsf, size_t size, - const char *file, const char *function, unsigned int line) + const char *file, const char *function, unsigned int line, const char *mname) #else void* tlsf_malloc(tlsf_t tlsf, size_t size) #endif @@ -964,7 +966,7 @@ void* tlsf_malloc(tlsf_t tlsf, size_t size) void *ptr; MDBG("tlsf_malloc(%p, %zu) called from %s: %s(%u)\n", tlsf, size, file, function, line); - ptr = block_prepare_used(control, block, adjust, file, function, line); + ptr = block_prepare_used(control, block, adjust, file, function, line, mname); MDBG("tlsf_malloc(%p, %zu) returns address %p \n", tlsf, size, ptr); return ptr; @@ -975,7 +977,7 @@ void* tlsf_malloc(tlsf_t tlsf, size_t size) #ifdef DBG_TLSF_MALLOC void tlsf_free(tlsf_t tlsf, void* ptr, - const char *file, const char *function, unsigned int line) + const char *file, const char *function, unsigned int line, const char *mname) #else void tlsf_free(tlsf_t tlsf, void* ptr) #endif @@ -1013,6 +1015,7 @@ void tlsf_free(tlsf_t tlsf, void* ptr) block->alloc_info.file = file; block->alloc_info.func = function; block->alloc_info.line = line; + block->alloc_info.mname = mname; #endif block_mark_as_free(block); block = block_merge_prev(control, block); @@ -1042,7 +1045,7 @@ void tlsf_free(tlsf_t tlsf, void* ptr) */ #ifdef DBG_TLSF_MALLOC void* tlsf_realloc(tlsf_t tlsf, void* ptr, size_t size, - const char *file, const char *function, unsigned int line) + const char *file, const char *function, unsigned int line, const char *mname) #else void* tlsf_realloc(tlsf_t tlsf, void* ptr, size_t size) #endif @@ -1054,7 +1057,7 @@ void* tlsf_realloc(tlsf_t tlsf, void* ptr, size_t size) if (ptr && size == 0) { #ifdef DBG_TLSF_MALLOC - tlsf_free(tlsf, ptr, file, function, line); + tlsf_free(tlsf, ptr, file, function, line, mname); #else tlsf_free(tlsf, ptr); #endif @@ -1063,7 +1066,7 @@ void* tlsf_realloc(tlsf_t tlsf, void* ptr, size_t size) else if (!ptr) { #ifdef DBG_TLSF_MALLOC - p = tlsf_malloc(tlsf, size, file, function, line); + p = tlsf_malloc(tlsf, size, file, function, line, mname); #else p = tlsf_malloc(tlsf, size); #endif @@ -1086,7 +1089,7 @@ void* tlsf_realloc(tlsf_t tlsf, void* ptr, size_t size) if (adjust > cursize && (!block_is_free(next) || adjust > combined)) { #ifdef DBG_TLSF_MALLOC - p = tlsf_malloc(tlsf, size, file, function, line); + p = tlsf_malloc(tlsf, size, file, function, line, mname); #else p = tlsf_malloc(tlsf, size); #endif @@ -1095,7 +1098,7 @@ void* tlsf_realloc(tlsf_t tlsf, void* ptr, size_t size) const size_t minsize = tlsf_min(cursize, size); memcpy(p, ptr, minsize); #ifdef DBG_TLSF_MALLOC - tlsf_free(tlsf, ptr, file, function, line); + tlsf_free(tlsf, ptr, file, function, line, mname); #else tlsf_free(tlsf, ptr); #endif @@ -1189,16 +1192,6 @@ void tlsf_status(tlsf_t pool) } #ifdef DBG_TLSF_MALLOC -typedef struct _mem_counter{ - const char *file; - const char *func; - unsigned long line; - - unsigned long size; - int count; - - struct _mem_counter *next; -} mem_counter; static mem_counter* get_mem_counter(mem_counter **root, block_header_t* f) { @@ -1211,6 +1204,7 @@ static mem_counter* get_mem_counter(mem_counter **root, block_header_t* f) x = malloc(sizeof(mem_counter)); x->file = f->alloc_info.file; x->func = f->alloc_info.func; + x->mname= f->alloc_info.mname; x->line = f->alloc_info.line; x->count = 0; x->size = 0; @@ -1257,13 +1251,68 @@ void tlsf_sums(tlsf_t pool) LOG_(DEFAULT_FACILITY, memlog, "tlsf_sums: ", "-----------------------------\n"); } + +void tlsf_mod_get_stats(tlsf_t pool, void **rootp) +{ + if (!rootp) { + return ; + } + + LM_DBG("get tlsf memory statistics\n"); + + mem_counter **root = (mem_counter **) rootp; + block_header_t* block = pool + tlsf_size() - sizeof(block_header_t*); + mem_counter *x; + + while (block && !block_is_last(block)) + { + if(!block_is_free(block)) { + x = get_mem_counter(root, block); + x->count++; + x->size+=block_size(block); + } + + block = block_next(block); + } +} + +void tlsf_mod_free_stats(void *rootp) +{ + if (!rootp) { + return ; + } + + LM_DBG("free tlsf memory statistics\n"); + + mem_counter *root = (mem_counter *) rootp; + mem_counter *x; + x = root; + while (x) { + root = x->next; + free(x); + x = root; + } +} + #else void tlsf_sums(tlsf_t pool) {} + +void tlsf_mod_get_stats(tlsf_t pool, void **rootp) +{ + LM_WARN("Enable DBG_TLSF_MALLOC for getting statistics\n"); + return ; +} + +void tlsf_mod_free_stats(void *rootp) +{ + LM_WARN("Enable DBG_TLSF_MALLOC for freeing statistics\n"); + return ; +} #endif /* defined DBG_TLSF_MALLOC */ /*memory manager core api*/ -static char *_tlsf_mem_name = "f_malloc"; +static char *_tlsf_mem_name = "tlsf_malloc"; /* PKG - private memory API*/ static void *_tlsf_pkg_pool = 0; @@ -1309,6 +1358,8 @@ int tlsf_malloc_init_pkg_manager(void) ma.xavailable = tlsf_available; ma.xsums = tlsf_sums; ma.xdestroy = tlsf_malloc_destroy_pkg_manager; + ma.xstats = tlsf_mod_get_stats; + ma.xfstats = tlsf_mod_free_stats; return pkg_init_api(&ma); } @@ -1320,38 +1371,38 @@ static tlsf_t _tlsf_shm_block = 0; /*SHM wrappers to sync the access to memory block*/ #ifdef DBG_TLSF_MALLOC void* tlsf_shm_malloc(void* tlsfmp, unsigned long size, - const char* file, const char* func, unsigned int line) + const char* file, const char* func, unsigned int line, const char* mname) { void *r; shm_lock(); - r = tlsf_malloc(tlsfmp, size, file, func, line); + r = tlsf_malloc(tlsfmp, size, file, func, line, mname); shm_unlock(); return r; } void* tlsf_shm_realloc(void* tlsfmp, void* p, unsigned long size, - const char* file, const char* func, unsigned int line) + const char* file, const char* func, unsigned int line, const char* mname) { void *r; shm_lock(); - r = tlsf_realloc(tlsfmp, p, size, file, func, line); + r = tlsf_realloc(tlsfmp, p, size, file, func, line, mname); shm_unlock(); return r; } void* tlsf_shm_resize(void* tlsfmp, void* p, unsigned long size, - const char* file, const char* func, unsigned int line) + const char* file, const char* func, unsigned int line, const char* mname) { void *r; shm_lock(); - if(p) tlsf_free(tlsfmp, p, file, func, line); - r = tlsf_malloc(tlsfmp, size, file, func, line); + if(p) tlsf_free(tlsfmp, p, file, func, line, mname); + r = tlsf_malloc(tlsfmp, size, file, func, line, mname); shm_unlock(); return r; } void tlsf_shm_free(void* tlsfmp, void* p, const char* file, const char* func, - unsigned int line) + unsigned int line, const char* mname) { shm_lock(); - tlsf_free(tlsfmp, p, file, func, line); + tlsf_free(tlsfmp, p, file, func, line, mname); shm_unlock(); } #else @@ -1457,6 +1508,8 @@ int tlsf_malloc_init_shm_manager(void) ma.xavailable = tlsf_shm_available; ma.xsums = tlsf_shm_sums; ma.xdestroy = tlsf_malloc_destroy_shm_manager; + ma.xstats = tlsf_mod_get_stats; + ma.xfstats = tlsf_mod_free_stats; if(shm_init_api(&ma)<0) { LM_ERR("cannot initialize the core shm api\n"); diff --git a/mem/tlsf_malloc.h b/mem/tlsf_malloc.h index 0c6c1f848c2..97e962a5990 100644 --- a/mem/tlsf_malloc.h +++ b/mem/tlsf_malloc.h @@ -47,11 +47,11 @@ void tlsf_remove_pool(tlsf_t tlsf, pool_t pool); /* malloc/memalign/realloc/free replacements. */ #ifdef DBG_TLSF_MALLOC void* tlsf_malloc(tlsf_t tlsf, size_t size, - const char *file, const char *function, unsigned int line); + const char *file, const char *function, unsigned int line, const char *mname); void* tlsf_realloc(tlsf_t tlsf, void* ptr, size_t size, - const char *file, const char *function, unsigned int line); + const char *file, const char *function, unsigned int line, const char *mname); void tlsf_free(tlsf_t tlsf, void* ptr, - const char *file, const char *function, unsigned int line); + const char *file, const char *function, unsigned int line, const char *mname); #else void* tlsf_malloc(tlsf_t tlsf, size_t bytes); void* tlsf_realloc(tlsf_t tlsf, void* ptr, size_t size); @@ -80,6 +80,20 @@ void tlsf_meminfo(tlsf_t pool, struct mem_info *info); void tlsf_status(tlsf_t pool); void tlsf_sums(tlsf_t pool); size_t tlsf_available(tlsf_t pool); +void tlsf_mod_get_stats(tlsf_t pool, void **root); +void tlsf_mod_free_stats(void *root); + +typedef struct _mem_counter{ + const char *file; + const char *func; + const char *mname; + unsigned long line; + + unsigned long size; + int count; + + struct _mem_counter *next; +} mem_counter; #if defined(__cplusplus) }; diff --git a/modules/ctl/binrpc_run.c b/modules/ctl/binrpc_run.c index c4b72977a07..3bd8b4ad685 100644 --- a/modules/ctl/binrpc_run.c +++ b/modules/ctl/binrpc_run.c @@ -36,8 +36,18 @@ rpc->scan (default: not set) */ int autoconvert=0; +#ifdef DBG_SR_MEMORY +/** + * note that if you get some error(overflow) when "kamcmd mod.stats all all" you might + * need to increase these values + **/ +int binrpc_max_body_size = 8; /* multiplied by 1024 in mod init */ +int binrpc_struct_max_body_size = 4; /* multiplied by 1024 in mod init */ +#else int binrpc_max_body_size = 4; /* multiplied by 1024 in mod init */ -int binrpc_struct_max_body_size = 1; /* multiplied by 1024 in mod init */ +int binrpc_struct_max_body_size = 1; /* multiplied by 1024 in mod init */ +#endif + #define BINRPC_MAX_BODY binrpc_max_body_size /* maximum body for send */ #define STRUCT_MAX_BODY binrpc_struct_max_body_size #define MAX_MSG_CHUNKS 96 diff --git a/modules/kex/doc/kex_admin.xml b/modules/kex/doc/kex_admin.xml index 1640acf0996..e73723f3b6e 100644 --- a/modules/kex/doc/kex_admin.xml +++ b/modules/kex/doc/kex_admin.xml @@ -712,6 +712,82 @@ resetdebug(); &sercmd; stats.reset_statistics shmem: fwd_requests fwd_replies + +
+ + <function moreinfo="none">mod.stats module_name/all pkg/shm/all</function> + + + Print private(pkg) or shared(shm) memory currently allocated a given module or by all modules. + + + NOTE: Processing is done only when the command is issued and involves iterating + throug the list of memory fragments and printing details about them. + + + NOTE: Only the module functions that directly calls shm_alloc or + pkg_alloc are taken into consideration. + + The firt parameter can be: + + + + module_name - print statistics for specific module. + + + + + all - print statistics for all modules that uses memory. + + + + + The second parameter can be: + + + + pkg - print private memory statistics. + + + + + shm - print shared memory statistics. + + + + + all - print both private and shared memory statistics. + + + + + Examples: + + + &sercmd; mod.stats core all + &sercmd; mod.stats userblacklist shm + &sercmd; mod.stats kex pkg + &sercmd; mod.stats all all + + + Output: + + +Module: kex +{ + // this is the pkg zone of the module + // function_name(line_where_pkg_malloc_was_called): size_alloc'ed_by_pkg_malloc + init_mi_uptime(74): 56 + Total: 56 +} +{ + // this is the shm zone of the module + // function_name(line_where_shm_malloc_was_called): size_alloc'ed_by_shm_malloc + pkg_proc_stats_init(79): 864 + Total: 864 +} + +
diff --git a/modules/kex/kex_mod.c b/modules/kex/kex_mod.c index 1a5f4b1b555..22af64bf99d 100644 --- a/modules/kex/kex_mod.c +++ b/modules/kex/kex_mod.c @@ -40,6 +40,7 @@ #include "mi_core.h" #include "core_stats.h" #include "pkg_stats.h" +#include "mod_stats.h" MODULE_VERSION @@ -145,6 +146,11 @@ static int mod_init(void) #endif register_pkg_proc_stats(); pkg_proc_stats_init_rpc(); + + register_mod_stats(); + mod_stats_init(); + mod_stats_init_rpc(); + return 0; } @@ -168,6 +174,7 @@ static int child_init(int rank) static void destroy(void) { pkg_proc_stats_destroy(); + mod_stats_destroy(); return; } diff --git a/modules/kex/mod_stats.c b/modules/kex/mod_stats.c new file mode 100644 index 00000000000..e324957ff2c --- /dev/null +++ b/modules/kex/mod_stats.c @@ -0,0 +1,282 @@ +/* + * Copyright (C) 2010 Daniel-Constantin Mierla (asipto.com) + * + * This file is part of Kamailio, a free SIP server. + * + * Kamailio 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 of the License, or + * (at your option) any later version. + * + * Kamailio 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/*! + * \file + * \brief KEX :: Kamailio private memory pool statistics + * \ingroup kex + */ + +#include +#include +#include +#include + +#include "../../dprint.h" +#include "../../ut.h" +#include "../../pt.h" +#include "../../sr_module.h" +#include "../../events.h" +#include "../../mem/f_malloc.h" +#include "../../rpc.h" +#include "../../rpc_lookup.h" + +#include "mod_stats.h" + + +#define DBG_MOD_PKG_FLAG 0 +#define DBG_MOD_SHM_FLAG 1 +#define DBG_MOD_ALL_FLAG 2 + +/** + * + */ +int mod_stats_init(void) +{ + return 0; +} + +/** + * + */ +int mod_stats_destroy(void) +{ + return 0; +} + + +/** + * + */ +static int mod_update_pkg_mod_stats_list(void *data) +{ + return 0; +} + + +/** + * + */ +static int mod_update_shm_mod_stats_list(void *data) +{ + return 0; +} + + +/** + * + */ +int register_mod_stats(void) +{ + sr_event_register_cb(SREV_MODULE_PKG_STATS, mod_update_pkg_mod_stats_list); + sr_event_register_cb(SREV_MODULE_SHM_STATS, mod_update_shm_mod_stats_list); + return 0; +} + +/** + * + */ +static const char* rpc_mod_stats_doc[2] = { + "Per module memory statistics", + 0 +}; + +/* test if the current mod info was already printed */ +static int rpc_mod_is_printed_one(mem_counter *stats, mem_counter *current) { + mem_counter *iter = stats; + + while (iter && iter != current) { + if (strcmp(iter->mname, current->mname) == 0) { + return 1; + } + iter = iter->next; + } + + return 0; +} + +/* print memory info for a specific module in a specific stats list */ +static int rpc_mod_print(rpc_t *rpc, void *ctx, const char *mname, + mem_counter *stats) +{ + char buff[128]; + const char *total_str= "Total"; + void *stats_th = NULL; + int total = 0; + mem_counter *iter = stats; + + if (stats == NULL) { + return -1; + } + + if (rpc->add(ctx, "{", &stats_th) < 0) { + rpc->fault(ctx, 500, "Internal error creating struct rpc"); + return -1; + } + + while (iter) { + if (strcmp(mname, iter->mname) == 0) { + sprintf(buff, "%s(%ld)", iter->func, iter->line); + if (rpc->struct_add(stats_th, "d", buff, iter->size) < 0) { + rpc->fault(ctx, 500, "Internal error adding to struct rpc"); + return -1; + } + total += iter->size; + } + iter = iter->next; + } + + if (rpc->struct_add(stats_th, "d", total_str, total) < 0) { + rpc->fault(ctx, 500, "Internal error adding total to struct rpc"); + return -1; + } + + return total; +} + +/* print memory info for a specific module */ +static int rpc_mod_print_one(rpc_t *rpc, void *ctx, const char *mname, + mem_counter *pkg_stats, mem_counter *shm_stats, int flag) +{ + if (rpc->rpl_printf(ctx, "Module: %s", mname) < 0) { + rpc->fault(ctx, 500, "Internal error adding module name to ctx"); + return -1; + } + + switch (flag){ + case DBG_MOD_PKG_FLAG: + rpc_mod_print(rpc, ctx, mname, pkg_stats); + break; + case DBG_MOD_SHM_FLAG: + rpc_mod_print(rpc, ctx, mname, shm_stats); + break; + case DBG_MOD_ALL_FLAG: + rpc_mod_print(rpc, ctx, mname, pkg_stats); + rpc_mod_print(rpc, ctx, mname, shm_stats); + break; + default: + rpc_mod_print(rpc, ctx, mname, pkg_stats); + rpc_mod_print(rpc, ctx, mname, shm_stats); + break; + } + + if (rpc->rpl_printf(ctx, "") < 0) { + rpc->fault(ctx, 500, "Internal error adding module name to ctx"); + return -1; + } + + return 0; +} + +/* print memory info for all modules */ +static int rpc_mod_print_all(rpc_t *rpc, void *ctx, + mem_counter *pkg_stats, mem_counter *shm_stats, int flag) +{ + mem_counter *pkg_iter = pkg_stats; + mem_counter *shm_iter = shm_stats; + + /* print unique module info found in pkg_stats */ + while (pkg_iter) { + if (!rpc_mod_is_printed_one(pkg_stats, pkg_iter)) { + rpc_mod_print_one(rpc, ctx, + pkg_iter->mname, pkg_stats, shm_stats, flag); + } + pkg_iter = pkg_iter->next; + } + + /* print unique module info found in shm_stats and not found in pkg_stats */ + while (shm_iter) { + if (!rpc_mod_is_printed_one(shm_stats, shm_iter) && + !rpc_mod_is_printed_one(pkg_stats, shm_iter)) { + rpc_mod_print_one(rpc, ctx, + shm_iter->mname, pkg_stats, shm_stats, flag); + } + shm_iter = shm_iter->next; + } + return 0; +} + +/** + * + */ +static void rpc_mod_stats(rpc_t *rpc, void *ctx) +{ + int flag = DBG_MOD_ALL_FLAG; + str mname = STR_NULL; + str mtype = STR_NULL; + + mem_counter *pkg_mod_stats_list = NULL; + mem_counter *shm_mod_stats_list = NULL; + + if (rpc->scan(ctx, "*S", &mname) != 1) { + rpc->fault(ctx, 500, "Module name or \"all\" needed"); + return; + } + + if (rpc->scan(ctx, "*S", &mtype) != 1) { + rpc->fault(ctx, 500, "\"pkg\" or \"shm\" or \"all\" needed"); + return; + } + + if (strcmp(mtype.s, "pkg") == 0) { + flag = DBG_MOD_PKG_FLAG; + } else if (strcmp(mtype.s, "shm") == 0) { + flag = DBG_MOD_SHM_FLAG; + } else if (strcmp(mtype.s, "all") == 0) { + flag = DBG_MOD_ALL_FLAG; + } + + pkg_mod_get_stats((void **)&pkg_mod_stats_list); + shm_mod_get_stats((void **)&shm_mod_stats_list); + + /* print info about all modules */ + if (strcmp(mname.s, "all") == 0) { + rpc_mod_print_all(rpc, ctx, pkg_mod_stats_list, shm_mod_stats_list, flag); + + /* print info about a particular module */ + } else { + rpc_mod_print_one(rpc, ctx, mname.s, pkg_mod_stats_list, shm_mod_stats_list, flag); + } + + pkg_mod_free_stats(pkg_mod_stats_list); + shm_mod_free_stats(shm_mod_stats_list); +} + +/** + * + */ +rpc_export_t kex_mod_rpc[] = { + {"mod.stats", rpc_mod_stats, rpc_mod_stats_doc, RET_ARRAY}, + {0, 0, 0, 0} +}; + +/** + * + */ +int mod_stats_init_rpc(void) +{ + if (rpc_register_array(kex_mod_rpc)!=0) + { + LM_ERR("failed to register RPC commands\n"); + return -1; + } + return 0; +} diff --git a/modules/kex/mod_stats.h b/modules/kex/mod_stats.h new file mode 100644 index 00000000000..3e7007a85a4 --- /dev/null +++ b/modules/kex/mod_stats.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2010 Daniel-Constantin Mierla (asipto.com) + * + * This file is part of Kamailio, a free SIP server. + * + * Kamailio 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 of the License, or + * (at your option) any later version. + * + * Kamailio 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/*! + * \file + * \brief KEX :: Kamailio private memory pool statistics + * \ingroup kex + */ + + +#ifndef _MOD_STATS_H_ +#define _MOD_STATS_H_ + +int mod_stats_init(void); +int mod_stats_destroy(void); +int register_mod_stats(void); +int mod_stats_init_rpc(void); + +#endif /*_MOD_STATS_H_*/