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