Statistics
| Branch: | Revision:

iof-bird-daemon / lib / mempool.c @ 92af6f30

History | View | Annotate | Download (3.06 KB)

1
/*
2
 *        BIRD Resource Manager -- Memory Pools
3
 *
4
 *        (c) 1998--1999 Martin Mares <mj@ucw.cz>
5
 *
6
 *        Can be freely distributed and used under the terms of the GNU GPL.
7
 */
8

    
9
#include <stdlib.h>
10
#include <string.h>
11

    
12
#include "nest/bird.h"
13
#include "lib/resource.h"
14

    
15
struct lp_chunk {
16
  struct lp_chunk *next;
17
  byte data[0];
18
};
19

    
20
struct linpool {
21
  resource r;
22
  byte *ptr, *end;
23
  struct lp_chunk *first, *current, **plast;        /* Normal (reusable) chunks */
24
  struct lp_chunk *first_large;                        /* Large chunks */
25
  unsigned chunk_size, threshold, total, total_large;
26
};
27

    
28
void lp_free(resource *);
29
void lp_dump(resource *);
30

    
31
static struct resclass lp_class = {
32
  "LinPool",
33
  sizeof(struct linpool),
34
  lp_free,
35
  lp_dump
36
};
37

    
38
linpool
39
*lp_new(pool *p, unsigned blk)
40
{
41
  linpool *m = ralloc(p, &lp_class);
42
  m->ptr = m->end = NULL;
43
  m->first = m->current = NULL;
44
  m->plast = &m->first;
45
  m->first_large = NULL;
46
  m->chunk_size = blk;
47
  m->threshold = 3*blk/4;
48
  m->total = m->total_large = 0;
49
  return m;
50
}
51

    
52
void *
53
lp_alloc(linpool *m, unsigned size)
54
{
55
  byte *a = (byte *) ALIGN((unsigned long) m->ptr, CPU_STRUCT_ALIGN);
56
  byte *e = a + size;
57

    
58
  if (e <= m->end)
59
    {
60
      m->ptr = e;
61
      return a;
62
    }
63
  else
64
    {
65
      struct lp_chunk *c;
66
      if (size >= m->threshold)
67
        {
68
          /* Too large => allocate large chunk */
69
          c = xmalloc(sizeof(struct lp_chunk) + size);
70
          m->total_large += size;
71
          c->next = m->first_large;
72
          m->first_large = c->next;
73
        }
74
      else
75
        {
76
          if (m->current)
77
            {
78
              /* Still have free chunks from previous incarnation (before lp_flush()) */
79
              c = m->current;
80
              m->current = c->next;
81
            }
82
          else
83
            {
84
              /* Need to allocate a new chunk */
85
              c = xmalloc(sizeof(struct lp_chunk) + m->chunk_size);
86
              m->total += m->chunk_size;
87
              *m->plast = c;
88
              m->plast = &c->next;
89
              c->next = NULL;
90
            }
91
          m->ptr = c->data + size;
92
          m->end = c->data + m->chunk_size;
93
        }
94
      return c->data;
95
    }
96
}
97

    
98
void *
99
lp_allocu(linpool *m, unsigned size)
100
{
101
  byte *a = m->ptr;
102
  byte *e = a + size;
103

    
104
  if (e <= m->end)
105
    {
106
      m->ptr = e;
107
      return a;
108
    }
109
  return lp_alloc(m, size);
110
}
111

    
112
void *
113
lp_allocz(linpool *m, unsigned size)
114
{
115
  void *z = lp_alloc(m, size);
116

    
117
  bzero(z, size);
118
  return z;
119
}
120

    
121
void
122
lp_flush(linpool *m)
123
{
124
  struct lp_chunk *c;
125

    
126
  /* Relink all normal chunks to free list and free all large chunks */
127
  m->ptr = m->end = NULL;
128
  m->current = m->first;
129
  while (c = m->first_large)
130
    {
131
      m->first_large = c->next;
132
      xfree(c);
133
    }
134
  m->total_large = 0;
135
}
136

    
137
void
138
lp_free(resource *r)
139
{
140
  linpool *m = (linpool *) r;
141
  struct lp_chunk *c, *d;
142

    
143
  for(d=m->first; d; d = c)
144
    {
145
      c = d->next;
146
      xfree(d);
147
    }
148
  for(d=m->first_large; d; d = c)
149
    {
150
      c = d->next;
151
      xfree(d);
152
    }
153
}
154

    
155
void
156
lp_dump(resource *r)
157
{
158
  linpool *m = (linpool *) r;
159
  struct lp_chunk *c;
160
  int cnt, cntl;
161

    
162
  for(cnt=0, c=m->first; c; c=c->next, cnt++)
163
    ;
164
  for(cntl=0, c=m->first_large; c; c=c->next, cntl++)
165
    ;
166
  debug("(chunk=%d threshold=%d count=%d+%d total=%d+%d)\n",
167
        m->chunk_size,
168
        m->threshold,
169
        cnt,
170
        cntl,
171
        m->total,
172
        m->total_large);
173
}