Listing 2: The HeapManager implementation
/*
* HEAPMGR.C
* 32-bit OS/2 heap management library.
*
*/
#define INCL_DOSMEMMGR
#define INCL_DOSPROCESS
#include <os2.h>
#include <stdio.h>
#include "heapmgr.h"
/*
* Completion of struct _heap
*
*/
HEAP {
size_t size,
free,
blocks;
void *base;
};
/*
* Round up to boundary
* (does not round negative numbers correctly)
*
*/
#define ROUNDUP(num,bdry) ((((num)+(bdry)-1)/(bdry))*(bdry))
/* * * * * * * create & destroy heap * * * * * * */
HEAP *createHeap(size_t size)
{
HEAP heap, *retval;
size = ROUNDUP(size,64*1024); /* DosAllocMem() rounds anyway */
heap.size = size;
heap.free = size - 64; /* size less system control info */
heap.blocks = 0;
heap.base = 0;
if ( size == 0 || DosAllocMem(&heap.base,size,PAG_READ | PAG_WRITE) )
return 0;
if ( DosSubSetMem(heap.base,
DOSSUB_INIT | DOSSUB_SPARSE_OBJ | DOSSUB_SERIALIZE,
size) ) {
DosFreeMem(heap.base);
return 0;
}
if ( !DosSubAllocMem(heap.base,(void **)&retval,sizeof(heap)) ) {
heap.free -= sizeof(heap) + sizeof(int);
*retval = heap; /* place control struct in heap */
}
else { /* shouldn't occur, DosSubAllocMem() shouldn't fail... */
DosSubUnsetMem(heap.base);
DosFreeMem(heap.base);
}
return retval;
}
int destroyHeap(HEAP *heap)
/* Returns OS/2 error code as a negative number on failure, */
/* otherwise returns the number of unfreed blocks. */
{
void *base = heap->base; /* after deallocation, HEAP content */
size_t blocks = heap->blocks; /* can no longer be trusted */
APIRET rc;
/* free HEAP structure */
if ( (rc = DosSubFreeMem(base,heap,sizeof(HEAP))) == 0 )
/* clear system control info */
if ( (rc = DosSubUnsetMem(base)) == 0 )
rc = DosFreeMem(base); /* free heap memory */
return !rc ? blocks : rc * -1;
}
/* * * * * * * * alloc & free * * * * * * * * */
void *allocMem(HEAP *heap, size_t size)
{
size_t *p,
/* user mem plus room to keep size */
totsize = size+sizeof(size_t);
if ( size == 0 ||
DosSubAllocMem(heap->base,(void **)&p,totsize) )
return 0;
*p = size; /* keep size in front of user area */
DosEnterCritSec();
heap->free -= ROUNDUP(totsize,sizeof(int)) + sizeof(void *);
heap->blocks++;
DosExitCritSec();
return p + 1; /* return a pointer to user area */
}
int freeMem(HEAP *heap, void *blockP)
{
void *blckbase = (char *)blockP-sizeof(size_t);
size_t size = *(size_t *)blckbase,
totsize = size + sizeof(size_t);
/* failure is sign of heap corruption */
if ( DosSubFreeMem(heap->base,blckbase,totsize) )
return FALSE;
DosEnterCritSec();
heap->free += ROUNDUP(totsize,sizeof(int)) + sizeof(void *);
heap->blocks--;
DosExitCritSec();
return TRUE;
}
/* * * * * * * * * utilities * * * * * * * * */
size_t queryHeapSize(HEAP *heap)
{
return heap->size;
}
size_t queryHeapFree(HEAP *heap)
{
return heap->free;
}
size_t queryHeapBlocks(HEAP *heap)
{
return heap->blocks;
}
void *queryHeapBase(HEAP *heap)
{
return heap->base;
}
size_t queryBlockSize(void *blockP)
{
return *(size_t *)((char *)blockP-sizeof(size_t));
}
/* End of File */