"Fossies" - the Fresh Open Source Software Archive

Member "rbldnsd-0.998/mempool.c" (6 Apr 2013, 3819 Bytes) of package /linux/misc/dns/rbldnsd-0.998.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "mempool.c" see the Fossies "Dox" file reference documentation.

    1 /* memory pool implementation
    2  */
    3 
    4 #include <stdlib.h>
    5 #include <string.h>
    6 #include "mempool.h"
    7 
    8 /* A pool of constant (in size) memory blocks which will be
    9  * freed all at once.  We allocate memory in (relatively)
   10  * large chunks (MEMPOOL_CHUNKSIZE) and keep list of chunks
   11  * with some free space within them and list of chunks without
   12  * sufficient free space.  Mempool is optimized to allocate
   13  * blocks of approximate equal size (determined dynamically),
   14  * so free chunks are moved to "used" list when free space
   15  * becomes less than an average allocated block size.
   16  */
   17 
   18 #define alignto sizeof(void*)
   19 #define alignmask (alignto-1)
   20 
   21 void *emalloc(unsigned size);
   22 
   23 #define MEMPOOL_CHUNKSIZE (65536-sizeof(unsigned)*4)
   24 
   25 struct mempool_chunk {
   26   char buf[MEMPOOL_CHUNKSIZE+alignto];
   27   struct mempool_chunk *next;
   28   unsigned size;
   29 };
   30 
   31 struct mempool_cfull { /* pseudo-chunk: one entry into full list */
   32   struct mempool_chunk *next;
   33   char buf[1];
   34 };
   35 
   36 void mp_init(struct mempool *mp) {
   37   mp->mp_chunk = mp->mp_fullc = NULL;
   38   mp->mp_nallocs = mp->mp_datasz = 0;
   39   mp->mp_lastbuf = NULL;
   40   mp->mp_lastlen = 0;
   41 }
   42 
   43 void *mp_alloc(struct mempool *mp, unsigned size, int align) {
   44   if (size >= MEMPOOL_CHUNKSIZE / 2) {
   45     /* for large blocks, allocate separate "full" chunk */
   46     struct mempool_cfull *c =
   47       (struct mempool_cfull*)emalloc(sizeof(*c)+size-1);
   48     if (!c)
   49       return NULL;
   50     c->next = mp->mp_fullc;
   51     mp->mp_fullc = (struct mempool_chunk*)c;
   52     return c->buf;
   53   }
   54   else {
   55     struct mempool_chunk *c;
   56     struct mempool_chunk *best; /* "best fit" chunk */
   57     unsigned avg; /* average data size: total size / numallocs */
   58 
   59     ++mp->mp_nallocs; mp->mp_datasz += size;
   60     avg = mp->mp_datasz / mp->mp_nallocs;
   61 
   62     /* round size up to a multiple of alignto */
   63     if (align)
   64       size = (size + alignmask) & ~alignmask;
   65 
   66     for(c = mp->mp_chunk, best = NULL; c; c = c->next)
   67       if (c->size >= size && (!best || best->size > c->size)) {
   68         best = c;
   69         if (c->size - size < avg)
   70           break;
   71       }
   72     
   73     if (best != NULL) { /* found a free chunk */
   74       char *b;
   75       if (align)
   76         best->size &= ~alignmask;
   77       b = best->buf + MEMPOOL_CHUNKSIZE - best->size;
   78       best->size -= size;
   79       if (best->size < avg) {
   80         struct mempool_chunk **cp = &mp->mp_chunk;
   81         while(*cp != best)
   82           cp = &(*cp)->next;
   83         *cp = best->next;
   84         best->next = mp->mp_fullc;
   85         mp->mp_fullc = best;
   86       }
   87       return b;
   88     }
   89 
   90     else { /* no sutable chunks -> allocate new one */
   91       c = (struct mempool_chunk *)emalloc(sizeof(*c));
   92       if (!c)
   93         return NULL;
   94       c->next = mp->mp_chunk;
   95       mp->mp_chunk = c;
   96       c->size = MEMPOOL_CHUNKSIZE - size;
   97       return c->buf;
   98     }
   99   }
  100 }
  101 
  102 void mp_free(struct mempool *mp) {
  103   struct mempool_chunk *c;
  104   while((c = mp->mp_chunk) != NULL) {
  105     mp->mp_chunk = c->next;
  106     free(c);
  107   }
  108   while((c = mp->mp_fullc) != NULL) {
  109     mp->mp_fullc = c->next;
  110     free(c);
  111   }
  112   mp_init(mp);
  113 }
  114 
  115 void *mp_memdup(struct mempool *mp, const void *buf, unsigned len) {
  116   void *b = mp_alloc(mp, len, 0);
  117   if (b)
  118     memcpy(b, buf, len);
  119   return b;
  120 }
  121 
  122 char *mp_strdup(struct mempool *mp, const char *str) {
  123   return (char*)mp_memdup(mp, str, strlen(str) + 1);
  124 }
  125 
  126 /* string pool: a pool of _constant_ strings, with minimal
  127  * elimination of dups (only last request is checked)
  128  */
  129 
  130 const void *mp_dmemdup(struct mempool *mp, const void *buf, unsigned len) {
  131   if (mp->mp_lastlen == len && memcmp(mp->mp_lastbuf, buf, len) == 0)
  132     return mp->mp_lastbuf;
  133   else if ((buf = mp_memdup(mp, buf, len)) != NULL)
  134     mp->mp_lastbuf = buf, mp->mp_lastlen = len;
  135   return buf;
  136 }
  137 
  138 const char *mp_dstrdup(struct mempool *mp, const char *str) {
  139   return (const char*)mp_dmemdup(mp, str, strlen(str) + 1);
  140 }