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_*/