1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
|
/*
* Copyright (c) 2003-2010 Alexandre Ratchov <alex@caoua.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* a pool is a large memory block (the pool) that is split into
* small blocks of equal size (pools entries). Its used for
* fast allocation of pool entries. Free enties are on a singly
* linked list
*/
#include "utils.h"
#include "pool.h"
unsigned pool_debug = 0;
/*
* initialises a pool of "itemnum" elements of size "itemsize"
*/
void
pool_init(struct pool *o, char *name, unsigned itemsize, unsigned itemnum)
{
unsigned i;
unsigned char *p;
/*
* round item size to sizeof unsigned
*/
if (itemsize < sizeof(struct poolent)) {
itemsize = sizeof(struct poolent);
}
itemsize += sizeof(unsigned) - 1;
itemsize &= ~(sizeof(unsigned) - 1);
o->data = xmalloc(itemsize * itemnum, "pool");
if (!o->data) {
log_puts("pool_init(");
log_puts(name);
log_puts("): out of memory\n");
panic();
}
o->first = NULL;
o->itemsize = itemsize;
o->itemnum = itemnum;
o->name = name;
#ifdef POOL_DEBUG
o->maxused = 0;
o->used = 0;
o->newcnt = 0;
#endif
/*
* create a linked list of all entries
*/
p = o->data;
for (i = itemnum; i != 0; i--) {
((struct poolent *)p)->next = o->first;
o->first = (struct poolent *)p;
p += itemsize;
o->itemnum++;
}
}
/*
* free the given pool
*/
void
pool_done(struct pool *o)
{
xfree(o->data);
#ifdef POOL_DEBUG
if (o->used != 0) {
log_puts("pool_done(");
log_puts(o->name);
log_puts("): WARNING ");
log_putu(o->used);
log_puts(" items still allocated\n");
}
if (pool_debug) {
log_puts("pool_done(");
log_puts(o->name);
log_puts("): using ");
log_putu((1023 + o->itemnum * o->itemsize) / 1024);
log_puts("kB maxused = ");
log_putu(100 * o->maxused / o->itemnum);
log_puts("% allocs = ");
log_putu(100 * o->newcnt / o->itemnum);
log_puts("%\n");
}
#endif
}
/*
* allocate an entry from the pool: just unlink
* it from the free list and return the pointer
*/
void *
pool_new(struct pool *o)
{
#ifdef POOL_DEBUG
unsigned i;
unsigned char *buf;
#endif
struct poolent *e;
if (!o->first) {
log_puts("pool_new(");
log_puts(o->name);
log_puts("): pool is empty\n");
panic();
}
/*
* unlink from the free list
*/
e = o->first;
o->first = e->next;
#ifdef POOL_DEBUG
o->newcnt++;
o->used++;
if (o->used > o->maxused)
o->maxused = o->used;
/*
* overwrite the entry with garbage so any attempt to use
* uninitialized memory will probably segfault
*/
buf = (unsigned char *)e;
for (i = o->itemsize; i > 0; i--)
*(buf++) = 0xd0;
#endif
return e;
}
/*
* free an entry: just link it again on the free list
*/
void
pool_del(struct pool *o, void *p)
{
struct poolent *e = (struct poolent *)p;
#ifdef POOL_DEBUG
unsigned i;
unsigned char *buf;
/*
* check if we aren't trying to free more
* entries than the poll size
*/
if (o->used == 0) {
log_puts("pool_del(");
log_puts(o->name);
log_puts("): pool is full\n");
panic();
}
o->used--;
/*
* overwrite the entry with garbage so any attempt to use a
* free entry will probably segfault
*/
buf = (unsigned char *)e;
for (i = o->itemsize; i > 0; i--)
*(buf++) = 0xdf;
#endif
/*
* link on the free list
*/
e->next = o->first;
o->first = e;
}
|