- malloc replacements
authorAndrei Pelinescu-Onciul <andrei@iptel.org>
Fri, 23 Nov 2001 09:29:00 +0000 (09:29 +0000)
committerAndrei Pelinescu-Onciul <andrei@iptel.org>
Fri, 23 Nov 2001 09:29:00 +0000 (09:29 +0000)
Makefile
data_lump.c
mem.h [new file with mode: 0644]
msg_parser.c
parse_via.c
q_malloc.c [new file with mode: 0644]
q_malloc.h [new file with mode: 0644]
receive.c
udp_server.c

index 6b95563..67b53c1 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -28,7 +28,7 @@ NAME=ser
 # DEBUG compiles in some extra debugging code
 # OLD_PARSER uses the old and stable parser (from ser 8.3.2)
 # DNS_IP_HACK faster ip address resolver for ip strings (e.g "127.0.0.1")
-DEFS=-DNOCR -DMACROEATER -DDNS_IP_HACK -DNO_DEBUG#-DSTATS -DNO_DEBUG 
+DEFS=-DNOCR -DMACROEATER -DDNS_IP_HACK #-DNO_DEBUG#-DSTATS -DNO_DEBUG 
 #-DNO_LOG
 
 PROFILE=  # -pg #set this if you want profiling
index 5fd84d7..c03f643 100644 (file)
@@ -4,6 +4,7 @@
 
 #include "data_lump.h"
 #include "dprint.h"
+#include "mem.h"
 
 #include <stdlib.h>
 
@@ -200,18 +201,18 @@ void free_lump_list(struct lump* l)
                r=crt->before;
                while(r){
                        foo=r; r=r->before;
-                       pkg_free_lump(foo);
+                       free_lump(foo);
                        pkg_free(foo);
                }
                r=crt->after;
                while(r){
                        foo=r; r=r->after;
-                       pkg_free_lump(foo);
+                       free_lump(foo);
                        pkg_free(foo);
                }
                
                /*clean current elem*/
-               pkg_free_lump(crt);
+               free_lump(crt);
                pkg_free(crt);
        }
 }
diff --git a/mem.h b/mem.h
new file mode 100644 (file)
index 0000000..a723909
--- /dev/null
+++ b/mem.h
@@ -0,0 +1,31 @@
+/* $Id$
+ *
+ * memory related stuff (malloc & friends)
+ * 
+ */
+
+
+#ifndef mem_h
+#define mem_h
+
+#ifdef PKG_MALLOC
+#include "q_malloc.h"
+
+extern struct qm_block* mem_block;
+
+
+#define pkg_malloc(s) qm_malloc(mem_block, s)
+#define pkg_free(p)   qm_free(mem_block, p)
+#define pkg_status()  qm_status(mem_block)
+
+#else
+#include <stdlib.h>
+
+#define pkg_malloc(s) malloc(s)
+#define pkg_free(p)  free(p)
+#define pkg_status()
+
+#endif
+
+
+#endif
index 79e3807..cb54d75 100644 (file)
@@ -13,6 +13,7 @@
 #include "ut.h"
 #include "error.h"
 #include "dprint.h"
+#include "mem.h"
 
 #ifdef DEBUG_DMALLOC
 #include <dmalloc.h>
@@ -928,4 +929,3 @@ void free_sip_msg(struct sip_msg* msg)
 
 
 
-}
index d0e54b6..385c098 100644 (file)
@@ -22,6 +22,7 @@
 #include "dprint.h"
 #include "msg_parser.h"
 #include "ut.h"
+#include "mem.h"
 
 
 
diff --git a/q_malloc.c b/q_malloc.c
new file mode 100644 (file)
index 0000000..9c51659
--- /dev/null
@@ -0,0 +1,232 @@
+/* $Id$
+ *
+ */
+
+#define q_malloc
+#ifdef q_malloc
+
+#include "q_malloc.h"
+#include "dprint.h"
+
+
+/*usefull macros*/
+#define FRAG_END(f)  \
+                       ((struct qm_frag_end*)((char*)f+sizeof(struct qm_frag)+f->size))
+
+#define FRAG_NEXT(f) \
+                       ((struct qm_frag*)((char*)f+sizeof(struct qm_frag)+f->size+ \
+                                                          sizeof(struct qm_frag_end)))
+                       
+#define FRAG_PREV(f) \
+               ( (struct qm_frag*) ( ((char*)f-sizeof(struct qm_frag_end))- \
+               ((struct qm_frag_end*)((char*)f-sizeof(struct qm_frag_end)))->size- \
+                       sizeof(struct qm_frag) ) )
+
+
+
+
+
+/* init malloc and return a qm_block*/
+struct qm_block* qm_malloc_init(char* address, unsigned int size)
+{
+       char* start;
+       char* end;
+       struct qm_block* qm;
+       unsigned int init_overhead;
+       unsigned int init_size;
+       
+       init_size=size;
+       /* make address and size multiple of 8*/
+       start=(char*)( ((unsigned int)address%8)?((unsigned int)address+8)/8*8:
+                       (unsigned int)address);
+       if (size<start-address) return 0;
+       size-=(start-address);
+       if (size <8) return 0;
+       size=(size%8)?(size-8)/8*8:size;
+       
+       init_overhead=sizeof(struct qm_block)+sizeof(struct qm_frag)+
+               sizeof(struct qm_frag_end);
+       if (size < init_overhead)
+       {
+               /* not enough mem to create our control structures !!!*/
+               return 0;
+       }
+       end=start+size;
+       qm=(struct qm_block*)start;
+       memset(qm, 0, sizeof(struct qm_block));
+       qm->init_size=init_size;
+       qm->size=size-init_overhead;
+       qm->real_used=init_overhead;
+       
+       qm->first_frag=(struct qm_frag*)(start+sizeof(struct qm_block));
+       qm->last_frag_end=(struct qm_frag_end*)(end-sizeof(struct qm_frag_end));
+       /* init initial fragment*/
+       qm->first_frag->size=size;
+       qm->first_frag->u.nxt_free=&(qm->free_lst);
+       qm->last_frag_end->size=size;
+       qm->last_frag_end->prev_free=&(qm->free_lst);
+       /* init free_lst* */
+       qm->free_lst.u.nxt_free=qm->first_frag;
+       qm->free_lst_end.prev_free=qm->first_frag;
+       qm->free_lst.size=0;
+       qm->free_lst_end.size=0;
+       
+       
+       return qm;
+}
+
+
+static inline void qm_insert_free(struct qm_block* qm, struct qm_frag* frag)
+{
+       struct qm_frag* f;
+       struct qm_frag* prev;
+
+       for(f=qm->free_lst.u.nxt_free; f!=&(qm->free_lst); f=f->u.nxt_free){
+               if (frag->size < f->size) break;
+       }
+       /*insert it here*/
+       prev=FRAG_END(f)->prev_free;
+       prev->u.nxt_free=frag;
+       FRAG_END(frag)->prev_free=prev;
+       frag->u.nxt_free=f;
+       FRAG_END(f)->prev_free=frag;
+}
+
+
+
+static inline void qm_detach_free(struct qm_block* qm, struct qm_frag* frag)
+{
+       struct qm_frag *prev;
+       struct qm_frag *next;
+       
+       struct qm_frag_end *end;
+
+       prev=FRAG_END(frag)->prev_free;
+       next=frag->u.nxt_free;
+       prev->u.nxt_free=next;
+       FRAG_END(next)->prev_free=prev;
+       
+}
+
+
+
+void* qm_malloc(struct qm_block* qm, unsigned int size)
+{
+       struct qm_frag* f;
+       struct qm_frag_end* end;
+       struct qm_frag* n;
+       unsigned int rest;
+       unsigned int overhead;
+       
+       /*size must be a multiple of 8*/
+       size=(size%8)?(size+8)/8*8:size;
+       if (size>(qm->size-qm->real_used)) return 0;
+       if (qm->free_lst.u.nxt_free==&(qm->free_lst)) return 0;
+       /*search for a suitable free frag*/
+       for (f=qm->free_lst.u.nxt_free; f!=&(qm->free_lst); f=f->u.nxt_free){
+               if (f->size>=size){
+                       /* we found it!*/
+                       /*detach it from the free list*/
+                       qm_detach_free(qm, f);
+                       /*mark it as "busy"*/
+                       f->u.is_free=0;
+                       
+                       /*see if we'll use full frag, or we'll split it in 2*/
+                       rest=f->size-size;
+                       overhead=sizeof(struct qm_frag)+sizeof(struct qm_frag_end);
+                       if (rest>overhead){
+                               f->size=size;
+                               /*split the fragment*/
+                               end=FRAG_END(f);
+                               end->size=size;
+                               n=(struct qm_frag*)((char*)end+sizeof(struct qm_frag_end));
+                               n->size=rest-overhead;
+                               FRAG_END(n)->size=n->size;
+                               qm->real_used+=overhead;
+                               /* reinsert n in free list*/
+                               qm_insert_free(qm, n);
+                       }else{
+                               /* we cannot split this fragment any more => alloc all of it*/
+                       }
+                       qm->real_used+=f->size;
+                       qm->used+=f->size;
+                       return (char*)f+sizeof(struct qm_frag);
+               }
+       }
+       return 0;
+}
+
+
+
+void qm_free(struct qm_block* qm, void* p)
+{
+       struct qm_frag* f;
+       struct qm_frag* prev;
+       struct qm_frag* next;
+       struct qm_frag_end *end;
+       unsigned int overhead;
+       unsigned int size;
+
+       if (p==0) {
+               DBG("WARNING:qm_free: free(0) called\n");
+               return;
+       }
+       prev=next=0;
+       f=(struct qm_frag*) ((char*)p-sizeof(struct qm_frag));
+       overhead=sizeof(struct qm_frag)+sizeof(struct qm_frag_end);
+       next=FRAG_NEXT(f);
+       size=f->size;
+       qm->used-=size;
+       qm->real_used-=size;
+       if (((char*)next < (char*)qm->last_frag_end) &&( next->u.is_free)){
+               /* join */
+               qm_detach_free(qm, next);
+               size+=next->size+overhead;
+               qm->real_used-=overhead;
+       }
+       
+       if (f > qm->first_frag){
+               prev=FRAG_PREV(f);
+               /*      (struct qm_frag*)((char*)f - (struct qm_frag_end*)((char*)f-
+                                                               sizeof(struct qm_frag_end))->size);*/
+               if (prev->u.is_free){
+                       /*join*/
+                       qm_detach_free(qm, prev);
+                       size+=prev->size+overhead;
+                       qm->real_used-=overhead;
+                       f=prev;
+               }
+       }
+       FRAG_END(f)->size=f->size;
+       qm_insert_free(qm, f);
+}
+
+
+
+void qm_status(struct qm_block* qm)
+{
+       struct qm_frag* f;
+       int i;
+
+       DBG("qm_status (%x):\n", qm);
+       DBG(" init_size= %d", qm->init_size);
+       DBG(" heap size= %d", qm->size);
+       DBG(" used= %d, used+overhead=%d, free=%d\n",
+                       qm->used, qm->real_used, qm->size-qm->real_used);
+       
+       DBG("dumping all fragments:\n");
+       for (f=qm->first_frag, i=0;(char*)f<(char*)qm->last_frag_end;f=FRAG_NEXT(f)
+                       ,i++)
+               DBG("    %3d. %c  address=%x  size=%d\n", i, (f->u.is_free)?'a':'N',
+                               (char*)f+sizeof(struct qm_frag), f->size);
+       DBG("dumping free list:\n");
+       for (f=qm->free_lst.u.nxt_free; f!=&(qm->free_lst); f=f->u.nxt_free)
+               DBG("    %3d. %c  address=%x  size=%d\n", i, (f->u.is_free)?'a':'N',
+                               (char*)f+sizeof(struct qm_frag), f->size);
+       DBG("-----------------------------\n");
+}
+
+
+
+
+#endif
diff --git a/q_malloc.h b/q_malloc.h
new file mode 100644 (file)
index 0000000..58582d5
--- /dev/null
@@ -0,0 +1,45 @@
+/* $Id$
+ *
+ * simple & fast malloc library
+ */
+
+#ifndef q_malloc_h
+#define q_malloc_h
+
+
+struct qm_frag{
+       unsigned int size;
+       union{
+               struct qm_frag* nxt_free;
+               int is_free;
+       }u;
+};
+
+struct qm_frag_end{
+       unsigned int size;
+       struct qm_frag* prev_free;
+};
+
+
+struct qm_block{
+       unsigned int init_size;
+       unsigned int size; /* total size */
+       unsigned int used; /* alloc'ed size*/
+       unsigned int real_used; /* used+malloc overhead*/
+       
+       struct qm_frag* first_frag;
+       struct qm_frag_end* last_frag_end;
+       
+       struct qm_frag free_lst;
+       struct qm_frag_end free_lst_end;
+};
+
+
+
+struct qm_block* qm_malloc_init(char* address, unsigned int size);
+void* qm_malloc(struct qm_block*, unsigned int size);
+void  qm_free(struct qm_block*, void* p);
+void  qm_status(struct qm_block*);
+
+
+#endif
index a9e8785..9b5c7ac 100644 (file)
--- a/receive.c
+++ b/receive.c
@@ -11,6 +11,7 @@
 #include "msg_parser.h"
 #include "forward.h"
 #include "action.h"
+#include "mem.h"
 
 
 #ifdef DEBUG_DMALLOC
@@ -27,7 +28,7 @@ int receive_msg(char* buf, unsigned int len, unsigned long src_ip)
 {
        struct sip_msg* msg;
 
-       msg=pkt_malloc(sizeof(struct sip_msg));
+       msg=pkg_malloc(sizeof(struct sip_msg));
        if (msg==0) goto error1;
        msg_no++;
 #ifdef STATS
@@ -41,7 +42,7 @@ int receive_msg(char* buf, unsigned int len, unsigned long src_ip)
        msg->src_ip=src_ip;
        msg->id=msg_no;
        /* make a copy of the message */
-       msg->orig=(char*) pkt_malloc(len+1);
+       msg->orig=(char*) pkg_malloc(len+1);
        if (msg->orig==0){
                LOG(L_ERR, "ERROR:receive_msg: memory allocation failure\n");
                goto error1;
@@ -108,7 +109,7 @@ int receive_msg(char* buf, unsigned int len, unsigned long src_ip)
 skip:
        DBG("skip:...\n");
        free_sip_msg(msg);
-       pkt_free(msg);
+       pkg_free(msg);
 #ifdef STATS
        if (skipped) update_received_drops;
 #endif
@@ -116,14 +117,14 @@ skip:
 error:
        DBG("error:...\n");
        free_sip_msg(msg);
-       pkt_free(msg);
+       pkg_free(msg);
 #ifdef STATS
        update_received_drops;
 #endif
        return -1;
 error1:
-       if (msg) pkt_free(msg);
-       pkt_free(buf);
+       if (msg) pkg_free(msg);
+       pkg_free(buf);
 #ifdef STATS
        update_received_drops;
 #endif
index a2fb5fa..66219a9 100644 (file)
@@ -14,6 +14,7 @@
 #include "config.h"
 #include "dprint.h"
 #include "receive.h"
+#include "mem.h"
 
 #ifdef DEBUG_DMALLOC
 #include <dmalloc.h>
@@ -153,7 +154,7 @@ int udp_rcv_loop()
        struct sockaddr* from;
        int fromlen;
 
-       buf=pkt_malloc(BUF_SIZE+1);
+       buf=pkg_malloc(BUF_SIZE+1);
        if (buf==0){
                LOG(L_ERR, "ERROR: udp_rcv_loop: could not allocate receive"
                                 " buffer\n");