/*
Calisto (c) 1998-1999 Peter Howkins, Matthew Howkins, Simon Howkins
$Id: pool.c,v 1.3 1999/12/28 19:50:34 peter Exp $
$Log: pool.c,v $
Revision 1.3 1999/12/28 19:50:34 peter
Created pool_stat() to return information for debugging
Revision 1.2 1999/12/12 19:20:13 peter
Added guards, changed blk to blkhead and blktail
Revision 1.1 1999/12/12 18:52:08 peter
Initial revision
*/
static char rcsid[] = "$Id: pool.c,v 1.3 1999/12/28 19:50:34 peter Exp $";
#include <stdio.h>
#include <stdlib.h>
#include "pool.h"
#define BLKS_PER_GRP 10
#define GUARD1 0x12345678
#define GUARD2 0x87654321
typedef struct blkhead blkhead;
struct blkhead {
pool *p;
blkhead *nextfree;
unsigned guard1;
};
typedef struct {
unsigned guard2;
} blktail;
typedef struct blkgrp blkgrp;
struct blkgrp {
blkgrp *next;
/* blkhead b[UNKNOWN];*/
};
struct pool {
blkgrp *first;
blkhead *free;
size_t block_size;
unsigned usage;
unsigned capacity;
};
pool *pool_create(size_t block_size) {
pool *p;
p = malloc(sizeof(pool));
if (p) {
p->free = NULL;
p->first = NULL;
p->block_size = block_size + sizeof(blkhead) + sizeof(blktail);
p->usage = 0;
p->capacity = 0;
}
return p;
}
/* void pool_destroy(pool *pool); */
void *pool_malloc(pool *p) {
if (!p->free)
{
blkgrp *bg;
bg = malloc(sizeof(blkgrp) + BLKS_PER_GRP * p->block_size);
if (!bg)
return NULL;
{
blkhead *b = (blkhead *)(bg + 1);
int i;
/* Add blks in this group to free list */
for (i = 0; i < BLKS_PER_GRP; i++)
{
blktail *bt; /* pointer to tail of current blk */
b->guard1 = GUARD1;
b->nextfree = p->free;
p->free = b;
/* Move b to next blkhead */
b = (blkhead *) ( (char *)b + p->block_size);
/* Move back from next blkhead to previous blktail */
bt = (blktail *) ((char *) b - sizeof(blktail));
bt->guard2 = GUARD2;
}
p->capacity += BLKS_PER_GRP;
}
}
{
blkhead *b;
b = p->free;
p->free = b->nextfree;
b->p = p;
p->usage++;
return b + 1;
}
}
void pool_free(void *ptr) {
if (ptr) {
blkhead *bh = (blkhead *) (((char *) ptr) - sizeof(blkhead));
pool *p = bh->p;
/* Check guard1 */
if (bh->guard1 != GUARD1) {
fprintf(stderr, "Pool: overran start of block %p\n", ptr);
return;
}
{
blktail *bt = (blktail *) ((char *) bh + p->block_size - sizeof(blktail));
/* Check guard2 */
if (bt->guard2 != GUARD2) {
fprintf(stderr, "Pool: overran end of block %p\n", ptr);
return;
}
}
/* Free up block */
bh->nextfree = p->free;
p->free = bh;
p->usage--;
}
}
void pool_debug(const pool *p)
{
printf("block size: %d\n", p->block_size - sizeof(blkhead) - sizeof(blktail));
printf("usage : %d\n", p->usage);
printf("capacity : %d\n", p->capacity);
}
pool_stat_t pool_stat(const pool *p)
{
pool_stat_t ps;
ps.block_size = p->block_size;
ps.usage = p->usage;
ps.capacity = p->capacity;
return ps;
}