home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
High Voltage Shareware
/
high1.zip
/
high1
/
DIR24
/
BASH_112.ZIP
/
BASH-112.TAR
/
bash-1.12
/
malloc.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-10-09
|
10KB
|
378 lines
/* Package of programs to manage the near heap. Implemented because of
the juvinile beharior of the Borland reallocation procedure. Attempts
to ensure that links have not been corrupted, and exits with an error
message and bad status if they have. All aborts are made through the
common routine
bombOut().
This enables the user to trap the stack at the point of the exit by
use of the debugger.
*/
#include <os2.h>
#include "stddef.h"
#include <stdio.h>
#include <stdlib.h>
unsigned _mallocAllocBlocks;
static char *noInit="Message control structure not initialized\n";
static char *badStructure="Message control structures corrupted\n";
static char *cantCommit="Can't commit memory\n";
static char *noAlloc = "Can't allocate mem\n";
static int controlSize;
static int noInitFlag = 1;
struct memControl{
struct memControl *next;
unsigned count;
ULONG checkValue;
struct _sysMemST *sysControl;
};
typedef struct memControl userMemST;
typedef struct _sysMemST{
ULONG signature;
userMemST *freeChain;
ULONG allocated; /* size of block as received from
system call */
ULONG noCommitSize;
PVOID firstByte;
PVOID noCommitMem;
} sysMemST;
#define CHECK_VALUE 0xA6A6A6A6
#define NUM_ALLOC_BLKS 1000
#define COMMIT_SIZE 8192
#define FULL_BLOCK(i, size) i&(size-1)? (i&(~(size-1)))+size: i
static sysMemST sysControlBlock;
static userMemST *currentFreeList;
static struct memControl *predecessor, /* used when finding list*/
*prePredecessor; /* position */
static int abut(struct memControl *, struct memControl*);
static void addList(struct memControl*);
void bombOut(char *);
static struct memControl *combine(struct memControl *);
void free(void *);
static int initMem(sysMemST *);
static void listPosition(struct memControl *);
static struct memControl *splitBlock(unsigned);
/* ******************************** ABUT ******************************* */
/* determine if two blocks are contiguous */
static int abut(blk1, blk2)
struct memControl *blk1,
*blk2;
{unsigned holeSize;
void *raw1,
*raw2;
if(blk1==NULL || blk2==NULL)
return 0;
holeSize = (char *)blk2 - (char *)blk1 - (blk1->count+controlSize);
if(holeSize >0)
return 0;
if(holeSize == 0)
return 1;
bombOut(badStructure);
}
/* ****************************** ADD_LIST ***************************** */
/* add a block to the free list. Predecessor must be defined */
static void addList(block)
struct memControl *block;
{
if(predecessor == NULL)
{block->next = block->sysControl->freeChain;
block->sysControl->freeChain = block;
currentFreeList = block;
return;
}
block->next = predecessor->next;
predecessor->next = block;
return;
}
/* ****************************** BOMB_OUT ***************************** */
void bombOut(mssg)
char *mssg;
{printf(mssg);
exit(1);
}
/* ****************************** CALLOC ******************************* */
void *calloc(num, size)
size_t num,
size;
{void *blk;
blk = malloc(num*size);
if(!blk)
return NULL;
memset(blk, 0, num*size);
return blk;
}
/* ****************************** COMBINE ****************************** */
/* combine input block with its successor block if they are contiguous.
Returns pointer to combined block if successful, else pointer to
successor block
*/
static struct memControl *combine(block)
struct memControl *block;
{
if(block == NULL)
return currentFreeList;
if(abut(block, block->next))
{block->count += (block->next->count + controlSize);
block->next = block->next->next;
return block;
}
return block->next;
}
/* ******************************* FREE ******************************** */
void free(inData)
void *inData;
{struct memControl *memBlock;
if(!inData)
return;
if(noInitFlag)
bombOut(noInit);
memBlock = (struct memControl *)((char *)inData - controlSize);
currentFreeList = memBlock->sysControl->freeChain;
listPosition(memBlock);
addList(memBlock);
combine(combine(predecessor));
return;
}
/* ***************************** INIT_MEM ****************************** */
static int initMem(sysMemST *sysControlBlock)
{struct memControl *trueStart;
unsigned i,
length;
void *pBaseAddress;
i = _mallocAllocBlocks? _mallocAllocBlocks: NUM_ALLOC_BLKS;
length = 4096*i;
if(DosAllocMem(&pBaseAddress, length, PAG_READ|PAG_WRITE))
return 1;
sysControlBlock->allocated = length;
sysControlBlock->signature = CHECK_VALUE;
sysControlBlock->noCommitMem = pBaseAddress;
sysControlBlock->noCommitSize = length;
sysControlBlock->freeChain = NULL;
sysControlBlock->firstByte = pBaseAddress;
controlSize = sizeof(struct memControl);
if(controlSize & 3)
controlSize = (controlSize & 0xfffc) + 4;
noInitFlag = 0;
return 0;
}
/* *************************** LIST_POSITION *************************** */
/* Find the block immediately proceeding the input block. Sets the static
variables predecessor and prePredecessor
*/
static void listPosition(block)
struct memControl *block;
{struct memControl *work;
predecessor = NULL;
prePredecessor = NULL;
for(work = block->sysControl->freeChain; work != NULL; work=work->next)
{if(work > block)
break;
prePredecessor = predecessor;
predecessor = work;
}
return;
}
/* ****************************** MALLOC ******************************* */
void *malloc(num)
size_t num;
{struct memControl *work;
int doAbut,
i,
toCommit,
useCommited;
char *pd,
*dataBlock;
sysMemST *sysControl;
ULONG result;
if(!num)
return NULL;
sysControl = &sysControlBlock;
if(noInitFlag)
initMem(sysControl);
num = FULL_BLOCK(num, 4);
prePredecessor = NULL;
predecessor = NULL;
for(work = sysControl->freeChain; work != NULL; work = work->next)
{if(work->count > num)
{(void)splitBlock(num);
dataBlock = (char *)work + controlSize;
return dataBlock;
}
prePredecessor = predecessor;
predecessor = work;
}
if(predecessor)
doAbut = (predecessor->count+predecessor+controlSize) == sysControl->noCommitMem;
else
doAbut = 0;
useCommited = doAbut? predecessor->count: 0;
if(useCommited+sysControl->noCommitSize < num)
return NULL;
toCommit = num-useCommited;
toCommit = FULL_BLOCK(toCommit, COMMIT_SIZE);
if((result = DosSetMem(sysControl->noCommitMem, toCommit,
PAG_COMMIT|PAG_READ|PAG_WRITE)))
bombOut(cantCommit);
work = (userMemST *) sysControl->noCommitMem;
work->checkValue = CHECK_VALUE;
work->next = NULL;
work->count = toCommit-controlSize;
work->sysControl = sysControl;
if(predecessor)
predecessor->next = work;
else
sysControl->freeChain = work;
sysControl->noCommitSize -= toCommit;
sysControl->noCommitMem += toCommit;
currentFreeList = work->sysControl->freeChain;
if(doAbut)
work = combine(predecessor);
return malloc(num);
}
/* *************************** REALLOC ***************************** */
void *realloc(inputData,num)
void *inputData;
size_t num;
{struct memControl *newBlock,
*oldPredecessor,
*SP,
*testBlock;
sysMemST *sysControl;
char *pd,
*ps;
unsigned availP,
availS,
i,
toMove;
void *newData;
sysControl = &sysControlBlock;
if(noInitFlag)
bombOut(noInit);
SP = (struct memControl *)((char *)inputData - controlSize);
if(SP->checkValue != CHECK_VALUE)
{bombOut(badStructure);
exit(1);
}
currentFreeList = SP->sysControl->freeChain;
toMove = SP->count;
listPosition(SP);
if(toMove > num) /* New block will fit inside the old one */
{addList(SP);
(void)combine(SP);
splitBlock(num);
return inputData;
}
availP = 0;
availS = 0;
if(abut(predecessor, SP))
availP = predecessor->count + controlSize;
if(predecessor != NULL)
testBlock = predecessor->next;
else
testBlock = sysControl->freeChain;
if(abut(SP, testBlock))
availS = testBlock->count + controlSize;
if(availP+availS+SP->count >= num) /* append old block to an adjacent one */
{addList(SP);
newBlock = combine(predecessor);
(void)combine(newBlock);
if(newBlock == predecessor)
predecessor = prePredecessor;
(void)splitBlock(num);
pd = (char *)SP + controlSize + toMove;
if(newBlock != SP)
{for(i=0, ps=(char *)SP+controlSize, pd=(char *)newBlock+controlSize;
i < toMove; ++i)
*pd++ = *ps++;
}
for(i=toMove; i<newBlock->count; ++i)
*pd++ = 0;
return (char *)newBlock + controlSize;
}
newData = malloc(num);
if(newData == NULL)
return NULL;
free(inputData);
pd = newData;
ps = inputData;
if(pd < ps)
{for(i=0; i<toMove; ++i)
*pd++ = *ps++;
}
else
{pd += toMove;
ps += toMove;
for(i=0; i<toMove; ++i)
*(--pd) = *(--ps);
}
return newData;
}
/* **************************** SPLIT_BLOCK *************************** */
/* allocate bytes from the block which follows predecessor */
static struct memControl *splitBlock(numBytes)
unsigned numBytes;
{struct memControl *block,
**link,
*newBlock;
sysMemST *sysControl;
unsigned bytesLeft;
sysControl = &sysControlBlock;
if(predecessor == NULL)
{block = sysControl->freeChain;
link = &sysControl->freeChain;
}
else
{block = predecessor->next;
link = &predecessor->next;
}
if(block->count <= (numBytes+controlSize))
{*link = block->next; /* no room for an extra control structure, so
can't split block */
return block;
}
bytesLeft = block->count - controlSize - numBytes;
newBlock = (struct memControl *)((char *)block + numBytes + controlSize);
newBlock->next = block->next;
newBlock->count = bytesLeft;
newBlock->checkValue = CHECK_VALUE;
newBlock->sysControl = block->sysControl;
*link = newBlock;
block->count = numBytes;
return block;
}