Browse code

performance and bug fixes

Jiri Kuthan authored on 07/01/2002 04:39:49
Showing 52 changed files
... ...
@@ -11,7 +11,7 @@ auto_gen=lex.yy.c cfg.tab.c   #lexx, yacc etc
11 11
 include Makefile.sources
12 12
 
13 13
 exclude_modules=CVS usrloc mysql auth
14
-static_modules=
14
+static_modules=tm
15 15
 static_modules_path=$(addprefix modules/, $(static_modules))
16 16
 extra_sources=$(wildcard $(addsuffix /*.c, $(static_modules_path)))
17 17
 extra_objs=$(extra_sources:.c=.o)
... ...
@@ -44,8 +44,16 @@ ARCH = $(shell uname -s)
44 44
 #		extra error checking (trying to free the same pointer
45 45
 #		twice, trying to free a pointer alloc'ed with a different
46 46
 #		malloc etc.)
47
+# -DVQ_MALLOC
48
+#		additional option to PKG_MALLOC which utilizes a fater then
49
+#		qm version
50
+#
51
+
47 52
 DEFS+= -DNAME='"$(NAME)"' -DVERSION='"$(RELEASE)"' -DARCH='"$(ARCH)"' \
48 53
 	 -DDNS_IP_HACK  -DPKG_MALLOC -DSHM_MEM  -DSHM_MMAP \
54
+	-DEXTRA_DEBUG \
55
+	-DVQ_MALLOC 
56
+	  #-DDBG_QM_MALLOC #-DVQ_MALLOC #-DNO_DEBUG
49 57
 	  #-DNO_DEBUG #-DDBG_QM_MALLOC
50 58
 #-DEXTRA_DEBUG
51 59
 # -DUSE_SHM_MEM
... ...
@@ -54,9 +62,9 @@ DEFS+= -DNAME='"$(NAME)"' -DVERSION='"$(RELEASE)"' -DARCH='"$(ARCH)"' \
54 62
 #-DNO_DEBUG#-DSTATS -DNO_DEBUG 
55 63
 #-DNO_LOG
56 64
 
57
-PROFILE=  #-pg #set this if you want profiling
58
-#mode = debug
59
-mode = release
65
+PROFILE=  -pg #set this if you want profiling
66
+mode = debug
67
+#mode = release
60 68
 
61 69
 # platform dependent settings
62 70
 
... ...
@@ -11,7 +11,7 @@
11 11
 # defines: sources, objs, depends
12 12
 #
13 13
 
14
-sources=$(filter-out $(auto_gen), $(wildcard *.c)) $(auto_gen)
14
+sources=$(filter-out $(auto_gen), $(wildcard *.c) $(wildcard mem/*.c) ) $(auto_gen)
15 15
 objs=$(sources:.c=.o)
16 16
 extra_objs=
17 17
 depends=$(sources:.c=.d)
... ...
@@ -15,7 +15,7 @@
15 15
 #include "msg_parser.h"
16 16
 #include "ut.h"
17 17
 #include "sr_module.h"
18
-#include "mem.h"
18
+#include "mem/mem.h"
19 19
 
20 20
 #include <sys/types.h>
21 21
 #include <sys/socket.h>
... ...
@@ -1,5 +1,5 @@
1 1
 /*
2
- *  $Id
2
+ *  $Id $
3 3
  */
4 4
 
5 5
 
... ...
@@ -12,8 +12,6 @@
12 12
 
13 13
 #define CFG_FILE "./ser.cfg"
14 14
 
15
-/* receive buffer size */
16
-#define BUF_SIZE 65507
17 15
 
18 16
 /* maximum number of addresses on which we will listen */
19 17
 #define MAX_LISTEN 16
... ...
@@ -47,11 +45,29 @@
47 45
 /*used only if PKG_MALLOC is defined*/
48 46
 #define PKG_MEM_POOL_SIZE 1024*1024
49 47
 
50
-/*used is SH_MEM is defined*/
48
+/*used if SH_MEM is defined*/
51 49
 #define SHM_MEM_SIZE 128*1024*1024
52 50
 
53 51
 #define TIMER_TICK 1
54 52
 #define LONG_SLEEP	3600
55 53
 
54
+/* dimensioning buckets in q_malloc */
55
+/* size of the size2bucket table; everything beyond that asks for
56
+   a variable-size kilo-bucket
57
+ */
58
+#define MAX_FIXED_BLOCK         3072
59
+/* distance of kilo-buckets */
60
+#define BLOCK_STEP                      512
61
+/* maximum number of possible buckets */
62
+#define MAX_BUCKET		15
63
+
64
+/* receive buffer size -- preferably set low to
65
+   avoid terror of excessively huge messages
66
+*/
67
+#define BUF_SIZE (MAX_FIXED_BLOCK-32)
68
+
69
+/* forwarding */
70
+#define MAX_VIA_LINE_SIZE	240
71
+#define MAX_RECEIVED_SIZE	57
56 72
 
57 73
 #endif
... ...
@@ -1,8 +1,11 @@
1 1
 /*
2
+ * $Id$
3
+ *
2 4
  *  Crc - 32 + 16 BIT ANSI X3.66 + CCITT CRC checksum files
3 5
  */
4 6
 
5 7
 #include <stdio.h>
8
+#include "crc.h"
6 9
 
7 10
 #define OK 0
8 11
 #define ERROR (-1)
... ...
@@ -60,7 +63,7 @@
60 63
 /*     hardware you could probably optimize the shift in assembler by  */
61 64
 /*     using byte-swap instructions.                                   */
62 65
 
63
-static unsigned long int crc_32_tab[] = { /* CRC polynomial 0xedb88320 */
66
+unsigned long int crc_32_tab[] = { /* CRC polynomial 0xedb88320 */
64 67
 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
65 68
 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
66 69
 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
67 70
new file mode 100644
... ...
@@ -0,0 +1,11 @@
1
+/* $Id$*/
2
+
3
+#ifndef _CRC_H_
4
+#define _CRC_H_
5
+
6
+extern unsigned long int crc_32_tab[];
7
+extern unsigned short int ccitt_tab[];
8
+extern unsigned short int crc_16_tab[];
9
+
10
+#endif
11
+
... ...
@@ -4,7 +4,7 @@
4 4
 
5 5
 #include "data_lump.h"
6 6
 #include "dprint.h"
7
-#include "mem.h"
7
+#include "mem/mem.h"
8 8
 
9 9
 #include <stdlib.h>
10 10
 
... ...
@@ -21,21 +21,15 @@
21 21
 #include "globals.h"
22 22
 #include "data_lump.h"
23 23
 #include "ut.h"
24
-#include "mem.h"
24
+#include "mem/mem.h"
25 25
 #include "msg_translator.h"
26 26
 #include "sr_module.h"
27
+#include "stats.h"
27 28
 
28 29
 #ifdef DEBUG_DMALLOC
29 30
 #include <dmalloc.h>
30 31
 #endif
31 32
 
32
-#define MAX_VIA_LINE_SIZE      240
33
-#define MAX_RECEIVED_SIZE  57
34
-
35
-#ifdef STATS
36
-#include "stats.h"
37
-#endif
38
-
39 33
 
40 34
 
41 35
 int forward_request( struct sip_msg* msg, struct proxy_l * p)
... ...
@@ -79,15 +73,11 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p)
79 73
 				sizeof(struct sockaddr_in))==-1){
80 74
 			p->errors++;
81 75
 			p->ok=0;
82
-#ifdef STATS
83
-			update_fail_on_send;
84
-#endif
76
+			STATS_TX_DROPS;
85 77
 			goto error;
86 78
 	}
87
-#ifdef STATS
88 79
 	/* sent requests stats */
89
-	else update_sent_request( msg->first_line.u.request.method_value );
90
-#endif
80
+	else STATS_TX_REQUEST(  msg->first_line.u.request.method_value );
91 81
 	free(buf);
92 82
 	free(to);
93 83
 	/* received_buf & line_buf will be freed in receiv_msg by free_lump_list*/
... ...
@@ -189,15 +179,10 @@ int forward_reply(struct sip_msg* msg)
189 179
 	if (udp_send(new_buf,new_len, (struct sockaddr*) to,
190 180
 					sizeof(struct sockaddr_in))==-1)
191 181
 	{
192
-#ifdef STATS
193
-		update_fail_on_send;
194
-#endif
182
+		STATS_TX_DROPS;
195 183
 		goto error;
196 184
 	}
197
-#ifdef STATS
198
-	else update_sent_response(  msg->first_line.u.reply.statusclass );
199
-#endif
200
-
185
+	else STATS_TX_RESPONSE(  msg->first_line.u.reply.statusclass );
201 186
 	free(new_buf);
202 187
 	free(to);
203 188
 skip:
... ...
@@ -23,9 +23,9 @@
23 23
 #include "route.h"
24 24
 #include "udp_server.h"
25 25
 #include "globals.h"
26
-#include "mem.h"
26
+#include "mem/mem.h"
27 27
 #ifdef SHM_MEM
28
-#include "shm_mem.h"
28
+#include "mem/shm_mem.h"
29 29
 #endif
30 30
 #include "sr_module.h"
31 31
 #include "timer.h"
... ...
@@ -33,9 +33,7 @@
33 33
 
34 34
 #include <signal.h>
35 35
 
36
-#ifdef STATS
37 36
 #include "stats.h"
38
-#endif
39 37
 
40 38
 #ifdef DEBUG_DMALLOC
41 39
 #include <dmalloc.h>
... ...
@@ -72,6 +70,9 @@ static char flags[]=
72 70
 #ifdef PKG_MALLOC
73 71
 ", PKG_MALLOC"
74 72
 #endif
73
+#ifdef VQ_MALLOC
74
+", VQ_MALLOC"
75
+#endif
75 76
 #ifdef USE_SHM_MEM
76 77
 ", USE_SHM_MEM"
77 78
 #endif
... ...
@@ -171,12 +172,6 @@ int process_no = 0;
171 172
 /* cfg parsing */
172 173
 int cfg_errors=0;
173 174
 
174
-#ifdef PKG_MALLOC
175
-char mem_pool[PKG_MEM_POOL_SIZE];
176
-struct qm_block* mem_block;
177
-#endif
178
-
179
-
180 175
 #define MAX_FD 32 /* maximum number of inherited open file descriptors,
181 176
 		    (normally it shouldn't  be bigger  than 3) */
182 177
 
... ...
@@ -332,7 +327,7 @@ int main_loop()
332 327
 static void sig_usr(int signo)
333 328
 {
334 329
 	DPrint("INT received, program terminates\n");
335
-	if (signo==SIGINT) {	/* exit gracefuly */
330
+	if (signo==SIGINT || signo==SIGPIPE) {	/* exit gracefuly */
336 331
 #ifdef STATS
337 332
 		/* print statistics on exit only for the first process */
338 333
 
... ...
@@ -380,6 +375,7 @@ static void sig_usr(int signo)
380 375
 }
381 376
 
382 377
 
378
+void test();
383 379
 
384 380
 int main(int argc, char** argv)
385 381
 {
... ...
@@ -396,12 +392,20 @@ int main(int argc, char** argv)
396 392
 		DPrint("ERROR: no SIGINT signal handler can be installed\n");
397 393
 		goto error;
398 394
 	}
395
+	/* if we debug and write to a pipe, we want to exit nicely too */
396
+	if (signal(SIGPIPE, sig_usr) == SIG_ERR ) {
397
+		DPrint("ERROR: no SIGINT signal handler can be installed\n");
398
+		goto error;
399
+	}
399 400
 
400 401
 	if (signal(SIGUSR1, sig_usr)  == SIG_ERR ) {
401 402
 		DPrint("ERROR: no SIGUSR1 signal handler can be installed\n");
402 403
 		goto error;
403 404
 	}
404 405
 
406
+	//memtest();
407
+	//hashtest();
408
+
405 409
 
406 410
 	/* process command line (get port no, cfg. file path etc) */
407 411
 	opterr=0;
... ...
@@ -522,21 +526,9 @@ int main(int argc, char** argv)
522 526
 	}
523 527
 
524 528
 	/*init mallocs (before parsing cfg !)*/
525
-#ifdef PKG_MALLOC
526
-	/*init mem*/
527
-	mem_block=qm_malloc_init(mem_pool, PKG_MEM_POOL_SIZE);
528
-	if (mem_block==0){
529
-		LOG(L_CRIT, "could not initialize memory pool\n");
529
+	if (init_mallocs()==-1)
530 530
 		goto error;
531
-	}
532
-#endif
533 531
 
534
-#ifdef SHM_MEM
535
-	if (shm_mem_init()<0) {
536
-		LOG(L_CRIT, "could not initialize shared memory pool, exiting...\n");
537
-		goto error;
538
-	}
539
-#endif
540 532
 	/*init timer, before parsing the cfg!*/
541 533
 	if (init_timer()<0){
542 534
 		LOG(L_CRIT, "could not initialize timer, exiting...\n");
... ...
@@ -641,3 +633,4 @@ error:
641 633
 	return -1;
642 634
 
643 635
 }
636
+
... ...
@@ -28,8 +28,8 @@ jku: added support to deal with vectors
28 28
 #include "md5global.h"
29 29
 #include "md5.h"
30 30
 #include "md5utils.h"
31
-
32 31
 #include "dprint.h"
32
+#include "ut.h"
33 33
 
34 34
 
35 35
 static void MDString PROTO_LIST ((char *));
... ...
@@ -45,13 +45,38 @@ static void MDString PROTO_LIST ((char *));
45 45
  */
46 46
 void MDStringArray (char *dst, str src[], int size)
47 47
 {
48
-  MD_CTX context;
49
-  unsigned char digest[16];
50
-  int i;
48
+	MD_CTX context;
49
+	unsigned char digest[16];
50
+ 	int i;
51
+	int len;
52
+	char *s;
53
+
54
+/*
55
+#	ifdef EXTRA_DEBUG
56
+	int j;
57
+	int sum;
58
+#endif
59
+*/
51 60
 
52
-  MDInit (&context);
53
-  for (i=0; i<size; i++) {
54
-  	MDUpdate (&context, src[i].s, src[i].len);
61
+	MDInit (&context);
62
+	for (i=0; i<size; i++) {
63
+		trim_len( len, s, src[i] );
64
+/*
65
+#		ifdef EXTRA_DEBUG
66
+		fprintf(stderr, "EXTRA_DEBUG: %d. (%d) {", i+1, len);
67
+		sum=0;
68
+		for (j=0; j<len; j++) {
69
+			fprintf( stderr, "%c ", *(s+j));
70
+			sum+=*(s+j);
71
+		}
72
+		for (j=0; j<len; j++) {
73
+			fprintf( stderr, "%d ", *(s+j));
74
+			sum+=*(s+j);
75
+		}
76
+		fprintf(stderr, " [%d]\n", sum );	
77
+#		endif
78
+*/
79
+  		MDUpdate (&context, s, len);
55 80
   }
56 81
   MDFinal (digest, &context);
57 82
 
58 83
deleted file mode 100644
... ...
@@ -1,56 +0,0 @@
1
-/* $Id$
2
- *
3
- * memory related stuff (malloc & friends)
4
- * 
5
- */
6
-
7
-
8
-#ifndef mem_h
9
-#define mem_h
10
-#include "dprint.h"
11
-
12
-#ifdef PKG_MALLOC
13
-#include "q_malloc.h"
14
-
15
-extern struct qm_block* mem_block;
16
-
17
-
18
-#ifdef DBG_QM_MALLOC
19
-
20
-#define pkg_malloc(s) qm_malloc(mem_block, (s),__FILE__, __FUNCTION__, \
21
-								__LINE__);
22
-#define pkg_free(p)   qm_free(mem_block, (p), __FILE__,  __FUNCTION__, \
23
-								__LINE__);
24
-
25
-#else
26
-
27
-#define pkg_malloc(s) qm_malloc(mem_block, (s))
28
-#define pkg_free(p)   qm_free(mem_block, (p))
29
-
30
-#endif
31
-
32
-#define pkg_status()  qm_status(mem_block)
33
-
34
-#elif defined(SHM_MEM) && defined(USE_SHM_MEM)
35
-
36
-#include "shm_mem.h"
37
-
38
-#define pkg_malloc(s) shm_malloc((s))
39
-#define pkg_free(p)   shm_free((p))
40
-#define pkg_status()  shm_status()
41
-
42
-#else
43
-
44
-#include <stdlib.h>
45
-
46
-#define pkg_malloc(s) \
47
-	(  { void *v; v=malloc((s)); \
48
-	   DBG("malloc %x size %d end %x\n", v, s, (unsigned int)v+(s));\
49
-	   v; } )
50
-#define pkg_free(p)  do{ DBG("free %x\n", (p)); free((p)); }while(0);
51
-#define pkg_status()
52
-
53
-#endif
54
-
55
-
56
-#endif
57 0
new file mode 100644
... ...
@@ -0,0 +1,51 @@
1
+/*
2
+ * $Id *
3
+ */
4
+
5
+#include "../config.h"
6
+#include "../dprint.h"
7
+#include "mem.h"
8
+
9
+#ifdef PKG_MALLOC
10
+#	ifdef VQ_MALLOC
11
+#		include "vq_malloc.h"
12
+#	else
13
+#		include "q_malloc.h"
14
+#	endif
15
+#endif
16
+
17
+#ifdef PKG_MALLOC
18
+	char mem_pool[PKG_MEM_POOL_SIZE];
19
+	#ifdef VQ_MALLOC
20
+		struct vqm_block* mem_block;
21
+	#else
22
+		struct qm_block* mem_block;
23
+	#endif
24
+#endif
25
+
26
+int init_mallocs()
27
+{
28
+#ifdef PKG_MALLOC
29
+        /*init mem*/
30
+	#ifdef VQ_MALLOC
31
+        	mem_block=vqm_malloc_init(mem_pool, PKG_MEM_POOL_SIZE);
32
+	#else
33
+        	mem_block=qm_malloc_init(mem_pool, PKG_MEM_POOL_SIZE);
34
+	#endif
35
+        if (mem_block==0){
36
+                LOG(L_CRIT, "could not initialize memory pool\n");
37
+		return -1;
38
+        }
39
+#endif
40
+
41
+#ifdef SHM_MEM
42
+        if (shm_mem_init()<0) {
43
+                LOG(L_CRIT, "could not initialize shared memory pool, exiting...\n");
44
+                return -1;
45
+        }
46
+#endif
47
+	return 0;
48
+
49
+}
50
+
51
+
0 52
new file mode 100644
... ...
@@ -0,0 +1,68 @@
1
+/* $Id$
2
+ *
3
+ * memory related stuff (malloc & friends)
4
+ * 
5
+ */
6
+
7
+
8
+#ifndef mem_h
9
+#define mem_h
10
+#include "../config.h"
11
+#include "../dprint.h"
12
+
13
+#ifdef PKG_MALLOC
14
+#	ifdef VQ_MALLOC
15
+#		include "vq_malloc.h"
16
+		extern struct vqm_block* mem_block;
17
+#	else
18
+#		include "q_malloc.h"
19
+		extern struct qm_block* mem_block;
20
+#	endif
21
+
22
+	extern char mem_pool[PKG_MEM_POOL_SIZE];
23
+
24
+
25
+#	ifdef DBG_QM_MALLOC
26
+#		ifdef VQ_MALLOC
27
+#			define pkg_malloc(s) vqm_malloc(mem_block, (s),__FILE__, \
28
+				__FUNCTION__, __LINE__);
29
+#			define pkg_free(p)   vqm_free(mem_block, (p), __FILE__,  \
30
+				__FUNCTION__, __LINE__);
31
+#		else
32
+#			define pkg_malloc(s) qm_malloc(mem_block, (s),__FILE__, \
33
+				__FUNCTION__, __LINE__);
34
+#			define pkg_free(p)   qm_free(mem_block, (p), __FILE__,  \
35
+				__FUNCTION__, __LINE__);
36
+#		endif
37
+#	else
38
+#		ifdef VQ_MALLOC
39
+#			define pkg_malloc(s) vqm_malloc(mem_block, (s))
40
+#			define pkg_free(p)   vqm_free(mem_block, (p))
41
+#		else
42
+#			define pkg_malloc(s) qm_malloc(mem_block, (s))
43
+#			define pkg_free(p)   qm_free(mem_block, (p))
44
+#		endif
45
+#	endif
46
+#	ifdef VQ_MALLOC
47
+#		define pkg_status()  vqm_status(mem_block)
48
+#	else
49
+#		define pkg_status()  qm_status(mem_block)
50
+#	endif
51
+#elif defined(SHM_MEM) && defined(USE_SHM_MEM)
52
+#	include "shm_mem.h"
53
+#	define pkg_malloc(s) shm_malloc((s))
54
+#	define pkg_free(p)   shm_free((p))
55
+#	define pkg_status()  shm_status()
56
+#else
57
+#	include <stdlib.h>
58
+#	define pkg_malloc(s) \
59
+	(  { void *v; v=malloc((s)); \
60
+	   DBG("malloc %x size %d end %x\n", v, s, (unsigned int)v+(s));\
61
+	   v; } )
62
+#	define pkg_free(p)  do{ DBG("free %x\n", (p)); free((p)); }while(0);
63
+#	define pkg_status()
64
+#endif
65
+
66
+int init_mallocs();
67
+
68
+#endif
0 69
new file mode 100644
... ...
@@ -0,0 +1,133 @@
1
+#ifdef DBG_QM_MALLOC
2
+
3
+#include "../globals.h"
4
+#include "../config.h"
5
+
6
+#ifdef PKG_MALLOC
7
+#       ifdef VQ_MALLOC
8
+#               include "vq_malloc.h"
9
+#		define MY_MALLOC vqm_malloc
10
+#		define MY_FREE vqm_free
11
+#		define MY_INIT vqm_malloc_init
12
+#		define MY_BLOCK vqm_block
13
+#		define MY_STATUS vqm_status
14
+#       else
15
+#               include "q_malloc.h"
16
+#		define MY_MALLOC qm_malloc
17
+#		define MY_FREE qm_free
18
+#		define MY_INIT qm_malloc_init
19
+#		define MY_BLOCK qm_block
20
+#		define MY_STATUS qm_status
21
+#       endif
22
+#endif
23
+
24
+
25
+void memtest()
26
+{
27
+#define	TEST_SIZE 1024*1024
28
+#define	TEST_RUN 1024
29
+#define LONG_RUN 100000
30
+#define ma(s) MY_MALLOC(mem_block, (s),__FILE__, __FUNCTION__, \
31
+                                                                __LINE__);
32
+#define mf(p)   MY_FREE(mem_block, (p), __FILE__,  __FUNCTION__, \
33
+                                                                __LINE__);
34
+	char tst_mem[TEST_SIZE];
35
+	struct MY_BLOCK* mem_block;
36
+	char *p0,*p1,*p2,*p3,*p4,*p5,*p6,*p7,*p8,*p9;
37
+	int i, j, f;
38
+	char *p[TEST_RUN];
39
+	int t;
40
+
41
+	debug=7;
42
+	log_stderr=1;
43
+
44
+	printf("entering test\n");
45
+
46
+	mem_block=MY_INIT( tst_mem, TEST_SIZE );
47
+
48
+	/* coalesing test w/big fragments */
49
+	p0=ma(8194);
50
+	p1=ma(8194);
51
+	p2=ma(8194);
52
+	MY_STATUS(mem_block);
53
+	mf(p1);
54
+	mf(p0);
55
+	MY_STATUS(mem_block);
56
+	mf(p2);
57
+	MY_STATUS(mem_block);
58
+
59
+	/* reuse test w/big fragments */
60
+	p0=ma(8194);
61
+	p1=ma(4196);
62
+	mf(p0);
63
+	p0=ma(8190);
64
+	MY_STATUS(mem_block);
65
+	mf(p1);
66
+	mf(p0);
67
+	MY_STATUS(mem_block);
68
+
69
+
70
+	exit(0);
71
+
72
+	p0=ma(8);
73
+	p1=ma(24);
74
+	p2=ma(32);
75
+	p3=ma(32);
76
+	p4=ma(32);
77
+	p5=ma(1024);
78
+	p6=ma(2048);
79
+
80
+//	MY_STATUS(mem_block);
81
+
82
+//	*(p0+9)=0;
83
+	mf(p0);
84
+	mf(p2);
85
+	mf(p5);
86
+	mf(p6);
87
+	
88
+//	MY_STATUS(mem_block);
89
+
90
+	mf(p1);
91
+	mf(p4);
92
+	mf(p3);
93
+//	mf(p3);
94
+
95
+//	MY_STATUS(mem_block);
96
+
97
+	for (i=0;i<TEST_RUN;i++)
98
+		p[i]=ma( random() & 1023 );
99
+//	MY_STATUS(mem_block);
100
+	for (i=0;i<TEST_RUN;i++)
101
+		mf( p[i] );
102
+//	MY_STATUS(mem_block);
103
+
104
+	f = 0;
105
+#define GRANULARITY 100
106
+	for (j=0; j<LONG_RUN; j++) {
107
+		for (i=0;i<TEST_RUN;i++) {
108
+			t=random() & 1023;
109
+			if (! (t%24) ) t=(t+4096)*2;
110
+			p[i]=ma( random() & 1023 );
111
+		}
112
+		for (i=TEST_RUN/3;i<2*TEST_RUN/3;i++)
113
+			mf( p[i] );
114
+		for (i=TEST_RUN/3;i<2*TEST_RUN/3;i++) {
115
+			t=random() & 1023;
116
+			if (! (t%24) ) t=(t+4096)*2;
117
+			p[i]=ma( random() & 1023 );
118
+		}
119
+		for (i=0;i<TEST_RUN;i++)
120
+			mf( p[i] );
121
+		if ( GRANULARITY*j/LONG_RUN > f ) {
122
+			f=GRANULARITY*j/LONG_RUN ;
123
+			printf("%d%% done\n", f);
124
+		}
125
+	}
126
+	printf("now I'm really done\n");
127
+	MY_STATUS(mem_block);
128
+	printf("And I'm done with dumping final report too\n");
129
+	
130
+	exit(0);
131
+}
132
+
133
+#endif
0 134
similarity index 92%
1 135
rename from q_malloc.c
2 136
rename to mem/q_malloc.c
... ...
@@ -2,29 +2,29 @@
2 2
  *
3 3
  */
4 4
 
5
+#if !defined(q_malloc) && !(defined VQ_MALLOC)
5 6
 #define q_malloc
6
-#ifdef q_malloc
7 7
 
8 8
 #include "q_malloc.h"
9
-#include "dprint.h"
9
+#include "../dprint.h"
10 10
 
11 11
 
12
-/*usefull macros*/
12
+/*useful macros*/
13 13
 #define FRAG_END(f)  \
14
-			((struct qm_frag_end*)((char*)(f)+sizeof(struct qm_frag)+ \
15
-								   (f)->size))
14
+	((struct qm_frag_end*)((char*)(f)+sizeof(struct qm_frag)+ \
15
+	   (f)->size))
16 16
 
17 17
 #define FRAG_NEXT(f) \
18
-			((struct qm_frag*)((char*)(f)+sizeof(struct qm_frag)+(f)->size+ \
19
-							   sizeof(struct qm_frag_end)))
18
+	((struct qm_frag*)((char*)(f)+sizeof(struct qm_frag)+(f)->size+ \
19
+	   sizeof(struct qm_frag_end)))
20 20
 			
21 21
 #define FRAG_PREV(f) \
22
-		( (struct qm_frag*) ( ((char*)(f)-sizeof(struct qm_frag_end))- \
23
-		((struct qm_frag_end*)((char*)(f)-sizeof(struct qm_frag_end)))->size- \
24
-			sizeof(struct qm_frag) ) )
22
+	( (struct qm_frag*) ( ((char*)(f)-sizeof(struct qm_frag_end))- \
23
+	((struct qm_frag_end*)((char*)(f)-sizeof(struct qm_frag_end)))->size- \
24
+	   sizeof(struct qm_frag) ) )
25 25
 
26 26
 #define PREV_FRAG_END(f) \
27
-		((struct qm_frag_end*)((char*)(f)-sizeof(struct qm_frag_end)))
27
+	((struct qm_frag_end*)((char*)(f)-sizeof(struct qm_frag_end)))
28 28
 
29 29
 #ifdef DBG_QM_MALLOC
30 30
 #define ST_CHECK_PATTERN   0xf0f0f0f0
... ...
@@ -162,6 +162,9 @@ void* qm_malloc(struct qm_block* qm, unsigned int size)
162 162
 	unsigned int overhead;
163 163
 	
164 164
 #ifdef DBG_QM_MALLOC
165
+	unsigned int list_cntr;
166
+
167
+	list_cntr = 0;
165 168
 	DBG("qm_malloc(%x, %d) called from %s: %s(%d)\n", qm, size, file, func,
166 169
 			line);
167 170
 #endif
... ...
@@ -171,6 +174,10 @@ void* qm_malloc(struct qm_block* qm, unsigned int size)
171 174
 	if (qm->free_lst.u.nxt_free==&(qm->free_lst)) return 0;
172 175
 	/*search for a suitable free frag*/
173 176
 	for (f=qm->free_lst.u.nxt_free; f!=&(qm->free_lst); f=f->u.nxt_free){
177
+#ifdef DBG_QM_MALLOC
178
+		list_cntr++;
179
+#endif
180
+		
174 181
 		if (f->size>=size){
175 182
 			/* we found it!*/
176 183
 			/*detach it from the free list*/
... ...
@@ -220,8 +227,8 @@ void* qm_malloc(struct qm_block* qm, unsigned int size)
220 227
 			f->check=ST_CHECK_PATTERN;
221 228
 		/*  FRAG_END(f)->check1=END_CHECK_PATTERN1;
222 229
 			FRAG_END(f)->check2=END_CHECK_PATTERN2;*/
223
-	DBG("qm_malloc(%x, %d) returns address %x\n", qm, size,
224
-			(char*)f+sizeof(struct qm_frag) );
230
+	DBG("qm_malloc(%x, %d) returns address %x on %d -th hit\n", qm, size,
231
+			(char*)f+sizeof(struct qm_frag), list_cntr );
225 232
 #endif
226 233
 			return (char*)f+sizeof(struct qm_frag);
227 234
 		}
... ...
@@ -318,6 +325,8 @@ void qm_status(struct qm_block* qm)
318 325
 	int i;
319 326
 
320 327
 	LOG(L_INFO, "qm_status (%x):\n", qm);
328
+	if (!qm) return;
329
+
321 330
 	LOG(L_INFO, " heap size= %d\n", qm->size);
322 331
 	LOG(L_INFO, " used= %d, used+overhead=%d, free=%d\n",
323 332
 			qm->used, qm->real_used, qm->size-qm->real_used);
324 333
similarity index 96%
325 334
rename from q_malloc.h
326 335
rename to mem/q_malloc.h
... ...
@@ -3,7 +3,7 @@
3 3
  * simple & fast malloc library
4 4
  */
5 5
 
6
-#ifndef q_malloc_h
6
+#if !defined(q_malloc_h) && !defined(VQ_MALLOC)
7 7
 #define q_malloc_h
8 8
 
9 9
 
10 10
similarity index 92%
11 11
rename from shm_mem.c
12 12
rename to mem/shm_mem.c
... ...
@@ -6,7 +6,7 @@
6 6
 #ifdef SHM_MEM
7 7
 
8 8
 #include "shm_mem.h"
9
-#include "config.h"
9
+#include "../config.h"
10 10
 
11 11
 #ifdef  SHM_MMAP
12 12
 
... ...
@@ -37,9 +37,15 @@
37 37
 #ifndef SHM_MMAP
38 38
 static int shm_shmid=-1; /*shared memory id*/
39 39
 #endif
40
+
41
+
40 42
 int shm_semid=-1; /*semaphore id*/
41 43
 static void* shm_mempool=(void*)-1;
42
-struct qm_block* shm_block;
44
+#ifdef VQ_MALLOC
45
+	struct vqm_block* shm_block;
46
+#else
47
+	struct qm_block* shm_block;
48
+#endif
43 49
 
44 50
 
45 51
 
... ...
@@ -110,7 +116,11 @@ int shm_mem_init()
110 116
 		return -1;
111 117
 	}
112 118
 	/* init it for malloc*/
113
-	shm_block=qm_malloc_init(shm_mempool, SHM_MEM_SIZE);
119
+#	ifdef VQ_MALLOC
120
+		shm_block=vqm_malloc_init(shm_mempool, SHM_MEM_SIZE);
121
+#	else
122
+		shm_block=qm_malloc_init(shm_mempool, SHM_MEM_SIZE);
123
+#	endif
114 124
 	if (shm_block==0){
115 125
 		LOG(L_CRIT, "ERROR: shm_mem_init: could not initialize shared"
116 126
 				" malloc\n");
117 127
similarity index 76%
118 128
rename from shm_mem.h
119 129
rename to mem/shm_mem.h
... ...
@@ -25,10 +25,21 @@
25 25
 
26 26
 
27 27
 
28
-#include "q_malloc.h"
29
-#include "dprint.h"
30
-
31
-extern struct qm_block* shm_block;
28
+#include "../dprint.h"
29
+
30
+#ifdef VQ_MALLOC
31
+#	include "vq_malloc.h"
32
+	extern struct vqm_block* shm_block;
33
+#	define MY_MALLOC vqm_malloc
34
+#	define MY_FREE vqm_free
35
+#	define MY_STATUS vqm_status
36
+#else
37
+#	include "q_malloc.h"
38
+	extern struct qm_block* shm_block;
39
+#	define MY_MALLOC qm_malloc
40
+#	define MY_FREE qm_free
41
+#	define MY_STATUS qm_status
42
+#endif
32 43
 extern int shm_semid;
33 44
 
34 45
 int shm_mem_init();
... ...
@@ -94,7 +105,7 @@ again:
94 105
 	\
95 106
 	/*if (shm_lock()==0){*/\
96 107
 		shm_lock();\
97
-		p=qm_malloc(shm_block, (size), __FILE__, __FUNCTION__, __LINE__);\
108
+		p=MY_MALLOC(shm_block, (size), __FILE__, __FUNCTION__, __LINE__);\
98 109
 		shm_unlock();\
99 110
 	/* \
100 111
 	}else{ \
... ...
@@ -108,7 +119,7 @@ again:
108 119
 #define shm_free(p) \
109 120
 do { \
110 121
 		shm_lock(); \
111
-		qm_free(shm_block, (p), __FILE__, __FUNCTION__, __LINE__); \
122
+		MY_FREE(shm_block, (p), __FILE__, __FUNCTION__, __LINE__); \
112 123
 		shm_unlock(); \
113 124
 }while(0)
114 125
 
... ...
@@ -122,7 +133,7 @@ do { \
122 133
 	\
123 134
 	/*if (shm_lock()==0){*/\
124 135
 		shm_lock();\
125
-		p=qm_malloc(shm_block, (size));\
136
+		p=MY_MALLOC(shm_block, (size));\
126 137
 		shm_unlock();\
127 138
 	/* \
128 139
 	}else{ \
... ...
@@ -136,7 +147,7 @@ do { \
136 147
 #define shm_free(p) \
137 148
 do { \
138 149
 		shm_lock(); \
139
-		qm_free(shm_block, (p)); \
150
+		MY_FREE(shm_block, (p)); \
140 151
 		shm_unlock(); \
141 152
 }while(0)
142 153
 
... ...
@@ -147,7 +158,7 @@ do { \
147 158
 #define shm_status() \
148 159
 do { \
149 160
 		shm_lock(); \
150
-		qm_status(shm_block); \
161
+		MY_STATUS(shm_block); \
151 162
 		shm_unlock(); \
152 163
 }while(0)
153 164
 
154 165
new file mode 100644
... ...
@@ -0,0 +1,438 @@
1
+/* $Id$
2
+ *
3
+ * History: 
4
+ * merged from Andrei's qmalloc and many fragments from Regents 
5
+ * University of California NetBSD malloc used; see
6
+ * http://www.ajk.tele.fi/libc/stdlib/malloc.c.html#malloc for more
7
+ * details including redistribution policy; this policy asks for
8
+ * displaying the copyright:
9
+ * Copyright (c) 1983 Regents of the University of California.
10
+ * All rights reserved.
11
+ *
12
+ *
13
+ * About:
14
+ * aggressive, wasteful and very quick malloc library built for
15
+ * servers that continuously alocate and release chunks of only
16
+ * few sizes:
17
+ * - free lists are organized by size (which eliminates long list traversal 
18
+ *   thru short free chunks if a long one is asked)
19
+ * - quite a few sizes are supported --> this results in more waste
20
+ *    (unused place in a chunk) however memory can be well reused after
21
+ *    freeing
22
+ * - the last bucket holds unlikely, huge, variable length chunks;
23
+ *   they are maintained as stack growing from the opposite direction
24
+ *   of our heap; coalesing is enabled; stack-like first-fit used to
25
+ *   find free fragments
26
+ *
27
+ * TODO: possibly, some delayed coalescation wouldn't hurt; also, further
28
+ * optimization will certainly speed-up the entire process a lot; using
29
+ * knowledge of application as well as trying to make pipeline happy
30
+ * (from which I am sadly far away now)
31
+ * provides optimization space; trying to use other memory allocators
32
+ * to compare would be a great thing to do too;
33
+ *
34
+ * also, comparing to other memory allocaters (like Horde) would not
35
+ * be a bad idea: those folks have been doing that for ages and specifically
36
+ * Horde has been heavily optimized for multi-processor machines
37
+ *
38
+ * References:
39
+ *   - list of malloc implementations: http://www.cs.colorado.edu/~zorn/Malloc.html
40
+ *   - a white-paper: http://g.oswego.edu/dl/html/malloc.html
41
+ *   - Paul R. Wilson, Mark S. Johnstone, Michael Neely, and David Boles: 
42
+       ``Dynamic Storage Allocation: A Survey and Critical Review'' in International 
43
+       Workshop on Memory Management, September 1995, 
44
+       ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps
45
+ *   - ptmalloc: http://www.malloc.de/en/
46
+ *   - GNU C-lib malloc: http://www.gnu.org/manual/glibc-2.0.6/html_chapter/libc_3.html
47
+ *   - delorie malocs: http://www.delorie.com/djgpp/malloc/
48
+ */
49
+
50
+#ifdef VQ_MALLOC
51
+
52
+#include "../config.h"
53
+#include "../globals.h"
54
+#include "vq_malloc.h"
55
+#include "../dprint.h"
56
+
57
+#define BIG_BUCKET(_qm) ((_qm)->max_small_bucket+1)
58
+#define IS_BIGBUCKET(_qm, _bucket) ((_bucket)==BIG_BUCKET(_qm)) 
59
+
60
+#ifdef DBG_QM_MALLOC
61
+#define ASSERT(a)	\
62
+	my_assert(a, __LINE__, __FILE__, __FUNCTION__ )
63
+#else
64
+#define ASSERT(a)
65
+#endif
66
+
67
+#ifdef DBG_QM_MALLOC
68
+#	define MORE_CORE(_q,_b,_s) (more_core( (_q), (_b), (_s), file, func, line ))
69
+#else
70
+#	define MORE_CORE(_q,_b,_s) (more_core( (_q), (_b), (_s) ))
71
+#endif
72
+
73
+
74
+
75
+/* dimensioning buckets: define the step function constants for size2bucket */
76
+int s2b_step[] = {8, 16, 32, 64, 128, 256, 512, 1024, 1536, 2048, 2560, MAX_FIXED_BLOCK, EO_STEP };
77
+
78
+void my_assert( int assertation, int line, char *file, char *function )
79
+{
80
+	if (assertation) return;
81
+
82
+	LOG(L_CRIT,"CRIT: assertation failed in $s (%s:%d)\n",
83
+		function, file, line);
84
+	abort();
85
+}
86
+
87
+#ifdef DBG_QM_MALLOC
88
+static  void vqm_debug_frag(struct vqm_block* qm, struct vqm_frag* f)
89
+{
90
+
91
+	int r;
92
+
93
+	if (f->check!=ST_CHECK_PATTERN){
94
+		LOG(L_CRIT, "BUG: vqm_*: fragm. %x beginning overwritten(%x)!\n",
95
+				f, f->check);
96
+		vqm_status(qm);
97
+		abort();
98
+	};
99
+	if (memcmp(f->end_check, END_CHECK_PATTERN, END_CHECK_PATTERN_LEN)!=0) {
100
+		LOG(L_CRIT, "BUG: vqm_*: fragm. %x end overwritten(%*s)!\n",
101
+				f, END_CHECK_PATTERN_LEN, f->end_check );
102
+		vqm_status(qm);
103
+		abort();
104
+	}
105
+}
106
+#endif
107
+
108
+
109
+/* takes  demanded size without overhead as input, returns bucket number
110
+   and changed the demanded size to size really used including all
111
+   possible overhead
112
+ */
113
+unsigned char size2bucket( struct vqm_block* qm, int *size )
114
+{
115
+	unsigned char b;	
116
+	unsigned int real_size;
117
+	unsigned int exceeds;
118
+
119
+
120
+	real_size = *size+ sizeof(struct vqm_frag)+
121
+			sizeof(struct vqm_frag_end);
122
+#ifdef DBG_QM_MALLOC
123
+	real_size+=END_CHECK_PATTERN_LEN;
124
+#endif
125
+	real_size+=((exceeds = (real_size % 8 )) ? 8 - exceeds : 0);
126
+	ASSERT( !(real_size%8) );
127
+	/* "small" chunk sizes <=1k translated using a table */
128
+	if ( real_size < MAX_FIXED_BLOCK ) {
129
+		b = qm->s2b[ real_size ];
130
+		*size = qm->s2s[ real_size ];
131
+	/* there might be various allocations slightly 1>1k, I still
132
+	   don't want to be too agressive and increase useless 
133
+	   allocations in small steps
134
+    	*/	
135
+	} else {
136
+		b = BIG_BUCKET(qm); 
137
+		*size = MAX_FIXED_BLOCK + 
138
+			(real_size-MAX_FIXED_BLOCK+BLOCK_STEP) 
139
+			/ BLOCK_STEP * BLOCK_STEP;
140
+	}
141
+	/*size must be a multiple of 8*/
142
+	ASSERT( !(*size%8) );
143
+	return b;
144
+}
145
+
146
+
147
+/* init malloc and return a qm_block */
148
+struct vqm_block* vqm_malloc_init(char* address, unsigned int size)
149
+{
150
+	char* start;
151
+	struct vqm_block* qm;
152
+	unsigned int init_overhead;
153
+	unsigned char b;	/* bucket iterator */
154
+	unsigned int s;		/* size iterator */
155
+	char *end;
156
+	
157
+	/* make address and size multiple of 8*/
158
+	start=(char*)( ((unsigned int)address%8)?((unsigned int)address+8)/8*8:
159
+			(unsigned int)address);
160
+	if (size<start-address) return 0;
161
+	size-=(start-address);
162
+	if (size <8) return 0;
163
+	size=(size%8)?(size-8)/8*8:size;
164
+
165
+	init_overhead=sizeof(struct vqm_block);
166
+	if (size < init_overhead)
167
+	{
168
+		/* not enough mem to create our control structures !!!*/
169
+		return 0;
170
+	}
171
+	end = start + size;
172
+	qm=(struct vqm_block*)start;
173
+	memset(qm, 0, sizeof(struct vqm_block));
174
+	size-=init_overhead;
175
+
176
+	/* definition of the size2bucket table */
177
+	for (s=0, b=0; s<MAX_FIXED_BLOCK ; s++) {
178
+		while (s>s2b_step[b]) b++;
179
+		if (b>MAX_BUCKET) {
180
+			LOG(L_CRIT, "CRIT: vqm_malloc_init: attempt to install too many buckets,"
181
+				"s2b_step > MAX_BUCKET\n");
182
+			return 0;
183
+		}
184
+		qm->s2b[s] = b;
185
+		qm->s2s[s] = s2b_step[b];
186
+	}
187
+	qm->max_small_bucket = b;
188
+
189
+	/* from where we will draw memory */
190
+	qm->core = (char *) ( start + sizeof( struct vqm_block ) );
191
+	qm->free_core = size;
192
+	/* remember for bound checking */
193
+	qm->init_core = qm->core;
194
+	qm->core_end = end;
195
+	/* allocate big chunks from end */
196
+	qm->big_chunks = end;
197
+	
198
+	return qm;
199
+}
200
+
201
+
202
+
203
+struct vqm_frag *more_core(	struct vqm_block* qm, 
204
+				unsigned char bucket, unsigned int size
205
+#ifdef DBG_QM_MALLOC
206
+				, char *file, char *func, unsigned int line
207
+#endif
208
+			 ) 
209
+{
210
+	struct vqm_frag *new_chunk;
211
+	struct vqm_frag_end *end;
212
+
213
+	if (qm->free_core<size) return 0;
214
+
215
+	/* update core */
216
+	if (IS_BIGBUCKET(qm, bucket)) {
217
+		qm->big_chunks-=size;
218
+		new_chunk = (struct vqm_frag *) qm->big_chunks ;	
219
+	} else {
220
+		new_chunk = (struct vqm_frag *) qm->core;	
221
+		qm->core+=size;
222
+	}
223
+	qm->free_core-=size;
224
+
225
+	/* initialize the new fragment */
226
+	new_chunk->u.inuse.bucket = bucket;
227
+	new_chunk->size = size;
228
+
229
+	end=FRAG_END( new_chunk );
230
+	end->size=size;
231
+
232
+	return new_chunk;
233
+}
234
+
235
+static inline void vqm_detach_free( struct vqm_block* qm, struct vqm_frag* frag)
236
+{
237
+
238
+	struct vqm_frag *prev, *next;
239
+	struct vqm_frag_end *end;
240
+
241
+	prev=FRAG_END(frag)->prv_free; 
242
+	next=frag->u.nxt_free;
243
+
244
+	if (prev) prev->u.nxt_free=next; 
245
+	else qm->next_free[BIG_BUCKET(qm)]=next;
246
+
247
+	if (next) FRAG_END(next)->prv_free=prev; 
248
+	 
249
+}
250
+
251
+
252
+#ifdef DBG_QM_MALLOC
253
+void* vqm_malloc(struct vqm_block* qm, unsigned int size, 
254
+	char* file, char* func, unsigned int line)
255
+#else
256
+void* vqm_malloc(struct vqm_block* qm, unsigned int size)
257
+#endif
258
+{
259
+	struct vqm_frag *new_chunk, *f;
260
+	unsigned char bucket;
261
+	
262
+#ifdef DBG_QM_MALLOC
263
+	unsigned int demanded_size;
264
+	DBG("vqm_malloc(%x, %d) called from %s: %s(%d)\n", qm, size, file, func,
265
+			line);
266
+	demanded_size = size;
267
+#endif
268
+	new_chunk=0;
269
+    	/* what's the bucket? what's the total size incl. overhead? */
270
+	bucket = size2bucket( qm, &size );
271
+
272
+	if (IS_BIGBUCKET(qm, bucket)) {	/* the kilo-bucket uses first-fit */
273
+		DBG("vqm_malloc: processing a big fragment\n");
274
+		for (f=qm->next_free[bucket] ; f; f=f->u.nxt_free ) 
275
+			if (f->size>=size) { /* first-fit */
276
+				new_chunk=f;
277
+				VQM_DEBUG_FRAG(qm, f);
278
+				vqm_detach_free(qm,f);
279
+				break;
280
+			}
281
+	} else if (  (new_chunk=qm->next_free[ bucket ]) ) { /*fixed size bucket*/
282
+			VQM_DEBUG_FRAG(qm, new_chunk);
283
+			/*detach it from the head of bucket's free list*/
284
+			qm->next_free[ bucket ] = new_chunk->u.nxt_free;
285
+	}
286
+
287
+	if (!new_chunk) { /* no chunk can be reused; slice one from the core */
288
+		new_chunk=MORE_CORE( qm, bucket, size );
289
+		if (!new_chunk) return 0;
290
+	}
291
+	new_chunk->u.inuse.magic = FR_USED;
292
+	new_chunk->u.inuse.bucket=bucket;
293
+#ifdef DBG_QM_MALLOC
294
+	new_chunk->file=file;
295
+	new_chunk->func=func;
296
+	new_chunk->line=line;
297
+	new_chunk->demanded_size=demanded_size;
298
+	qm->usage[ bucket ]++;
299
+	DBG("vqm_malloc( %x, %d ) returns address %x in bucket %d, real-size %d \n",
300
+		qm, demanded_size, (char*)new_chunk+sizeof(struct vqm_frag), 
301
+		bucket, size );
302
+
303
+	new_chunk->end_check=(char*)new_chunk+sizeof(struct vqm_frag)+demanded_size;
304
+	memcpy(  new_chunk->end_check, END_CHECK_PATTERN, END_CHECK_PATTERN_LEN );
305
+	new_chunk->check=ST_CHECK_PATTERN;
306
+#endif
307
+	return (char*)new_chunk+sizeof(struct vqm_frag);
308
+}
309
+
310
+
311
+
312
+
313
+#ifdef DBG_QM_MALLOC
314
+void vqm_free(struct vqm_block* qm, void* p, char* file, char* func, 
315
+				unsigned int line)
316
+#else
317
+void vqm_free(struct vqm_block* qm, void* p)
318
+#endif
319
+{
320
+	struct vqm_frag *f, *next, *prev, *first_big;
321
+	unsigned char b;
322
+
323
+#ifdef DBG_QM_MALLOC
324
+	DBG("vqm_free(%x, %x), called from %s: %s(%d)\n", qm, p, file, func, line);
325
+	if (p>(void *)qm->core_end || p<(void*)qm->init_core){
326
+		LOG(L_CRIT, "BUG: vqm_free: bad pointer %x (out of memory block!) - "
327
+				"aborting\n", p);
328
+		abort();
329
+	}
330
+#endif
331
+	if (p==0) {
332
+		DBG("WARNING:vqm_free: free(0) called\n");
333
+		return;
334
+	}
335
+	f=(struct  vqm_frag*) ((char*)p-sizeof(struct vqm_frag));
336
+	b=f->u.inuse.bucket;
337
+#ifdef DBG_QM_MALLOC
338
+	VQM_DEBUG_FRAG(qm, f);
339
+	if ( ! FRAG_ISUSED(f) ) {
340
+		LOG(L_CRIT, "BUG: vqm_free: freeing already freed pointer,"
341
+				" first freed: %s: %s(%d) - aborting\n",
342
+				f->file, f->func, f->line);
343
+		abort();
344
+	}
345
+	if ( b>MAX_BUCKET ) {
346
+		LOG(L_CRIT, "BUG: vqm_free: fragment with too high bucket nr: "
347
+				"%d, allocated: %s: %s(%d) - aborting\n",
348
+				b, f->file, f->func, f->line); 
349
+		abort();
350
+	}
351
+	DBG("vqm_free: freeing %d bucket block alloc'ed from %s: %s(%d)\n", 
352
+		f->u.inuse.bucket, f->file, f->func, f->line);
353
+	f->file=file; f->func=func; f->line=line;
354
+	qm->usage[ f->u.inuse.bucket ]--;
355
+#endif
356
+	if (IS_BIGBUCKET(qm,b)) {
357
+		next=FRAG_NEXT(f);
358
+		if  ((char *)next +sizeof( struct vqm_frag) < qm->core_end) {
359
+			VQM_DEBUG_FRAG(qm, next);
360
+			if (! FRAG_ISUSED(next)) { /* coalescate with next fragment */
361
+				DBG("vqm_free: coalescated with next\n");
362
+				vqm_detach_free(qm, next);
363
+				f->size+=next->size;
364
+				FRAG_END(f)->size=f->size;
365
+			}
366
+		}
367
+		first_big = qm->next_free[b];
368
+		if (first_big &&  f>first_big) {
369
+			prev=FRAG_PREV(f);
370
+			VQM_DEBUG_FRAG(qm, prev);
371
+			if (!FRAG_ISUSED(prev)) { /* coalescate with prev fragment */
372
+				DBG("vqm_free: coalescated with prev\n");
373
+				vqm_detach_free(qm, prev );
374
+				prev->size+=f->size;
375
+				f=prev;
376
+				FRAG_END(f)->size=f->size;
377
+			}
378
+		}
379
+		if ((char *)f==qm->big_chunks) { /* release unused core */
380
+			DBG("vqm_free: big chunk released\n");
381
+			qm->free_core+=f->size;
382
+			qm->big_chunks+=f->size;
383
+			return;
384
+		}		
385
+		first_big = qm->next_free[b];
386
+		/* fix reverse link (used only for BIG_BUCKET */
387
+		if (first_big) FRAG_END(first_big)->prv_free=f;
388
+		FRAG_END(f)->prv_free=0;
389
+	} else first_big = qm->next_free[b];
390
+	f->u.nxt_free = first_big; /* also clobbers magic */
391
+	qm->next_free[b] = f;
392
+}
393
+
394
+void dump_frag( struct vqm_frag* f, int i )
395
+{
396
+	LOG(L_INFO, "    %3d. address=%x  real size=%d bucket=%d\n", i, 
397
+		(char*)f+sizeof(struct vqm_frag), f->size, f->u.inuse.bucket);
398
+#ifdef DBG_QM_MALLOC
399
+	LOG(L_INFO, "            demanded size=%d\n", f->demanded_size );
400
+	LOG(L_INFO, "            alloc'd from %s: %s(%d)\n",
401
+		f->file, f->func, f->line);
402
+	LOG(L_INFO, "        start check=%x, end check= %*s\n",
403
+			f->check, END_CHECK_PATTERN_LEN, f->end_check );
404
+#endif
405
+}
406
+
407
+void vqm_status(struct vqm_block* qm)
408
+{
409
+	struct vqm_frag* f;
410
+	unsigned int i,j,on_list;
411
+
412
+	LOG(L_INFO, "vqm_status (%x):\n", qm);
413
+	if (!qm) return;
414
+	LOG(L_INFO, " heap size= %d, available: %d\n", 
415
+		qm->core_end-qm->init_core, qm->free_core );
416
+	
417
+	LOG(L_INFO, "dumping unfreed fragments:\n");
418
+	for (f=(struct vqm_frag*)qm->init_core, i=0;(char*)f<(char*)qm->core;
419
+		f=FRAG_NEXT(f) ,i++) if ( FRAG_ISUSED(f) ) dump_frag(f, i);
420
+
421
+	LOG(L_INFO, "dumping unfreed big fragments:\n");
422
+    for (f=(struct vqm_frag*)qm->big_chunks,i=0;(char*)f<(char*)qm->core_end;
423
+		f=FRAG_NEXT(f) ,i++) if ( FRAG_ISUSED(f) ) dump_frag( f, i );
424
+
425
+#ifdef DBG_QM_MALLOC
426
+	DBG("dumping bucket statistics:\n");
427
+	for (i=0; i<=BIG_BUCKET(qm); i++) {
428
+		for(on_list=0, f=qm->next_free[i]; f; f=f->u.nxt_free ) on_list++;
429
+		LOG(L_DBG, "    %3d. bucket: in use: %d, on free list: %d\n", 
430
+			i, qm->usage[i], on_list );
431
+	}
432
+#endif
433
+	LOG(L_INFO, "-----------------------------\n");
434
+}
435
+
436
+
437
+
438
+#endif
0 439
new file mode 100644
... ...
@@ -0,0 +1,130 @@
1
+/* $Id$
2
+ *
3
+ */
4
+
5
+#if !defined(VQ_MALLOC_H) && defined(VQ_MALLOC)
6
+#define VQ_MALLOC_H
7
+
8
+#include "../config.h"
9
+
10
+
11
+/* indicates this fragment is not in use (must not be offset of valid
12
+   aligned fragment beginning
13
+*/
14
+#define	FR_USED		0xef
15
+
16
+/*useful macros*/
17
+#define FRAG_END(f)  \
18
+	((struct vqm_frag_end*)((char*)(f)-sizeof(struct vqm_frag_end)+ \
19
+	(f)->size))
20
+
21
+#define FRAG_NEXT(f) \
22
+	((struct vqm_frag*)((char*)(f)+(f)->size))
23
+
24
+#define PREV_FRAG_END(f) \
25
+	((struct vqm_frag_end*)((char*)(f)-sizeof(struct vqm_frag_end)))
26
+
27
+#define FRAG_PREV(f) \
28
+	( (struct vqm_frag*) ( (char*)(f) - PREV_FRAG_END(f)->size ))
29
+
30
+#define FRAG_ISUSED(f) \
31
+	((f)->u.inuse.magic==FR_USED)
32
+
33
+/* just a bumper for the step function */
34
+#define EO_STEP                         -1
35
+
36
+
37
+#ifdef DBG_QM_MALLOC
38
+#define ST_CHECK_PATTERN   	0xf0f0f0f0
39
+#define END_CHECK_PATTERN  	"sExP"
40
+#define END_CHECK_PATTERN_LEN 	4
41
+
42
+#define VQM_DEBUG_FRAG(qm, f) vqm_debug_frag( (qm), (f))
43
+#else
44
+#define VQM_DEBUG_FRAG(qm, f)
45
+#endif
46
+
47
+
48
+struct vqm_frag {
49
+	/* XXX */
50
+	/* total chunk size including all overhead/bellowfoot/roundings/etc */
51
+	/* useless as otherwise size implied by bucket (if I really want to save 
52
+       bytes, I'll remove it  from here */
53
+	unsigned int size;
54
+	union{
55
+		/* pointer to next chunk in a bucket if free */
56
+		struct vqm_frag* nxt_free; 
57
+		struct {   /* or bucket number if busy */
58
+			unsigned char magic;
59
+			unsigned char bucket;
60
+        } inuse;
61
+	} u;
62
+#ifdef DBG_QM_MALLOC
63
+	/* source code info */
64
+	char* file;
65
+	char* func;
66
+	unsigned int line;
67
+	/* your safety is important to us! safety signatures */
68
+	unsigned int check;
69
+	char *end_check;
70
+	/* the size user was originally asking for */
71
+	unsigned int demanded_size;
72
+#endif
73
+};
74
+
75
+struct vqm_frag_end{
76
+	/* total chunk size including all overhead/bellowfoot/roundings/etc */
77
+	unsigned int size; 
78
+	/* XXX */
79
+	/* used only for variable-size chunks; might have different
80