diff --git a/Makefile.modules b/Makefile.modules index c86834903f..df6c2c5bc5 100644 --- a/Makefile.modules +++ b/Makefile.modules @@ -40,6 +40,6 @@ CFLAGS:=$(MOD_CFLAGS) LDFLAGS:=$(MOD_LDFLAGS) endif -CFLAGS+=-DMOD_NAME='"$(MOD_NAME)"' +CFLAGS+=-DMOD_NAME='$(MOD_NAME)' include ../../Makefile.rules diff --git a/Makefile.rules b/Makefile.rules index 5f3192aab6..465768c413 100644 --- a/Makefile.rules +++ b/Makefile.rules @@ -46,6 +46,23 @@ ifeq (,$(FASTER)) endif $(Q)$(CC) $(CFLAGS) $(DEFS) -c $< -o $@ +.PHONY: generate-mem-stats +generate-mem-stats: + -@rm -f mem/mem_stats.c + @echo "/* This file is auto-generated by running 'make generate-mem-stats' */" >> mem/mem_stats.c + @echo "/* You should NOT edit this file manually */" >> mem/mem_stats.c + @echo "unsigned long core_mem_stat; /* core statistic */" >> mem/mem_stats.c + @find modules/ -name "[Mm]akefile" -exec grep NAME= {} \; \ + | awk 'BEGIN { FS = "[=\. ]" } {print "unsigned long " $$(NF-1) "_mem_stat;"}' >> mem/mem_stats.c + -@rm -f mem/mem_stats.h + @echo "/* This file is auto-generated by running 'make generate-mem-stats' */" >> mem/mem_stats.h + @echo "/* You should NOT edit this file manually */" >> mem/mem_stats.h + @ echo "#ifndef __MEM_STAT_H_\n#define __MEM_STAT_H_" >> mem/mem_stats.h + @echo "extern unsigned long core_mem_stat; /* core statistic */" >> mem/mem_stats.h + @find modules/ -name "[Mm]akefile" -exec grep NAME= {} \; \ + | awk 'BEGIN { FS = "[=\. ]" } {print "extern unsigned long " $$(NF-1) "_mem_stat;"}' >> mem/mem_stats.h + @echo "#endif" >> mem/mem_stats.h + .PHONY: all all: $(NAME) modules diff --git a/cfg.lex b/cfg.lex index 04989ac49e..5efdb811be 100644 --- a/cfg.lex +++ b/cfg.lex @@ -294,6 +294,7 @@ LOGFACILITY log_facility LOGNAME log_name AVP_ALIASES avp_aliases LISTEN listen +MEMGROUP mem-group ALIAS alias AUTO_ALIASES auto_aliases DNS dns @@ -565,6 +566,7 @@ IMPORTFILE "import_file" {LOGNAME} { yylval.strval=yytext; return LOGNAME; } {AVP_ALIASES} { yylval.strval=yytext; return AVP_ALIASES; } {LISTEN} { count(); yylval.strval=yytext; return LISTEN; } +{MEMGROUP} { count(); yylval.strval=yytext; return MEMGROUP; } {ALIAS} { count(); yylval.strval=yytext; return ALIAS; } {AUTO_ALIASES} { count(); yylval.strval=yytext; return AUTO_ALIASES; } {DNS} { count(); yylval.strval=yytext; return DNS; } diff --git a/cfg.y b/cfg.y index ea4c46a2f0..4395a4a857 100644 --- a/cfg.y +++ b/cfg.y @@ -108,6 +108,10 @@ #include "net/trans.h" #include "config.h" +#ifdef SHM_EXTRA_STATS +#include "mem/module_info.h" +#endif + #ifdef DEBUG_DMALLOC #include #endif @@ -140,12 +144,22 @@ action_elem_t *a_tmp; static inline void warn(char* s); static struct socket_id* mk_listen_id(char*, enum sip_protos, int); static struct socket_id* set_listen_id_adv(struct socket_id *, char *, int); +static struct multi_str *new_string(char *s); extern int line; extern int column; extern int startcolumn; extern char *finame; +#ifndef SHM_EXTRA_STATS +struct multi_str{ + char *s; + struct multi_str* next; +}; +#else +static struct multi_str *tmp_mod; +#endif + #define get_cfg_file_name \ ((finame) ? finame : cfg_file ? cfg_file : "default") @@ -196,6 +210,7 @@ extern char *finame; struct ip_addr* ipaddr; struct socket_id* sockid; struct _pv_spec *specval; + struct multi_str* multistr; } /* terminals */ @@ -306,6 +321,7 @@ extern char *finame; %token LOGNAME %token AVP_ALIASES %token LISTEN +%token MEMGROUP %token ALIAS %token AUTO_ALIASES %token DNS @@ -462,6 +478,7 @@ extern char *finame; %type route_name %type route_param %type folded_string +%type multi_string /* * since "if_cmd" is inherently ambiguous, @@ -595,6 +612,10 @@ listen_def: phostport { $$=$1; } any_proto: ANY { $$=PROTO_NONE; } | proto { $$=$1; } +multi_string: STRING { $$=new_string($1); } + | STRING multi_string { $$=new_string($1); $$->next=$2; } + ; + blst_elem: LPAREN any_proto COMMA ipnet COMMA port COMMA STRING RPAREN { s_tmp.s=$8; s_tmp.len=strlen($8); @@ -884,6 +905,46 @@ assign_stm: DEBUG EQUAL snumber { | LISTEN EQUAL error { yyerror("ip address or hostname " "expected (use quotes if the hostname includes" " config keywords)"); } + | MEMGROUP EQUAL STRING COLON multi_string { + /* convert STIRNG ($3) to an ID */ + /* update the memstats type for each module */ + #ifndef SHM_EXTRA_STATS + LM_CRIT("SHM_EXTRA_STATS not defined"); + YYABORT; + #else + + #ifdef SHM_SHOW_DEFAULT_GROUP + if(strcmp($3, "default") == 0){ + LM_CRIT("default group name is not allowed"); + YYABORT; + } + #endif + + for(tmp_mod = mod_names; tmp_mod; tmp_mod=tmp_mod->next){ + if(strcmp($3, tmp_mod->s) == 0){ + LM_CRIT("The same mem-group name is used twice: [%s] [%s]\n", $3, tmp_mod->s); + YYABORT; + } + } + + tmp_mod = pkg_malloc(sizeof(struct multi_str)); + if(!tmp_mod){ + LM_CRIT("out of pkg memory"); + YYABORT; + } + + tmp_mod->s = $3; + tmp_mod->next = mod_names; + mod_names = tmp_mod; + for (tmp_mod = $5; tmp_mod; tmp_mod = tmp_mod->next){ + if(set_mem_idx(tmp_mod->s, mem_free_idx)){ + YYABORT; + } + } + mem_free_idx++; + #endif + } + | MEMGROUP EQUAL STRING COLON error { yyerror("invalid or no module specified"); } | ALIAS EQUAL id_lst { for(lst_tmp=$3; lst_tmp; lst_tmp=lst_tmp->next) add_alias(lst_tmp->name, strlen(lst_tmp->name), @@ -2689,6 +2750,18 @@ static struct socket_id* mk_listen_id(char* host, enum sip_protos proto, return l; } +static struct multi_str *new_string(char *s) +{ + struct multi_str *ms = pkg_malloc(sizeof(struct multi_str)); + if (!ms) { + LM_CRIT("cfg. parser: out of memory.\n"); + }else{ + ms->s = s; + ms->next = NULL; + } + return ms; +} + static struct socket_id* set_listen_id_adv(struct socket_id* sock, char *adv_name, int adv_port) diff --git a/dprint.h b/dprint.h index 6a75f793ea..0c83422895 100644 --- a/dprint.h +++ b/dprint.h @@ -88,7 +88,7 @@ #define DPRINT_LEV L_ERR #ifndef MOD_NAME - #define MOD_NAME "core" + #define MOD_NAME core #endif #ifndef NO_DEBUG @@ -203,8 +203,9 @@ static inline char* dp_time(void) #else /* NO_LOG */ #ifdef __SUNPRO_C - - #define LOG_PREFIX MOD_NAME ": " + #define LOG_PREFIX_UTIL2(_n) #_n + #define LOG_PREFIX_UTIL(_n) LOG_PREFIX_UTIL2(_n) + #define LOG_PREFIX LOG_PREFIX_UTIL(MOD_NAME) ": " #define MY_DPRINT( ...) \ dprint( LOG_PREFIX __VA_ARGS__ ) \ @@ -324,7 +325,9 @@ static inline char* dp_time(void) #else /*SUN_PRO_C*/ - #define LOG_PREFIX MOD_NAME ":%s: " + #define LOG_PREFIX_UTIL2(_n) #_n + #define LOG_PREFIX_UTIL(_n) LOG_PREFIX_UTIL2(_n) + #define LOG_PREFIX LOG_PREFIX_UTIL(MOD_NAME) ":%s: " #define MY_DPRINT( _prefix, _fmt, args...) \ dprint( _prefix LOG_PREFIX _fmt, dp_time(), \ diff --git a/mem/f_malloc.c b/mem/f_malloc.c index 9e4587982f..8926ebcc61 100644 --- a/mem/f_malloc.c +++ b/mem/f_malloc.c @@ -50,7 +50,7 @@ #define FRAG_NEXT(f) \ ((struct fm_frag*)((char*)(f)+sizeof(struct fm_frag)+(f)->size )) -#define FRAG_OVERHEAD (sizeof(struct fm_frag)) + /* ROUNDTO= 2^k so the following works */ @@ -84,6 +84,12 @@ #define F_MALLOC_DEFRAG_LIMIT (F_MALLOC_LARGE_LIMIT * 5) #define F_MALLOC_DEFRAG_PERCENT 5 +inline unsigned long frag_size(void* p){ + if(!p) + return 0; + return (((struct fm_frag*) ((char*)p-sizeof(struct fm_frag)))->size); +} + static inline void free_minus(struct fm_block* qm, unsigned long size ) { @@ -240,6 +246,7 @@ void fm_split_frag(struct fm_block* qm, struct fm_frag* frag, /* init malloc and return a fm_block*/ struct fm_block* fm_malloc_init(char* address, unsigned long size) + { char* start; char* end; @@ -271,12 +278,12 @@ struct fm_block* fm_malloc_init(char* address, unsigned long size) qm=(struct fm_block*)start; memset(qm, 0, sizeof(struct fm_block)); qm->size=size; - #if defined(DBG_F_MALLOC) || defined(STATISTICS) qm->used=size-init_overhead; qm->real_used=size; qm->max_real_used=init_overhead; + qm->fragments = 0; #endif qm->first_frag=(struct fm_frag*)(start+ROUNDUP(sizeof(struct fm_block))); @@ -404,6 +411,7 @@ void* fm_malloc(struct fm_block* qm, unsigned long size) #if defined(DBG_F_MALLOC) || defined(STATISTICS) if (qm->max_real_usedreal_used) qm->max_real_used=qm->real_used; + qm->fragments += 1; #endif pkg_threshold_check(); @@ -467,6 +475,9 @@ void fm_free(struct fm_block* qm, void* p) no_join: fm_insert_free(qm, f); +#if defined(DBG_F_MALLOC) || defined(STATISTICS) + qm->fragments -= 1; +#endif pkg_threshold_check(); } diff --git a/mem/f_malloc.h b/mem/f_malloc.h index ad91ba98aa..f9e41cc308 100644 --- a/mem/f_malloc.h +++ b/mem/f_malloc.h @@ -71,6 +71,8 @@ * ROUNDTO from bucket to bucket * +1 .... end - size = 2^k, big buckets */ +#define FRAG_OVERHEAD (sizeof(struct fm_frag)) + struct fm_frag{ unsigned long size; union{ @@ -95,7 +97,7 @@ struct fm_block{ unsigned long size; /* total size */ unsigned long large_space; unsigned long large_limit; - + unsigned long fragments; /* number of fragments in use */ #if defined(DBG_F_MALLOC) || defined(STATISTICS) unsigned long used; /* alloc'ed size*/ unsigned long real_used; /* used+malloc overhead*/ @@ -109,7 +111,7 @@ struct fm_block{ }; - +inline unsigned long frag_size(void* p); struct fm_block* fm_malloc_init(char* address, unsigned long size); #ifdef DBG_F_MALLOC @@ -160,12 +162,7 @@ static inline unsigned long fm_get_max_real_used(struct fm_block* qm) } static inline unsigned long fm_get_frags(struct fm_block* qm) { - unsigned long frags; - unsigned int r; - for(r=0,frags=0;rfree_hash[r].no; - } - return frags; + return qm->fragments; } #endif /*STATISTICS*/ diff --git a/mem/hp_malloc.c b/mem/hp_malloc.c index 8bea88ae20..2c5e401fa7 100644 --- a/mem/hp_malloc.c +++ b/mem/hp_malloc.c @@ -129,6 +129,12 @@ inline static unsigned long big_hash_idx(unsigned long s) return idx; } +inline unsigned long frag_size(void* p){ + if(!p) + return 0; + return ((struct hp_frag*) ((char*)p - sizeof(struct hp_frag)))->size; +} + static inline void hp_frag_attach(struct hp_block *hpb, struct hp_frag *frag) { struct hp_frag **f; diff --git a/mem/hp_malloc.h b/mem/hp_malloc.h index 54d005a9ac..ebf991fc20 100644 --- a/mem/hp_malloc.h +++ b/mem/hp_malloc.h @@ -191,6 +191,8 @@ struct hp_block { struct hp_frag_lnk free_hash[HP_HASH_SIZE + HP_EXTRA_HASH_SIZE]; }; +inline unsigned long frag_size(void* p); + struct hp_block *hp_pkg_malloc_init(char *addr, unsigned long size); struct hp_block *hp_shm_malloc_init(char *addr, unsigned long size); diff --git a/mem/module_info.c b/mem/module_info.c new file mode 100644 index 0000000000..71eafbc247 --- /dev/null +++ b/mem/module_info.c @@ -0,0 +1,62 @@ +#include +#include + +#include "module_info.h" +#include "../dprint.h" +#include "shm_mem.h" + +char buff[60]; + + +unsigned int mem_free_idx = 1; +struct multi_str* mod_names = NULL; +void* main_handle = NULL; +volatile struct module_info* memory_mods_stats = NULL; +int core_index; + +int set_mem_idx(char* mod_name, int mem_free_idx){ + + int *var; + if(!main_handle){ + main_handle = dlopen(NULL, RTLD_LAZY); + if(!main_handle){ + LM_CRIT("could not load main binary handle\n"); + return -1; + } + } + + if(strlen(mod_name) == 4 && (strncmp("core", mod_name, 4) == 0)) + core_index = mem_free_idx; + + strcpy(buff, mod_name); + strcat(buff, STAT_SUFIX); + + var = (int*) dlsym(main_handle, buff); + + if(!var){ + LM_CRIT("The module %s was not found, be sure it is the same as the NAME variable from the module's Makefile" + "(without .so) and run 'make generate-mem-stat'\n", mod_name); + return -1; + } + + *var = mem_free_idx; + LM_INFO("changed module variable %s = %d\n", buff, *var); + + return 0; +} + +inline void update_module_stats(long mem_used, long real_used, int frags, int group_idx){ + if(mem_free_idx == 1) + return; +#ifdef SHM_SHOW_DEFAULT_GROUP + update_stat(memory_mods_stats[group_idx].fragments, frags); + update_stat(memory_mods_stats[group_idx].memory_used, mem_used); + update_stat(memory_mods_stats[group_idx].real_used, real_used); +#else + if(group_idx == 0) + return; + update_stat(memory_mods_stats[group_idx - 1].fragments, frags); + update_stat(memory_mods_stats[group_idx - 1].memory_used, mem_used); + update_stat(memory_mods_stats[group_idx - 1].real_used, real_used); +#endif +} \ No newline at end of file diff --git a/mem/module_info.h b/mem/module_info.h new file mode 100644 index 0000000000..32cb1a81bc --- /dev/null +++ b/mem/module_info.h @@ -0,0 +1,30 @@ +#ifndef _MODULE_INFO__ +#define _MODULE_INFO__ + +#include "../statistics.h" + +#define STAT_SUFIX "_mem_stat" +#define STAT_PREFIX "shmem_group_" +#define STAT_PREFIX_LEN 12 + +extern struct multi_str* mod_names; +extern unsigned int mem_free_idx; +extern void* main_handle; +extern volatile struct module_info* memory_mods_stats; +extern int core_index; + +struct module_info{ + stat_var* fragments; + stat_var* memory_used; + stat_var* real_used; +}; + +struct multi_str{ + char *s; + struct multi_str* next; +}; + +int set_mem_idx(char* mod_name, int mem_free_idx); + +void update_module_stats(long mem_used, long real_used, int frags, int group_idx); +#endif \ No newline at end of file diff --git a/mem/q_malloc.c b/mem/q_malloc.c index fdf3ec6955..5c0152709b 100644 --- a/mem/q_malloc.c +++ b/mem/q_malloc.c @@ -64,9 +64,6 @@ ((struct qm_frag_end*)((char*)(f)-sizeof(struct qm_frag_end))) -#define FRAG_OVERHEAD (sizeof(struct qm_frag)+sizeof(struct qm_frag_end)) - - #define ROUNDTO_MASK (~((unsigned long)ROUNDTO-1)) #define ROUNDUP(s) (((s)+(ROUNDTO-1))&ROUNDTO_MASK) #define ROUNDDOWN(s) ((s)&ROUNDTO_MASK) @@ -132,7 +129,6 @@ inline static unsigned long big_hash_idx(unsigned long s) #define END_CHECK_PATTERN2 0xabcdefed #endif - static void qm_debug_frag(struct qm_block* qm, struct qm_frag* f) { if (f->check!=ST_CHECK_PATTERN){ @@ -165,7 +161,11 @@ static void qm_debug_frag(struct qm_block* qm, struct qm_frag* f) } #endif - +inline unsigned long frag_size(void* p){ + if(!p) + return 0; + return (((struct qm_frag*) ((char*)p-sizeof(struct qm_frag)))->size); +} static inline void qm_insert_free(struct qm_block* qm, struct qm_frag* frag) { @@ -191,7 +191,6 @@ static inline void qm_insert_free(struct qm_block* qm, struct qm_frag* frag) } - /* init malloc and return a qm_block*/ struct qm_block* qm_malloc_init(char* address, unsigned long size) { @@ -227,6 +226,8 @@ struct qm_block* qm_malloc_init(char* address, unsigned long size) memset(qm, 0, sizeof(struct qm_block)); qm->size=size; qm->used=size-init_overhead; + qm->fragments = 0; + qm->real_used=size; qm->max_real_used = 0; size-=init_overhead; @@ -417,6 +418,7 @@ void* qm_malloc(struct qm_block* qm, unsigned long size) qm, size, (char*)f+sizeof(struct qm_frag), f, f->size, list_cntr ); #endif pkg_threshold_check(); + qm->fragments += 1; return (char*)f+sizeof(struct qm_frag); } pkg_threshold_check(); @@ -501,6 +503,7 @@ void qm_free(struct qm_block* qm, void* p) f->line=line; #endif qm_insert_free(qm, f); + qm->fragments -= 1; pkg_threshold_check(); } diff --git a/mem/q_malloc.h b/mem/q_malloc.h index 522d672681..5259d24bfa 100644 --- a/mem/q_malloc.h +++ b/mem/q_malloc.h @@ -64,6 +64,7 @@ #define QM_HASH_SIZE ((unsigned long)(QM_MALLOC_OPTIMIZE/ROUNDTO + \ (sizeof(long)*8-QM_MALLOC_OPTIMIZE_FACTOR)+1)) +#define FRAG_OVERHEAD (sizeof(struct qm_frag)+sizeof(struct qm_frag_end)) /* hash structure: * 0 .... QM_MALLOC_OPTIMIE/ROUNDTO - small buckets, size increases with * ROUNDTO from bucket to bucket @@ -108,6 +109,7 @@ struct qm_block{ unsigned long used; /* alloc'ed size*/ unsigned long real_used; /* used+malloc overhead*/ unsigned long max_real_used; + unsigned long fragments; /* number of fragments in use */ struct qm_frag* first_frag; struct qm_frag_end* last_frag_end; @@ -119,6 +121,7 @@ struct qm_block{ struct qm_block* qm_malloc_init(char* address, unsigned long size); +inline unsigned long frag_size(void* p); #ifdef DBG_QM_MALLOC void* qm_malloc(struct qm_block*, unsigned long size, const char* file, @@ -173,12 +176,7 @@ static inline unsigned long qm_get_max_real_used(struct qm_block* qm) } static inline unsigned long qm_get_frags(struct qm_block* qm) { - int r; - unsigned long frags; - for(r=0,frags=0;rfree_hash[r].no; - } - return frags; + return qm->fragments; } #endif /* STATISTICS */ diff --git a/mem/shm_mem.c b/mem/shm_mem.c index 705bef961c..f2838f669a 100644 --- a/mem/shm_mem.c +++ b/mem/shm_mem.c @@ -89,6 +89,7 @@ static void* shm_mempool=(void*)-1; struct qm_block* shm_block; #endif + /* * - the memory fragmentation pattern of OpenSIPS * - holds the total number of shm_mallocs requested for each @@ -305,6 +306,53 @@ int shm_mem_init_mallocs(void* mempool, unsigned long pool_size) shm_mem_destroy(); return -1; } +#ifdef SHM_EXTRA_STATS + int size_prealoc, j, one_full_entry, groups; + char *start; + if(mem_free_idx != 1){ + #ifndef SHM_SHOW_DEFAULT_GROUP + groups = mem_free_idx - 1; + #else + groups = mem_free_idx; + #endif + + one_full_entry = 3 * (sizeof(stat_var) + sizeof(stat_val)); + size_prealoc = groups * sizeof(struct module_info) + groups * one_full_entry; + + #ifndef DBG_QM_MALLOC + memory_mods_stats = MY_MALLOC_UNSAFE(shm_block, size_prealoc); + #else + memory_mods_stats = MY_MALLOC_UNSAFE(shm_block, size_prealoc, __FILE__, __FUNCTION__, __LINE__ ); + #endif + + if(!memory_mods_stats){ + LM_CRIT("could not alloc shared memory"); + return -1; + } + memset( (void*)memory_mods_stats, 0, size_prealoc); + start = (char*)memory_mods_stats + groups * sizeof(struct module_info); + for(j = 0; j < groups; j++){ + memory_mods_stats[j].fragments = (stat_var *)(start + j * one_full_entry); + memory_mods_stats[j].memory_used = (stat_var *)(start + j * one_full_entry + sizeof(stat_var)); + memory_mods_stats[j].real_used = (stat_var *)(start + j * one_full_entry + 2 * sizeof(stat_var)); + + memory_mods_stats[j].fragments->u.val = (stat_val*)(start + j * one_full_entry + 3 * sizeof(stat_var)); + memory_mods_stats[j].memory_used->u.val = (stat_val*)(start + j * one_full_entry + 3 * sizeof(stat_var) + sizeof(stat_val)); + memory_mods_stats[j].real_used->u.val = (stat_val*)(start + j * one_full_entry + 3 * sizeof(stat_var) + 2 * sizeof(stat_val)); + } + #ifndef SHM_SHOW_DEFAULT_GROUP + if(core_index != 0){ + update_stat(memory_mods_stats[core_index - 1].fragments, 1); + update_stat(memory_mods_stats[core_index - 1].memory_used, size_prealoc); + update_stat(memory_mods_stats[core_index - 1].real_used, size_prealoc + FRAG_OVERHEAD); + } + #else + update_stat(memory_mods_stats[core_index].fragments, 1); + update_stat(memory_mods_stats[core_index].memory_used, size_prealoc); + update_stat(memory_mods_stats[core_index].real_used, size_prealoc + FRAG_OVERHEAD); + #endif + } +#endif #ifdef HP_MALLOC /* lock_alloc cannot be used yet! */ @@ -414,6 +462,60 @@ void init_shm_statistics(void) #ifdef HP_MALLOC hp_init_shm_statistics(shm_block); #endif + +#ifdef SHM_EXTRA_STATS + struct multi_str *mod_name; + int i, len; + char *full_name = NULL; + + if(mem_free_idx != 1){ + +#ifdef SHM_SHOW_DEFAULT_GROUP + if (register_stat("shmem_group_default", "fragments", (stat_var **)&memory_mods_stats[0].fragments, STAT_NO_RESET|STAT_ONLY_REGISTER)!=0 ) { + LM_CRIT("can't add stat variable"); + return; + } + + if (register_stat("shmem_group_default", "memory_used", (stat_var **)&memory_mods_stats[0].memory_used, STAT_NO_RESET|STAT_ONLY_REGISTER)!=0 ) { + LM_CRIT("can't add stat variable"); + return; + } + + if (register_stat("shmem_group_default", "real_used", (stat_var **)&memory_mods_stats[0].real_used, STAT_NO_RESET|STAT_ONLY_REGISTER)!=0 ) { + LM_CRIT("can't add stat variable"); + return; + } + + + i = mem_free_idx - 1; +#else + i = mem_free_idx - 2; +#endif + for(mod_name = mod_names; mod_name != NULL; mod_name = mod_name->next){ + len = strlen(mod_name->s); + full_name = pkg_malloc((len + STAT_PREFIX_LEN + 1) * sizeof(char)); + + strcpy(full_name, STAT_PREFIX); + strcat(full_name, mod_name->s); + if (register_stat(full_name, "fragments", (stat_var **)&memory_mods_stats[i].fragments, STAT_NO_RESET|STAT_ONLY_REGISTER)!=0 ) { + LM_CRIT("can't add stat variable"); + return; + } + + if (register_stat(full_name, "memory_used", (stat_var **)&memory_mods_stats[i].memory_used, STAT_NO_RESET|STAT_ONLY_REGISTER)!=0 ) { + LM_CRIT("can't add stat variable"); + return; + } + + if (register_stat(full_name, "real_used", (stat_var **)&memory_mods_stats[i].real_used, STAT_NO_RESET|STAT_ONLY_REGISTER)!=0 ) { + LM_CRIT("can't add stat variable"); + return; + } + i--; + } + } +#endif + } void shm_mem_destroy(void) diff --git a/mem/shm_mem.h b/mem/shm_mem.h index 765c85e7e5..78c2cb2739 100644 --- a/mem/shm_mem.h +++ b/mem/shm_mem.h @@ -39,6 +39,7 @@ #include #include + #ifndef SHM_MMAP #include @@ -66,6 +67,11 @@ #include "../lock_ops.h" /* we don't include locking.h on purpose */ #include "common.h" +#ifdef SHM_EXTRA_STATS +#include "module_info.h" +#include "mem_stats.h" +#endif + #ifdef VQ_MALLOC # include "vq_malloc.h" # define MY_MALLOC vqm_malloc @@ -203,12 +209,16 @@ inline static void shm_threshold_check(void) #define shm_unlock(i) lock_release(&mem_lock[i]) #endif +#ifdef SHM_EXTRA_STATS + #define PASTER(_x, _y) _x ## _y + #define VAR_STAT(_n) PASTER(_n, _mem_stat) +#endif #ifdef DBG_QM_MALLOC -#ifdef __SUNPRO_C - #define __FUNCTION__ "" /* gcc specific */ -#endif + #ifdef __SUNPRO_C + #define __FUNCTION__ "" /* gcc specific */ + #endif inline static void* _shm_malloc_unsafe(unsigned int size, const char *file, const char *function, int line ) @@ -216,9 +226,13 @@ inline static void* _shm_malloc_unsafe(unsigned int size, void *p; p = MY_MALLOC_UNSAFE(shm_block, size, file, function, line); - shm_threshold_check(); +#ifdef SHM_EXTRA_STATS + unsigned long size_f = frag_size(p); + update_module_stats(size_f, size_f + FRAG_OVERHEAD, 1, VAR_STAT(MOD_NAME)); +#endif + return p; } @@ -227,16 +241,21 @@ inline static void* _shm_malloc(unsigned int size, { void *p; -#ifndef HP_MALLOC - shm_lock(); -#endif + #ifndef HP_MALLOC + shm_lock(); + #endif p = MY_MALLOC(shm_block, size, file, function, line); shm_threshold_check(); -#ifndef HP_MALLOC - shm_unlock(); -#endif + #ifndef HP_MALLOC + shm_unlock(); + #endif + + #ifdef SHM_EXTRA_STATS + unsigned long size_f = frag_size(p); + update_module_stats(size_f, size_f + FRAG_OVERHEAD, 1, VAR_STAT(MOD_NAME)); + #endif return p; } @@ -247,6 +266,10 @@ inline static void* _shm_realloc(void *ptr, unsigned int size, { void *p; + #ifdef SHM_EXTRA_STATS + long size_f = frag_size(ptr); + #endif + #ifndef HP_MALLOC shm_lock(); #endif @@ -258,6 +281,12 @@ inline static void* _shm_realloc(void *ptr, unsigned int size, shm_unlock(); #endif + #ifdef SHM_EXTRA_STATS + size_f = (frag_size(p) - size_f); + update_module_stats(size_f, size_f + (ptr)?(0):(FRAG_OVERHEAD), (ptr)?(0):(1), VAR_STAT(MOD_NAME)); + + #endif + return p; } @@ -266,12 +295,22 @@ inline static void* _shm_realloc_unsafe(void *ptr, unsigned int size, { void *p; + #ifdef SHM_EXTRA_STATS + long size_f = frag_size(ptr); + #endif + p = MY_REALLOC_UNSAFE(shm_block, ptr, size, file, function, line); shm_threshold_check(); + #ifdef SHM_EXTRA_STATS + size_f = (frag_size(p) - size_f); + update_module_stats(size_f, size_f + (ptr)?(0):(FRAG_OVERHEAD), (ptr)?(0):(1), VAR_STAT(MOD_NAME)); + #endif + return p; } + #define shm_malloc( _size ) _shm_malloc((_size), \ __FILE__, __FUNCTION__, __LINE__ ) @@ -285,12 +324,21 @@ inline static void* _shm_realloc_unsafe(void *ptr, unsigned int size, __FILE__, __FUNCTION__, __LINE__ ) +#ifndef SHM_EXTRA_STATS + #define shm_free_unsafe( _p ) \ + do {\ + MY_FREE( shm_block, (_p), __FILE__, __FUNCTION__, __LINE__ ); \ + shm_threshold_check(); \ + } while(0) +#else + #define shm_free_unsafe( _p ) \ + do {\ + update_module_stats(-frag_size(_p), -(frag_size(_p) + FRAG_OVERHEAD), -1, VAR_STAT(MOD_NAME)); \ + MY_FREE( shm_block, (_p), __FILE__, __FUNCTION__, __LINE__ ); \ + shm_threshold_check(); \ + } while(0) -#define shm_free_unsafe( _p ) \ -do {\ - MY_FREE( shm_block, (_p), __FILE__, __FUNCTION__, __LINE__ ); \ - shm_threshold_check(); \ -} while(0) +#endif #define shm_free(_p) \ do { \ @@ -319,6 +367,11 @@ inline static void* shm_malloc_unsafe(unsigned int size) shm_threshold_check(); +#ifdef SHM_EXTRA_STATS + unsigned long size_f = frag_size(p); + update_module_stats(size_f, size_f + FRAG_OVERHEAD, 1, VAR_STAT(MOD_NAME)); +#endif + return p; } @@ -337,6 +390,11 @@ inline static void* shm_malloc(unsigned long size) shm_unlock(); #endif +#ifdef SHM_EXTRA_STATS + unsigned long size_f = frag_size(p); + update_module_stats(size_f, size_f + FRAG_OVERHEAD, 1, VAR_STAT(MOD_NAME)); +#endif + return p; } @@ -359,6 +417,10 @@ inline static void* shm_realloc(void *ptr, unsigned int size) #endif #endif +#ifdef SHM_EXTRA_STATS + long size_f = frag_size(ptr); +#endif + p = MY_REALLOC(shm_block, ptr, size); shm_threshold_check(); @@ -366,24 +428,46 @@ inline static void* shm_realloc(void *ptr, unsigned int size) shm_unlock(); #endif +#ifdef SHM_EXTRA_STATS + size_f = (frag_size(p) - size_f); + update_module_stats(size_f, size_f + (ptr)?(0):(FRAG_OVERHEAD), (ptr)?(0):(1), VAR_STAT(MOD_NAME)); +#endif + return p; } inline static void* shm_realloc_unsafe(void *ptr, unsigned int size) { void *p; +#ifdef SHM_EXTRA_STATS + long size_f = frag_size(ptr); +#endif p = MY_REALLOC_UNSAFE(shm_block, ptr, size); shm_threshold_check(); +#ifdef SHM_EXTRA_STATS + size_f = (frag_size(p) - size_f); + update_module_stats(size_f, size_f + (ptr)?(0):(FRAG_OVERHEAD), (ptr)?(0):(1), VAR_STAT(MOD_NAME)); +#endif return p; } +#ifndef SHM_EXTRA_STATS #define shm_free_unsafe( _p ) \ do { \ MY_FREE_UNSAFE(shm_block, (_p)); \ shm_threshold_check(); \ } while(0) +#else +#define shm_free_unsafe( _p ) \ +do { \ + update_module_stats(-frag_size(_p), -(frag_size(_p) + FRAG_OVERHEAD), -1, VAR_STAT(MOD_NAME)); \ + MY_FREE_UNSAFE(shm_block, (_p)); \ + shm_threshold_check(); \ +} while(0) + +#endif /** * FIXME: tmp hacks --liviu @@ -406,6 +490,10 @@ inline static void shm_free(void *_p) #endif #ifdef HP_MALLOC + #ifdef SHM_EXTRA_STATS + long size_f = frag_size(_p); + update_module_stats(-size_f, -size_f - FRAG_OVERHEAD, -1, VAR_STAT(MOD_NAME)); + #endif MY_FREE(shm_block, _p); #else shm_free_unsafe( (_p)); diff --git a/modules/cpl-c/Makefile b/modules/cpl-c/Makefile index 7b9702d1f4..24d95612e1 100644 --- a/modules/cpl-c/Makefile +++ b/modules/cpl-c/Makefile @@ -4,7 +4,7 @@ include ../../Makefile.defs auto_gen= -NAME=cpl-c.so +NAME=cpl_c.so ifeq ($(CROSS_COMPILE),) XML2CFG=$(shell which xml2-config) diff --git a/statistics.c b/statistics.c index 817731dd0a..7e5ad65403 100644 --- a/statistics.c +++ b/statistics.c @@ -467,6 +467,11 @@ int register_stat2( char *module, char *name, stat_var **pvar, } name_len = strlen(name); + + if(flags&STAT_ONLY_REGISTER){ + stat = *pvar; + goto do_register; + } stat = unsafe ? (stat_var*)shm_malloc_unsafe(sizeof(stat_var) + ((flags&STAT_SHM_NAME)==0)*name_len) @@ -499,6 +504,7 @@ int register_stat2( char *module, char *name, stat_var **pvar, } /* is the module already recorded? */ +do_register: smodule.s = module; smodule.len = strlen(module); mods = get_stat_module(&smodule); @@ -515,7 +521,11 @@ int register_stat2( char *module, char *name, stat_var **pvar, stat->name.len = name_len; if ( (flags&STAT_SHM_NAME)==0 ) { - stat->name.s = (char*)(stat+1); + if(flags&STAT_ONLY_REGISTER) + stat->name.s = shm_malloc_unsafe(name_len); + else + stat->name.s = (char*)(stat+1); + memcpy(stat->name.s, name, name_len); } else { stat->name.s = name; diff --git a/statistics.h b/statistics.h index ca72e2b126..ee1d3fb2b6 100644 --- a/statistics.h +++ b/statistics.h @@ -46,6 +46,7 @@ #define STAT_NO_SYNC (1<<1) #define STAT_SHM_NAME (1<<2) #define STAT_IS_FUNC (1<<3) +#define STAT_ONLY_REGISTER (1<<4) #ifdef NO_ATOMIC_OPS typedef unsigned int stat_val;