Browse code

mem: summarize in-use memory on exit

Additional qm_sums and fm_sums as extension to qm_status/fm_status, with
summarized values per allocation source.
Slightly modified SER-224 patch version (no locking, sr changes --andrei).

Closes SER-224.

Signed-off-by: Andrei Pelinescu-Onciul <andrei@iptel.org>

Dragos Vingarzan authored on 28/09/2009 20:01:17
Showing 7 changed files
... ...
@@ -532,6 +532,8 @@ void cleanup(show_status)
532 532
 	if (show_status){
533 533
 		LOG(memlog, "Memory status (pkg):\n");
534 534
 		pkg_status();
535
+		LOG(memlog, "Memory still-in-use summary (pkg):\n");
536
+		pkg_sums();
535 537
 	}
536 538
 #endif
537 539
 #ifdef SHM_MEM
... ...
@@ -540,6 +542,8 @@ void cleanup(show_status)
540 540
 	if (show_status){
541 541
 			LOG(memlog, "Memory status (shm):\n");
542 542
 			shm_status();
543
+			LOG(memlog, "Memory still-in-use summary (shm):\n");
544
+			shm_sums();
543 545
 	}
544 546
 	/* zero all shmem alloc vars that we still use */
545 547
 	shm_mem_destroy();
... ...
@@ -40,6 +40,7 @@
40 40
  *  2006-04-07  s/DBG/MDBG (andrei)
41 41
  *  2007-02-23  added fm_available() (andrei)
42 42
  *  2007-06-23  added hash bitmap (andrei)
43
+ *  2009-09-28  added fm_sums() (patch from Dragos Vingarzan)
43 44
  */
44 45
 
45 46
 
... ...
@@ -711,4 +712,85 @@ unsigned long fm_available(struct fm_block* qm)
711 711
 #endif
712 712
 }
713 713
 
714
+
715
+#ifdef DBG_F_MALLOC
716
+
717
+typedef struct _mem_counter{
718
+	const char *file;
719
+	const char *func;
720
+	unsigned long line;
721
+	
722
+	unsigned long size;
723
+	int count;
724
+	
725
+	struct _mem_counter *next;
726
+} mem_counter;
727
+
728
+static mem_counter* get_mem_counter(mem_counter **root,struct fm_frag* f)
729
+{
730
+	mem_counter *x;
731
+	
732
+	if (!*root) goto make_new;
733
+	for(x=*root;x;x=x->next)
734
+		if (x->file == f->file && x->func == f->func && x->line == f->line)
735
+			return x;
736
+make_new:	
737
+	x = malloc(sizeof(mem_counter));
738
+	x->file = f->file;
739
+	x->func = f->func;
740
+	x->line = f->line;
741
+	x->count = 0;
742
+	x->size = 0;
743
+	x->next = *root;
744
+	*root = x;
745
+	return x;
746
+}
747
+
748
+
749
+
750
+void fm_sums(struct fm_block* qm)
751
+{
752
+	struct fm_frag* f;
753
+	struct fm_frag* free_frag;
754
+	int i, hash;
755
+	mem_counter *root,*x;
756
+	
757
+	root=0;
758
+	if (!qm) return;
759
+
760
+	LOG(memlog, "summarizing all alloc'ed. fragments:\n");
761
+	
762
+	for (f=qm->first_frag, i=0; (char*)f<(char*)qm->last_frag;
763
+			f=FRAG_NEXT(f), i++){
764
+		if (f->u.nxt_free==0){
765
+			/* it might be in-use or the last free fragm. in a free list 
766
+			   => search the free frags of the same size for a possible
767
+			   match --andrei*/
768
+			hash=GET_HASH(f->size);
769
+			for(free_frag=qm->free_hash[hash].first;
770
+					free_frag && (free_frag!=f);
771
+					free_frag=free_frag->u.nxt_free);
772
+			if (free_frag==0){ /* not found among the free frag */
773
+				x = get_mem_counter(&root,f);
774
+				x->count++;
775
+				x->size+=f->size;
776
+			}
777
+		}
778
+	}
779
+	x = root;
780
+	while(x){
781
+		LOG(memlog, " count=%6d size=%10lu bytes from %s: %s(%ld)\n",
782
+			x->count,x->size,
783
+			x->file, x->func, x->line
784
+			);
785
+		root = x->next;
786
+		free(x);
787
+		x = root;
788
+	}
789
+	LOG(memlog, "-----------------------------\n");
790
+}
791
+#endif /* DBG_F_MALLOC */
792
+
793
+
794
+
714 795
 #endif
... ...
@@ -155,4 +155,10 @@ void  fm_info(struct fm_block*, struct mem_info*);
155 155
 
156 156
 unsigned long fm_available(struct fm_block*);
157 157
 
158
+#ifdef DBG_F_MALLOC
159
+void fm_sums(struct fm_block*);
160
+#else
161
+#define fm_sums(v) do{}while(0)
162
+#endif /* DBG_F_MALLOC */
163
+
158 164
 #endif
... ...
@@ -120,20 +120,24 @@
120 120
 #		define pkg_status()    fm_status(mem_block)
121 121
 #		define pkg_info(mi)    fm_info(mem_block, mi)
122 122
 #		define pkg_available() fm_available(mem_block)
123
+#		define pkg_sums()      fm_sums(mem_block)
123 124
 #	elif defined DL_MALLOC
124 125
 #		define pkg_status()  0
125 126
 #		define pkg_info(mi)  0
126 127
 #		define pkg_available()  0
128
+#		define pkg_sums()  0
127 129
 #	else
128 130
 #		define pkg_status()    qm_status(mem_block)
129 131
 #		define pkg_info(mi)    qm_info(mem_block, mi)
130 132
 #		define pkg_available() qm_available(mem_block)
133
+#		define pkg_sums()      qm_sums(mem_block)
131 134
 #	endif
132 135
 #elif defined(SHM_MEM) && defined(USE_SHM_MEM)
133 136
 #	include "shm_mem.h"
134 137
 #	define pkg_malloc(s) shm_malloc((s))
135 138
 #	define pkg_free(p)   shm_free((p))
136 139
 #	define pkg_status()  shm_status()
140
+#	define pkg_sums()    shm_sums()
137 141
 #else
138 142
 #	include <stdlib.h>
139 143
 #	include "memdbg.h"
... ...
@@ -147,6 +151,7 @@
147 147
 	    ____v123; } )
148 148
 #	define pkg_free(p)  do{ MDBG("free %p\n", (p)); free((p)); }while(0);
149 149
 #	define pkg_status()
150
+#	define pkg_sums()
150 151
 #endif
151 152
 
152 153
 int init_pkg_mallocs();
... ...
@@ -40,6 +40,7 @@
40 40
  *  2006-02-03  fixed realloc out of mem. free bug (andrei)
41 41
  *  2006-04-07  s/DBG/MDBG (andrei)
42 42
  *  2007-02-23  added fm_available() (andrei)
43
+ *  2009-09-28  added fm_sums() (patch from Dragos Vingarzan)
43 44
  */
44 45
 
45 46
 
... ...
@@ -779,4 +780,73 @@ unsigned long qm_available(struct qm_block* qm)
779 779
 }
780 780
 
781 781
 
782
+
783
+#ifdef DBG_QM_MALLOC
784
+
785
+typedef struct _mem_counter{
786
+	const char *file;
787
+	const char *func;
788
+	unsigned long line;
789
+	
790
+	unsigned long size;
791
+	int count;
792
+	
793
+	struct _mem_counter *next;
794
+} mem_counter;
795
+
796
+static mem_counter* get_mem_counter(mem_counter **root, struct qm_frag* f)
797
+{
798
+	mem_counter *x;
799
+	if (!*root) goto make_new;
800
+	for(x=*root;x;x=x->next)
801
+		if (x->file == f->file && x->func == f->func && x->line == f->line)
802
+			return x;
803
+make_new:	
804
+	x = malloc(sizeof(mem_counter));
805
+	x->file = f->file;
806
+	x->func = f->func;
807
+	x->line = f->line;
808
+	x->count = 0;
809
+	x->size = 0;
810
+	x->next = *root;
811
+	*root = x;
812
+	return x;
813
+}
814
+
815
+
816
+
817
+void qm_sums(struct qm_block* qm)
818
+{
819
+	struct qm_frag* f;
820
+	int i;
821
+	mem_counter *root, *x;
822
+	
823
+	root=0;
824
+	if (!qm) return;
825
+	
826
+	LOG(memlog, "summarizing all alloc'ed. fragments:\n");
827
+	
828
+	for (f=qm->first_frag, i=0;(char*)f<(char*)qm->last_frag_end;
829
+			f=FRAG_NEXT(f),i++){
830
+		if (! f->u.is_free){
831
+			x = get_mem_counter(&root,f);
832
+			x->count++;
833
+			x->size+=f->size;
834
+		}
835
+	}
836
+	x = root;
837
+	while(x){
838
+		LOG(memlog, " count=%6d size=%10lu bytes from %s: %s(%ld)\n",
839
+			x->count,x->size,
840
+			x->file, x->func, x->line
841
+			);
842
+		root = x->next;
843
+		free(x);
844
+		x = root;
845
+	}
846
+	LOG(memlog, "-----------------------------\n");
847
+}
848
+#endif /* DBG_QM_MALLOC */
849
+
850
+
782 851
 #endif
... ...
@@ -153,4 +153,10 @@ void  qm_info(struct qm_block*, struct mem_info*);
153 153
 
154 154
 unsigned long qm_available(struct qm_block* qm);
155 155
 
156
+#ifdef DBG_QM_MALLOC
157
+void qm_sums(struct qm_block* qm);
158
+#else
159
+#define qm_sums(v) do{}while(0)
160
+#endif /*DBQ_QM_MALLOC */
161
+
156 162
 #endif
... ...
@@ -98,6 +98,7 @@
98 98
 #	define shm_free_unsafe shm_free
99 99
 #	define shm_available	sfm_available(shm_block)
100 100
 #	define shm_status() sfm_status(shm_block)
101
+#	define shm_sums() do{}while(0)
101 102
 #	define shm_malloc_init sfm_malloc_init
102 103
 #	define shm_malloc_destroy(b) sfm_malloc_destroy(b)
103 104
 #	define shm_malloc_on_fork()	sfm_pool_reset()
... ...
@@ -124,6 +125,7 @@
124 124
 #	define shm_free_unsafe shm_free
125 125
 #	define shm_available	sfm_available(shm_block)
126 126
 #	define shm_status() sfm_status(shm_block)
127
+#	define shm_sums() do{}while(0)
127 128
 #	define shm_malloc_init sfm_malloc_init
128 129
 #	define shm_malloc_destroy(b) sfm_malloc_destroy(b)
129 130
 #	define shm_malloc_on_fork()	sfm_pool_reset()
... ...
@@ -133,6 +135,7 @@
133 133
 #	define MY_MALLOC vqm_malloc
134 134
 #	define MY_FREE vqm_free
135 135
 #	define MY_STATUS vqm_status
136
+#	define MY_SUMS do{}while(0)
136 137
 #	define  shm_malloc_init vqm_malloc_init
137 138
 #	define shm_malloc_destroy(b) do{}while(0)
138 139
 #	define shm_malloc_on_fork() do{}while(0)
... ...
@@ -145,6 +148,7 @@
145 145
 #	define MY_REALLOC fm_realloc
146 146
 #	define MY_STATUS fm_status
147 147
 #	define MY_MEMINFO	fm_info
148
+#	define MY_SUMS	fm_sums
148 149
 #	define  shm_malloc_init fm_malloc_init
149 150
 #	define shm_malloc_destroy(b) do{}while(0)
150 151
 #	define shm_available() fm_available(shm_block)
... ...
@@ -156,6 +160,7 @@
156 156
 #	define MY_FREE mspace_free
157 157
 #	define MY_REALLOC mspace_realloc
158 158
 #	define MY_STATUS(...) 0
159
+#	define MY_SUMS do{}while(0)
159 160
 #	define MY_MEMINFO	mspace_info
160 161
 #	define  shm_malloc_init(buf, len) create_mspace_with_base(buf, len, 0)
161 162
 #	define shm_malloc_destroy(b) do{}while(0)
... ...
@@ -168,6 +173,7 @@
168 168
 #	define MY_REALLOC qm_realloc
169 169
 #	define MY_STATUS qm_status
170 170
 #	define MY_MEMINFO	qm_info
171
+#	define MY_SUMS	qm_sums
171 172
 #	define  shm_malloc_init qm_malloc_init
172 173
 #	define shm_malloc_destroy(b) do{}while(0)
173 174
 #	define shm_available() qm_available(shm_block)
... ...
@@ -318,6 +324,16 @@ do{\
318 318
 	shm_unlock(); \
319 319
 }while(0)
320 320
 
321
+#ifdef MY_SUMS
322
+#define shm_sums() \
323
+	do { \
324
+		shm_lock(); \
325
+		MY_SUMS(shm_block); \
326
+		shm_unlock(); \
327
+	}while(0)
328
+	
329
+#endif /* MY_SUMS */
330
+
321 331
 #endif /* ! SHM_SAFE_MALLOC */
322 332
 
323 333
 #endif /* shm_mem_h */