/* mmgr/ph_mmgr.c. Generated from mmgr.c.in by configure. */
/*
** Copyright 2000-2004 University of Illinois Board of Trustees
** Copyright 2000-2004 Mark D. Roth
** All rights reserved.
**
** ph_mmgr.c - memory management code
**
** Mark D. Roth <roth@uiuc.edu>
** Campus Information Technologies and Educational Services
** University of Illinois at Urbana-Champaign
*/
#include <config.h>
#include <compat.h>
#include <ph_mmgr.h>
#include <errno.h>
#ifdef STDC_HEADERS
# include <stdlib.h>
#endif
/* useful macros */
#define BIT_ISSET(bitfield, opt) ((bitfield) & (opt))
#define BIT_SET(bitfield, opt) ((bitfield) |= (opt))
#define BIT_CLEAR(bitfield, opt) ((bitfield) &= ~(opt))
#define BIT_TOGGLE(bitfield, opt) { \
if (BIT_ISSET(bitfield, opt)) \
BIT_CLEAR(bitfield, opt); \
else \
BIT_SET(bitfield, opt); \
}
/* flags for internal use */
#define MMGR_VALID 1 /* memblock is valid */
#define MMGR_FOREIGN 2 /* used by _mmgr_register() */
#define MMGR_INTERNAL_MASK 255 /* mask for internal flags */
struct ph_mmgr
{
ph_memblock_t *mm_memblocks;
unsigned long mm_numblocks;
unsigned long mm_freeblock;
};
int
ph_mmgr_init(ph_mmgr_t *mmgrp)
{
*mmgrp = (ph_mmgr_t)calloc(1, sizeof(struct ph_mmgr));
if (*mmgrp == NULL)
return -1;
return 0;
}
void
ph_mmgr_cleanup(ph_mmgr_t mmgr)
{
int index;
for (index = 0; index < mmgr->mm_freeblock; index++)
ph_mmgr_free(mmgr->mm_memblocks + index, 1);
free(mmgr);
}
static int
_find_free_memblock(ph_mmgr_t mmgr)
{
void *ptr;
int index;
#ifdef MMGR_DEBUG
puts("==> _find_free_memblock()");
#endif
/* check if we can re-use previously-allocated memblocks */
for (index = 0; index < mmgr->mm_freeblock; index++)
if (! BIT_ISSET(mmgr->mm_memblocks[index].mb_flags, MMGR_VALID))
{
#ifdef MMGR_DEBUG
printf("<== _find_free_memblock(): returning %d\n",
index);
#endif
return index;
}
/* allocate new memblocks if needed */
if (mmgr->mm_freeblock >= mmgr->mm_numblocks)
{
ptr = realloc(mmgr->mm_memblocks,
(mmgr->mm_numblocks + 10) * sizeof(ph_memblock_t));
if (ptr == NULL)
{
#ifdef MMGR_DEBUG
printf("<== _find_free_memblock(): returning -1\n");
#endif
return -1;
}
mmgr->mm_memblocks = (ph_memblock_t *)ptr;
memset(mmgr->mm_memblocks + mmgr->mm_numblocks, 0,
sizeof(ph_memblock_t) * 10);
mmgr->mm_numblocks += 10;
}
#ifdef MMGR_DEBUG
printf("<== _find_free_memblock(): returning %d\n", mmgr->mm_freeblock);
#endif
return mmgr->mm_freeblock++;
}
int
ph_mmgr_malloc(ph_mmgr_t mmgr,
unsigned long flags,
size_t nelem,
size_t elsize,
ph_free_func_t freefunc,
ph_memblock_t **blockpp)
{
int index;
index = _find_free_memblock(mmgr);
if (index == -1)
return -1;
*blockpp = mmgr->mm_memblocks + index;
/* don't let caller set internal flags */
BIT_CLEAR(flags, MMGR_INTERNAL_MASK);
/* nelem is always set to 1 for non-arrays */
if (! BIT_ISSET(flags, ph_MMGR_ARRAY))
nelem = 1;
(*blockpp)->mb_flags = flags;
(*blockpp)->mb_elsize = elsize;
(*blockpp)->mb_nelem = nelem;
(*blockpp)->mb_freefunc = freefunc;
if ((nelem * elsize) == 0)
(*blockpp)->mb_ptr = NULL;
else
{
(*blockpp)->mb_ptr = calloc(nelem, elsize);
if ((*blockpp)->mb_ptr == NULL)
return -1;
}
/* now we can set the valid bit */
BIT_SET((*blockpp)->mb_flags, MMGR_VALID);
return 0;
}
int
ph_mmgr_register(ph_mmgr_t mmgr,
void *ptr,
ph_free_func_t freefunc,
ph_memblock_t **blockpp)
{
int index;
index = _find_free_memblock(mmgr);
if (index == -1)
return -1;
*blockpp = mmgr->mm_memblocks + index;
memset(*blockpp, 0, sizeof(ph_memblock_t));
(*blockpp)->mb_ptr = ptr;
(*blockpp)->mb_freefunc = freefunc;
(*blockpp)->mb_flags = (MMGR_VALID | MMGR_FOREIGN);
return 0;
}
int
ph_mmgr_array_add(ph_memblock_t *blockp, size_t nelem)
{
void *ptr;
size_t oldsize, newsize;
#ifdef MMGR_DEBUG
printf("==> ph_mmgr_array_add(blockp=0x%lx, nelem=%lu)\n",
blockp, (unsigned long)nelem);
#endif
oldsize = blockp->mb_elsize * blockp->mb_nelem;
newsize = blockp->mb_elsize * nelem;
#ifdef MMGR_DEBUG
printf(" ph_mmgr_array_add(): oldsize=%lu newsize=%lu\n",
(unsigned long)oldsize, (unsigned long)newsize);
#endif
ptr = realloc(blockp->mb_ptr, newsize);
if (ptr == NULL)
return -1;
blockp->mb_ptr = ptr;
blockp->mb_nelem = nelem;
if (newsize > oldsize)
{
ptr = (unsigned char *)ptr + oldsize;
memset(ptr, 0, newsize - oldsize);
}
return 0;
}
int
ph_mmgr_realloc(ph_memblock_t *blockp,
size_t newsize)
{
void *ptr;
ptr = realloc(blockp->mb_ptr, newsize);
if (ptr == NULL)
return -1;
blockp->mb_ptr = ptr;
if (newsize > blockp->mb_elsize)
{
ptr = (unsigned char *)ptr + blockp->mb_elsize;
memset(ptr, 0, newsize - blockp->mb_elsize);
}
blockp->mb_elsize = newsize;
return 0;
}
int
ph_mmgr_free(ph_memblock_t *blockp, int freeflag)
{
#ifdef MMGR_DEBUG
printf("==> ph_mmgr_free(blockp=0x%lx, freeflag=%d)\n",
blockp, freeflag);
#endif
if (!BIT_ISSET(blockp->mb_flags, MMGR_VALID))
return 0;
if (freeflag && blockp->mb_ptr != NULL)
(*(blockp->mb_freefunc))(blockp->mb_ptr);
BIT_CLEAR(blockp->mb_flags, MMGR_VALID);
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1