]> mj.ucw.cz Git - netgrind.git/blob - lib/pools.c
TODO: A note on IPv6
[netgrind.git] / lib / pools.c
1 /*
2  *      Sherlock Library -- Memory Pools (One-Time Allocation)
3  *
4  *      (c) 1997--2001 Martin Mares <mj@ucw.cz>
5  *
6  *      This software may be freely distributed and used according to the terms
7  *      of the GNU Lesser General Public License.
8  */
9
10 #include "lib/lib.h"
11 #include "lib/pools.h"
12
13 #include <stdlib.h>
14 #include <string.h>
15
16 struct memchunk {
17   struct memchunk *next;
18   byte data[0];
19 };
20
21 struct mempool *
22 mp_new(uns size)
23 {
24   struct mempool *p = xmalloc(sizeof(struct mempool));
25
26   size -= sizeof(struct memchunk);
27   p->free = p->last = NULL;
28   p->first = p->current = p->first_large = NULL;
29   p->plast = &p->first;
30   p->chunk_size = size;
31   p->threshold = size / 3;
32   return p;
33 }
34
35 void
36 mp_delete(struct mempool *p)
37 {
38   struct memchunk *c, *d;
39
40   for(d=p->first; d; d = c)
41     {
42       c = d->next;
43       xfree(d);
44     }
45   for(d=p->first_large; d; d = c)
46     {
47       c = d->next;
48       xfree(d);
49     }
50   xfree(p);
51 }
52
53 void
54 mp_flush(struct mempool *p)
55 {
56   struct memchunk *c;
57
58   p->free = p->last = NULL;
59   p->current = p->first;
60   while (c = p->first_large)
61     {
62       p->first_large = c->next;
63       xfree(c);
64     }
65 }
66
67 void *
68 mp_alloc(struct mempool *p, uns s)
69 {
70   if (s <= p->threshold)
71     {
72       byte *x = (byte *)(((uintptr_t) p->free + POOL_ALIGN - 1) & ~((uintptr_t) POOL_ALIGN - 1));
73       if (x + s > p->last)
74         {
75           struct memchunk *c;
76
77           if (p->current)
78             {
79               /* Still have free chunks from previous incarnation */
80               c = p->current;
81               p->current = c->next;
82             }
83           else
84             {
85               c = xmalloc(sizeof(struct memchunk) + p->chunk_size);
86               *p->plast = c;
87               p->plast = &c->next;
88               c->next = NULL;
89             }
90           x = c->data;
91           p->last = x + p->chunk_size;
92         }
93       p->free = x + s;
94       return x;
95     }
96   else
97     {
98       struct memchunk *c = xmalloc(sizeof(struct memchunk) + s);
99       c->next = p->first_large;
100       p->first_large = c;
101       return c->data;
102     }
103 }
104
105 void *
106 mp_alloc_zero(struct mempool *p, uns s)
107 {
108   void *x = mp_alloc(p, s);
109   bzero(x, s);
110   return x;
111 }