Statistics
| Branch: | Revision:

iof-bird-daemon / lib / resource.c @ 5cc1e1f8

History | View | Annotate | Download (6.38 KB)

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

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

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

    
16
/**
17
 * DOC: Resource pools
18
 *
19
 * Resource pools (&pool) are just containers holding a list of
20
 * other resources. Freeing a pool causes all the listed resources
21
 * to be freed as well. Each existing &resource is linked to some pool
22
 * except for a root pool which isn't linked anywhere, so all the
23
 * resources form a tree structure with internal nodes corresponding
24
 * to pools and leaves being the other resources.
25
 *
26
 * Example: Almost all modules of BIRD have their private pool which
27
 * is freed upon shutdown of the module.
28
 */
29

    
30
struct pool {
31
  resource r;
32
  list inside;
33
  char *name;
34
};
35

    
36
static void pool_dump(resource *);
37
static void pool_free(resource *);
38
static resource *pool_lookup(resource *, unsigned long);
39

    
40
static struct resclass pool_class = {
41
  "Pool",
42
  sizeof(pool),
43
  pool_free,
44
  pool_dump,
45
  pool_lookup
46
};
47

    
48
pool root_pool;
49

    
50
static int indent;
51

    
52
/**
53
 * rp_new - create a resource pool
54
 * @p: parent pool
55
 * @name: pool name (to be included in debugging dumps)
56
 *
57
 * rp_new() creates a new resource pool inside the specified
58
 * parent pool.
59
 */
60
pool *
61
rp_new(pool *p, char *name)
62
{
63
  pool *z = ralloc(p, &pool_class);
64
  z->name = name;
65
  init_list(&z->inside);
66
  return z;
67
}
68

    
69
static void
70
pool_free(resource *P)
71
{
72
  pool *p = (pool *) P;
73
  resource *r, *rr;
74

    
75
  r = HEAD(p->inside);
76
  while (rr = (resource *) r->n.next)
77
    {
78
      r->class->free(r);
79
      xfree(r);
80
      r = rr;
81
    }
82
}
83

    
84
static void
85
pool_dump(resource *P)
86
{
87
  pool *p = (pool *) P;
88
  resource *r;
89

    
90
  debug("%s\n", p->name);
91
  indent += 3;
92
  WALK_LIST(r, p->inside)
93
    rdump(r);
94
  indent -= 3;
95
}
96

    
97
static resource *
98
pool_lookup(resource *P, unsigned long a)
99
{
100
  pool *p = (pool *) P;
101
  resource *r, *q;
102

    
103
  WALK_LIST(r, p->inside)
104
    if (r->class->lookup && (q = r->class->lookup(r, a)))
105
      return q;
106
  return NULL;
107
}
108

    
109
/**
110
 * rfree - free a resource
111
 * @res: resource
112
 *
113
 * rfree() frees the given resource and all information associated
114
 * with it. In case it's a resource pool, it also frees all the objects
115
 * living inside the pool.
116
 *
117
 * It works by calling a class-specific freeing function.
118
 */
119
void
120
rfree(void *res)
121
{
122
  resource *r = res;
123

    
124
  if (r)
125
    {
126
      if (r->n.next)
127
        rem_node(&r->n);
128
      r->class->free(r);
129
      xfree(r);
130
    }
131
}
132

    
133
/**
134
 * rdump - dump a resource
135
 * @res: resource
136
 *
137
 * This function prints out all available information about the given
138
 * resource to the debugging output.
139
 *
140
 * It works by calling a class-specific dump function.
141
 */
142
void
143
rdump(void *res)
144
{
145
  char x[16];
146
  resource *r = res;
147

    
148
  bsprintf(x, "%%%ds%%08x ", indent);
149
  debug(x, "", (int) r);
150
  if (r)
151
    {
152
      debug("%s ", r->class->name);
153
      r->class->dump(r);
154
    }
155
  else
156
    debug("NULL\n");
157
}
158

    
159
/**
160
 * ralloc - create a resource
161
 * @p: pool to create the resource in
162
 * @c: class of the new resource
163
 *
164
 * This function is called by the resource classes to create a new
165
 * resource of the specified class and link it to the given pool.
166
 * Size of the resource structure is taken from the @size field
167
 * of the &resclass.
168
 */
169
void *
170
ralloc(pool *p, struct resclass *c)
171
{
172
  resource *r = xmalloc(c->size);
173

    
174
  r->class = c;
175
  add_tail(&p->inside, &r->n);
176
  return r;
177
}
178

    
179
/**
180
 * rlookup - look up a memory location
181
 * @a: memory address
182
 *
183
 * This function examines all existing resources to see whether
184
 * the address @a is inside any resource. It's used for debugging
185
 * purposes only.
186
 *
187
 * It works by calling a class-specific lookup function for each
188
 * resource.
189
 */
190
void
191
rlookup(unsigned long a)
192
{
193
  resource *r;
194

    
195
  debug("Looking up %08lx\n", a);
196
  if (r = pool_lookup(&root_pool.r, a))
197
    rdump(r);
198
  else
199
    debug("Not found.\n");
200
}
201

    
202
/**
203
 * resource_init - initialize the resource manager
204
 *
205
 * This function is called during BIRD startup. It initializes
206
 * all data structures of the resource manager and creates the
207
 * root pool.
208
 */
209
void
210
resource_init(void)
211
{
212
  root_pool.r.class = &pool_class;
213
  root_pool.name = "Root";
214
  init_list(&root_pool.inside);
215
}
216

    
217
/**
218
 * DOC: Memory blocks
219
 *
220
 * Memory blocks are pieces of contiguous allocated memory.
221
 * They are a bit non-standard since they are represented not by a pointer
222
 * to &resource, but by a void pointer to the start of data of the
223
 * memory block. All memory block functions know how to locate the header
224
 * given the data pointer.
225
 *
226
 * Example: All "unique" data structures such as hash tables are allocated
227
 * as memory blocks.
228
 */
229

    
230
struct mblock {
231
  resource r;
232
  unsigned size;
233
  byte data[0];
234
};
235

    
236
static void mbl_free(resource *r)
237
{
238
}
239

    
240
static void mbl_debug(resource *r)
241
{
242
  struct mblock *m = (struct mblock *) r;
243

    
244
  debug("(size=%d)\n", m->size);
245
}
246

    
247
static resource *
248
mbl_lookup(resource *r, unsigned long a)
249
{
250
  struct mblock *m = (struct mblock *) r;
251

    
252
  if ((unsigned long) m->data <= a && (unsigned long) m->data + m->size > a)
253
    return r;
254
  return NULL;
255
}
256

    
257
static struct resclass mb_class = {
258
  "Memory",
259
  0,
260
  mbl_free,
261
  mbl_debug,
262
  mbl_lookup
263
};
264

    
265
/**
266
 * mb_alloc - allocate a memory block
267
 * @p: pool
268
 * @size: size of the block
269
 *
270
 * mb_alloc() allocates memory of a given size and creates
271
 * a memory block resource representing this memory chunk
272
 * in the pool @p.
273
 *
274
 * Please note that mb_alloc() returns a pointer to the memory
275
 * chunk, not to the resource, hence you have to free it using
276
 * mb_free(), not rfree().
277
 */
278
void *
279
mb_alloc(pool *p, unsigned size)
280
{
281
  struct mblock *b = xmalloc(sizeof(struct mblock) + size);
282

    
283
  b->r.class = &mb_class;
284
  add_tail(&p->inside, &b->r.n);
285
  b->size = size;
286
  return b->data;
287
}
288

    
289
/**
290
 * mb_allocz - allocate and clear a memory block
291
 * @p: pool
292
 * @size: size of the block
293
 *
294
 * mb_allocz() allocates memory of a given size, initializes it to
295
 * zeroes and creates a memory block resource representing this memory
296
 * chunk in the pool @p.
297
 *
298
 * Please note that mb_alloc() returns a pointer to the memory
299
 * chunk, not to the resource, hence you have to free it using
300
 * mb_free(), not rfree().
301
 */
302
void *
303
mb_allocz(pool *p, unsigned size)
304
{
305
  void *x = mb_alloc(p, size);
306
  bzero(x, size);
307
  return x;
308
}
309

    
310
/**
311
 * mb_free - free a memory block
312
 * @m: memory block
313
 *
314
 * mb_free() frees all memory associated with the block @m.
315
 */
316
void
317
mb_free(void *m)
318
{
319
  struct mblock *b = SKIP_BACK(struct mblock, data, m);
320
  rfree(b);
321
}