... | ... |
@@ -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) |
... | ... |
@@ -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, |
... | ... |
@@ -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); |
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 |