globle void InitializeMemory( void *theEnv) { AllocateEnvironmentData(theEnv,MEMORY_DATA,sizeof(struct memoryData),NULL); MemoryData(theEnv)->OutOfMemoryFunction = DefaultOutOfMemoryFunction; #if (MEM_TABLE_SIZE > 0) MemoryData(theEnv)->MemoryTable = (struct memoryPtr **) malloc((STD_SIZE) (sizeof(struct memoryPtr *) * MEM_TABLE_SIZE)); if (MemoryData(theEnv)->MemoryTable == NULL) { PrintErrorID(theEnv,"MEMORY",1,TRUE); EnvPrintRouter(theEnv,WERROR,"Out of memory.\n"); EnvExitRouter(theEnv,EXIT_FAILURE); } else { int i; for (i = 0; i < MEM_TABLE_SIZE; i++) MemoryData(theEnv)->MemoryTable[i] = NULL; } #else // MEM_TABLE_SIZE == 0 MemoryData(theEnv)->MemoryTable = NULL; #endif }
globle void ReturnAllBlocks( void *theEnv) { struct blockInfo *theBlock, *nextBlock; struct longMemoryPtr *theLongMemory, *nextLongMemory; /*======================================*/ /* Free up int based memory allocation. */ /*======================================*/ theBlock = MemoryData(theEnv)->TopMemoryBlock; while (theBlock != NULL) { nextBlock = theBlock->nextBlock; free((char *) theBlock); theBlock = nextBlock; } MemoryData(theEnv)->TopMemoryBlock = NULL; /*=======================================*/ /* Free up long based memory allocation. */ /*=======================================*/ theLongMemory = MemoryData(theEnv)->TopLongMemoryPtr; while (theLongMemory != NULL) { nextLongMemory = theLongMemory->next; genlongfree(theEnv,theLongMemory,(unsigned long) theLongMemory->size); theLongMemory = nextLongMemory; } MemoryData(theEnv)->TopLongMemoryPtr = NULL; }
globle long int EnvReleaseMem( void *theEnv, long int maximum) { struct memoryPtr *tmpPtr, *memPtr; int i; long int returns = 0; long int amount = 0; for (i = (MEM_TABLE_SIZE - 1) ; i >= (int) sizeof(char *) ; i--) { YieldTime(theEnv); memPtr = MemoryData(theEnv)->MemoryTable[i]; while (memPtr != NULL) { tmpPtr = memPtr->next; genfree(theEnv,(void *) memPtr,(unsigned) i); memPtr = tmpPtr; amount += i; returns++; if ((returns % 100) == 0) { YieldTime(theEnv); } } MemoryData(theEnv)->MemoryTable[i] = NULL; if ((amount > maximum) && (maximum > 0)) { return(amount); } } return(amount); }
globle void *gm1( void *theEnv, size_t size) { struct memoryPtr *memPtr; char *tmpPtr; size_t i; if (size < (long) sizeof(char *)) size = sizeof(char *); if (size >= MEM_TABLE_SIZE) { tmpPtr = (char *) genalloc(theEnv,(unsigned) size); for (i = 0 ; i < size ; i++) { tmpPtr[i] = '\0'; } return((void *) tmpPtr); } memPtr = (struct memoryPtr *) MemoryData(theEnv)->MemoryTable[size]; if (memPtr == NULL) { tmpPtr = (char *) genalloc(theEnv,(unsigned) size); for (i = 0 ; i < size ; i++) { tmpPtr[i] = '\0'; } return((void *) tmpPtr); } MemoryData(theEnv)->MemoryTable[size] = memPtr->next; tmpPtr = (char *) memPtr; for (i = 0 ; i < size ; i++) { tmpPtr[i] = '\0'; } return ((void *) tmpPtr); }
globle void *genalloc( void *theEnv, size_t size) { char *memPtr; memPtr = (char *) malloc(size); if (memPtr == NULL) { EnvReleaseMem(theEnv,(long) ((size * 5 > 4096) ? size * 5 : 4096)); memPtr = (char *) malloc(size); if (memPtr == NULL) { EnvReleaseMem(theEnv,-1L); memPtr = (char *) malloc(size); while (memPtr == NULL) { if ((*MemoryData(theEnv)->OutOfMemoryFunction)(theEnv,size)) return(NULL); memPtr = (char *) malloc(size); } } } MemoryData(theEnv)->MemoryAmount += (long) size; MemoryData(theEnv)->MemoryCalls++; return((void *) memPtr); }
globle long int UpdateMemoryUsed( void *theEnv, long int value) { MemoryData(theEnv)->MemoryAmount += value; return(MemoryData(theEnv)->MemoryAmount); }
globle long int UpdateMemoryRequests( void *theEnv, long int value) { MemoryData(theEnv)->MemoryCalls += value; return(MemoryData(theEnv)->MemoryCalls); }
globle void *RequestChunk( void *theEnv, size_t requestSize) { struct chunkInfo *chunkPtr; struct blockInfo *blockPtr; /*==================================================*/ /* Allocate initial memory pool block if it has not */ /* already been allocated. */ /*==================================================*/ if (MemoryData(theEnv)->BlockMemoryInitialized == FALSE) { if (InitializeBlockMemory(theEnv,requestSize) == 0) return(NULL); } /*====================================================*/ /* Make sure that the amount of memory requested will */ /* fall on a boundary of strictest alignment */ /*====================================================*/ requestSize = (((requestSize - 1) / STRICT_ALIGN_SIZE) + 1) * STRICT_ALIGN_SIZE; /*=====================================================*/ /* Search through the list of free memory for a block */ /* of the appropriate size. If a block is found, then */ /* allocate and return a pointer to it. */ /*=====================================================*/ blockPtr = MemoryData(theEnv)->TopMemoryBlock; while (blockPtr != NULL) { chunkPtr = blockPtr->nextFree; while (chunkPtr != NULL) { if ((chunkPtr->size == requestSize) || (chunkPtr->size > (requestSize + MemoryData(theEnv)->ChunkInfoSize))) { AllocateChunk(theEnv,blockPtr,chunkPtr,requestSize); return((void *) (((char *) chunkPtr) + MemoryData(theEnv)->ChunkInfoSize)); } chunkPtr = chunkPtr->nextFree; } if (blockPtr->nextBlock == NULL) { if (AllocateBlock(theEnv,blockPtr,requestSize) == 0) /* get another block */ { return(NULL); } } blockPtr = blockPtr->nextBlock; } SystemError(theEnv,(char*)"MEMORY",2); EnvExitRouter(theEnv,EXIT_FAILURE); return(NULL); /* Unreachable, but prevents warning. */ }
globle int (*EnvSetOutOfMemoryFunction(void *theEnv,int (*functionPtr)(void *,size_t)))(void *,size_t) { int (*tmpPtr)(void *,size_t); tmpPtr = MemoryData(theEnv)->OutOfMemoryFunction; MemoryData(theEnv)->OutOfMemoryFunction = functionPtr; return(tmpPtr); }
globle int (*EnvSetOutOfMemoryFunction(void *theEnv,int (*functionPtr)(void *,unsigned long)))(void *,unsigned long) { int (*tmpPtr)(void *,unsigned long); tmpPtr = MemoryData(theEnv)->OutOfMemoryFunction; MemoryData(theEnv)->OutOfMemoryFunction = functionPtr; return(tmpPtr); }
globle intBool EnvSetConserveMemory( void *theEnv, intBool value) { int ov; ov = MemoryData(theEnv)->ConserveMemory; MemoryData(theEnv)->ConserveMemory = value; return(ov); }
globle CLIPS_BOOLEAN EnvSetConserveMemory( void *theEnv, CLIPS_BOOLEAN value) { int ov; ov = MemoryData(theEnv)->ConserveMemory; MemoryData(theEnv)->ConserveMemory = value; return(ov); }
globle int genlongfree( void *theEnv, void *ptr, unsigned long size) { #if (! MAC) && (! IBM_TBC) && (! IBM_MSC) && (! IBM_ICB) && (! IBM_ZTC) && (! IBM_SC) && (! IBM_MCW) unsigned int test; #endif #if BLOCK_MEMORY struct longMemoryPtr *theLongMemory; #endif if (sizeof(unsigned int) == sizeof(unsigned long)) { return(genfree(theEnv,(void *) ptr,(unsigned) size)); } #if (! MAC) && (! IBM_TBC) && (! IBM_MSC) && (! IBM_ICB) && (! IBM_ZTC) && (! IBM_SC) && (! IBM_MCW) test = (unsigned int) size; if (test != size) return(-1); return(genfree(theEnv,(void *) ptr,(unsigned) test)); #endif #if BLOCK_MEMORY size += sizeof(struct longMemoryPtr); theLongMemory = ((struct longMemoryPtr *) ptr) - 1; if (theLongMemory->prev == NULL) { MemoryData(theEnv)->TopLongMemoryPtr = MemoryData(theEnv)->TopLongMemoryPtr->next; MemoryData(theEnv)->TopLongMemoryPtr->prev = NULL; } else { theLongMemory->prev->next = theLongMemory->next; if (theLongMemory->next != NULL) { theLongMemory->next->prev = theLongMemory->next; } } #endif #if MAC || IBM_ICB || IBM_MCW MemoryData(theEnv)->MemoryAmount -= (long) size; MemoryData(theEnv)->MemoryCalls--; SpecialFree(ptr); return(0); #endif #if IBM_TBC || IBM_ZTC || IBM_SC MemoryData(theEnv)->MemoryAmount -= size; MemoryData(theEnv)->MemoryCalls--; SpecialFree(ptr); return(0); #endif #if IBM_MSC MemoryData(theEnv)->MemoryAmount -= size; MemoryData(theEnv)->MemoryCalls--; SpecialFree(ptr); return(0); #endif }
globle int genfree( void *theEnv, void *waste, size_t size) { free(waste); MemoryData(theEnv)->MemoryAmount -= (long) size; MemoryData(theEnv)->MemoryCalls--; return(0); }
globle void *genalloc( void *theEnv, size_t size) { char *memPtr; #if BLOCK_MEMORY memPtr = (char *) RequestChunk(theEnv,size); if (memPtr == NULL) { EnvReleaseMem(theEnv,(long) ((size * 5 > 4096) ? size * 5 : 4096),FALSE); memPtr = (char *) RequestChunk(theEnv,size); if (memPtr == NULL) { EnvReleaseMem(theEnv,-1L,TRUE); memPtr = (char *) RequestChunk(theEnv,size); while (memPtr == NULL) { if ((*MemoryData(theEnv)->OutOfMemoryFunction)(theEnv,(unsigned long) size)) return(NULL); memPtr = (char *) RequestChunk(theEnv,size); } } } #else memPtr = (char *) malloc(size); if (memPtr == NULL) { EnvReleaseMem(theEnv,(long) ((size * 5 > 4096) ? size * 5 : 4096),FALSE); memPtr = (char *) malloc(size); if (memPtr == NULL) { EnvReleaseMem(theEnv,-1L,TRUE); memPtr = (char *) malloc(size); while (memPtr == NULL) { if ((*MemoryData(theEnv)->OutOfMemoryFunction)(theEnv,size)) return(NULL); memPtr = (char *) malloc(size); } } } #endif MemoryData(theEnv)->MemoryAmount += (long) size; MemoryData(theEnv)->MemoryCalls++; return((void *) memPtr); }
globle unsigned long ActualPoolSize( void *theEnv) { #if WIN_BTC register int i; struct memoryPtr *memPtr; unsigned long cnt = 0; for (i = sizeof(char *) ; i < MEM_TABLE_SIZE ; i++) { memPtr = MemoryData(theEnv)->MemoryTable[i]; while (memPtr != NULL) { /*==============================================================*/ /* For a block of size n, the Turbo-C Library routines require */ /* a header of size 8 bytes and further require that all memory */ /* allotments be paragraph (16-bytes) aligned. */ /*==============================================================*/ cnt += (((unsigned long) i) + 19L) & 0xfffffff0L; memPtr = memPtr->next; } } return(cnt); #else return(PoolSize(theEnv)); #endif }
globle void *gm3( void *theEnv, size_t size) { struct memoryPtr *memPtr; if (size < (long) sizeof(char *)) size = sizeof(char *); if (size >= MEM_TABLE_SIZE) return(genalloc(theEnv,size)); memPtr = (struct memoryPtr *) MemoryData(theEnv)->MemoryTable[(int) size]; if (memPtr == NULL) { return(genalloc(theEnv,size)); } MemoryData(theEnv)->MemoryTable[(int) size] = memPtr->next; return ((void *) memPtr); }
globle void ReturnAllBlocks( void *theEnv) { struct blockInfo *theBlock, *nextBlock; /*======================================*/ /* Free up int based memory allocation. */ /*======================================*/ theBlock = MemoryData(theEnv)->TopMemoryBlock; while (theBlock != NULL) { nextBlock = theBlock->nextBlock; free((char *) theBlock); theBlock = nextBlock; } MemoryData(theEnv)->TopMemoryBlock = NULL; }
globle void *gm2( void *theEnv, unsigned int size) { struct memoryPtr *memPtr; if (size < sizeof(char *)) size = sizeof(char *); if (size >= MEM_TABLE_SIZE) return(genalloc(theEnv,(unsigned) size)); memPtr = (struct memoryPtr *) MemoryData(theEnv)->MemoryTable[size]; if (memPtr == NULL) { return(genalloc(theEnv,(unsigned) size)); } MemoryData(theEnv)->MemoryTable[size] = memPtr->next; return ((void *) memPtr); }
globle long int EnvReleaseMem( void *theEnv, long int maximum, int printMessage) { struct memoryPtr *tmpPtr, *memPtr; int i; long int returns = 0; long int amount = 0; if (printMessage == TRUE) { EnvPrintRouter(theEnv,WDIALOG,(char*)"\n*** DEALLOCATING MEMORY ***\n"); } for (i = (MEM_TABLE_SIZE - 1) ; i >= (int) sizeof(char *) ; i--) { YieldTime(theEnv); memPtr = MemoryData(theEnv)->MemoryTable[i]; while (memPtr != NULL) { tmpPtr = memPtr->next; genfree(theEnv,(void *) memPtr,(unsigned) i); memPtr = tmpPtr; amount += i; returns++; if ((returns % 100) == 0) { YieldTime(theEnv); } } MemoryData(theEnv)->MemoryTable[i] = NULL; if ((amount > maximum) && (maximum > 0)) { if (printMessage == TRUE) { EnvPrintRouter(theEnv,WDIALOG,(char*)"*** MEMORY DEALLOCATED ***\n"); } return(amount); } } if (printMessage == TRUE) { EnvPrintRouter(theEnv,WDIALOG,(char*)"*** MEMORY DEALLOCATED ***\n"); } return(amount); }
globle int genfree( void *theEnv, void *waste, size_t size) { #if BLOCK_MEMORY if (ReturnChunk(theEnv,waste,size) == FALSE) { PrintErrorID(theEnv,(char*)"MEMORY",2,TRUE); EnvPrintRouter(theEnv,WERROR,(char*)"Release error in genfree.\n"); return(-1); } #else free(waste); #endif MemoryData(theEnv)->MemoryAmount -= (long) size; MemoryData(theEnv)->MemoryCalls--; return(0); }
globle int rm3( void *theEnv, void *str, size_t size) { struct memoryPtr *memPtr; if (size == 0) { SystemError(theEnv,(char*)"MEMORY",1); EnvExitRouter(theEnv,EXIT_FAILURE); } if (size < (long) sizeof(char *)) size = sizeof(char *); if (size >= MEM_TABLE_SIZE) return(genfree(theEnv,(void *) str,(unsigned long) size)); memPtr = (struct memoryPtr *) str; memPtr->next = MemoryData(theEnv)->MemoryTable[(int) size]; MemoryData(theEnv)->MemoryTable[(int) size] = memPtr; return(1); }
globle unsigned long PoolSize( void *theEnv) { register int i; struct memoryPtr *memPtr; unsigned long cnt = 0; for (i = sizeof(char *) ; i < MEM_TABLE_SIZE ; i++) { memPtr = MemoryData(theEnv)->MemoryTable[i]; while (memPtr != NULL) { cnt += (unsigned long) i; memPtr = memPtr->next; } } return(cnt); }
static int AllocateBlock( void *theEnv, struct blockInfo *blockPtr, unsigned int requestSize) { unsigned int blockSize, usableBlockSize; struct blockInfo *newBlock; struct chunkInfo *newTopChunk; /*============================================================*/ /* Determine the size of the block that needs to be allocated */ /* to satisfy the request. Normally, a default block size is */ /* used, but if the requested size is larger than the default */ /* size, then the requested size is used for the block size. */ /*============================================================*/ blockSize = (BLOCKSIZE > requestSize ? BLOCKSIZE : requestSize); blockSize += MemoryData(theEnv)->BlockInfoSize + MemoryData(theEnv)->ChunkInfoSize * 2; blockSize = (((blockSize - 1) / STRICT_ALIGN_SIZE) + 1) * STRICT_ALIGN_SIZE; usableBlockSize = blockSize - MemoryData(theEnv)->BlockInfoSize - (2 * MemoryData(theEnv)->ChunkInfoSize); /*=========================*/ /* Allocate the new block. */ /*=========================*/ newBlock = (struct blockInfo *) malloc((STD_SIZE) blockSize); if (newBlock == NULL) return(0); /*======================================*/ /* Initialize the block data structure. */ /*======================================*/ newBlock->nextBlock = NULL; newBlock->prevBlock = blockPtr; newBlock->nextFree = (struct chunkInfo *) (((char *) newBlock) + MemoryData(theEnv)->BlockInfoSize); newBlock->size = (long) usableBlockSize; blockPtr->nextBlock = newBlock; newTopChunk = (struct chunkInfo *) (((char *) newBlock) + MemoryData(theEnv)->BlockInfoSize + MemoryData(theEnv)->ChunkInfoSize + usableBlockSize); newTopChunk->nextFree = NULL; newTopChunk->lastFree = NULL; newTopChunk->size = 0; newTopChunk->prevChunk = newBlock->nextFree; newBlock->nextFree->nextFree = NULL; newBlock->nextFree->lastFree = NULL; newBlock->nextFree->prevChunk = NULL; newBlock->nextFree->size = (long) usableBlockSize; return(1); }
globle intBool DestroyEnvironment( void *vtheEnvironment) { struct environmentCleanupFunction *cleanupPtr; int i; struct memoryData *theMemData; intBool rv = TRUE; struct environmentData *theEnvironment = (struct environmentData *) vtheEnvironment; if (EvaluationData(theEnvironment)->CurrentExpression != NULL) { return(FALSE); } #if DEFRULE_CONSTRUCT if (EngineData(theEnvironment)->ExecutingRule != NULL) { return(FALSE); } #endif theMemData = MemoryData(theEnvironment); EnvReleaseMem(theEnvironment,-1,FALSE); for (i = 0; i < MAXIMUM_ENVIRONMENT_POSITIONS; i++) { if (theEnvironment->cleanupFunctions[i] != NULL) { (*theEnvironment->cleanupFunctions[i])(theEnvironment); } } free(theEnvironment->cleanupFunctions); for (cleanupPtr = theEnvironment->listOfCleanupEnvironmentFunctions; cleanupPtr != NULL; cleanupPtr = cleanupPtr->next) { (*cleanupPtr->func)(theEnvironment); } RemoveEnvironmentCleanupFunctions(theEnvironment); EnvReleaseMem(theEnvironment,-1,FALSE); #if ALLOW_ENVIRONMENT_GLOBALS RemoveHashedEnvironment(theEnvironment); #endif if ((theMemData->MemoryAmount != 0) || (theMemData->MemoryCalls != 0)) { FPRINTF(stderr, "\n[ENVRNMNT8] Environment data not fully deallocated.\n"); rv = FALSE; } free(theMemData->MemoryTable); #if BLOCK_MEMORY ReturnAllBlocks(theEnvironment); #endif for (i = 0; i < MAXIMUM_ENVIRONMENT_POSITIONS; i++) { if (theEnvironment->theData[i] != NULL) { free(theEnvironment->theData[i]); theEnvironment->theData[i] = NULL; } } free(theEnvironment->theData); #if ALLOW_ENVIRONMENT_GLOBALS if (CurrentEnvironment == theEnvironment) { CurrentEnvironment = NULL; } #endif free(theEnvironment); return(rv); }
globle long int EnvMemRequests( void *theEnv) { return(MemoryData(theEnv)->MemoryCalls); }
globle int ReturnChunk( void *theEnv, void *memPtr, size_t size) { struct chunkInfo *chunkPtr, *lastChunk, *nextChunk, *topChunk; struct blockInfo *blockPtr; /*=====================================================*/ /* Determine if the expected size of the chunk matches */ /* the size stored in the chunk's information record. */ /*=====================================================*/ size = (((size - 1) / STRICT_ALIGN_SIZE) + 1) * STRICT_ALIGN_SIZE; chunkPtr = (struct chunkInfo *) (((char *) memPtr) - MemoryData(theEnv)->ChunkInfoSize); if (chunkPtr == NULL) { return(FALSE); } if (chunkPtr->size >= 0) { return(FALSE); } if (chunkPtr->size != - (long int) size) { return(FALSE); } chunkPtr->size = - chunkPtr->size; /*=============================================*/ /* Determine in which block the chunk resides. */ /*=============================================*/ topChunk = chunkPtr; while (topChunk->prevChunk != NULL) { topChunk = topChunk->prevChunk; } blockPtr = (struct blockInfo *) (((char *) topChunk) - MemoryData(theEnv)->BlockInfoSize); /*===========================================*/ /* Determine the chunks physically preceding */ /* and following the returned chunk. */ /*===========================================*/ lastChunk = chunkPtr->prevChunk; nextChunk = (struct chunkInfo *) (((char *) memPtr) + size); /*=========================================================*/ /* Add the chunk to the list of free chunks for the block. */ /*=========================================================*/ if (blockPtr->nextFree != NULL) { blockPtr->nextFree->lastFree = chunkPtr; } chunkPtr->nextFree = blockPtr->nextFree; chunkPtr->lastFree = NULL; blockPtr->nextFree = chunkPtr; /*=====================================================*/ /* Combine this chunk with previous chunk if possible. */ /*=====================================================*/ if (lastChunk != NULL) { if (lastChunk->size > 0) { lastChunk->size += (MemoryData(theEnv)->ChunkInfoSize + chunkPtr->size); if (nextChunk != NULL) { nextChunk->prevChunk = lastChunk; } else { return(FALSE); } if (lastChunk->lastFree != NULL) { lastChunk->lastFree->nextFree = lastChunk->nextFree; } if (lastChunk->nextFree != NULL) { lastChunk->nextFree->lastFree = lastChunk->lastFree; } lastChunk->nextFree = chunkPtr->nextFree; if (chunkPtr->nextFree != NULL) { chunkPtr->nextFree->lastFree = lastChunk; } lastChunk->lastFree = NULL; blockPtr->nextFree = lastChunk; chunkPtr->lastFree = NULL; chunkPtr->nextFree = NULL; chunkPtr = lastChunk; } } /*=====================================================*/ /* Combine this chunk with the next chunk if possible. */ /*=====================================================*/ if (nextChunk == NULL) return(FALSE); if (chunkPtr == NULL) return(FALSE); if (nextChunk->size > 0) { chunkPtr->size += (MemoryData(theEnv)->ChunkInfoSize + nextChunk->size); topChunk = (struct chunkInfo *) (((char *) nextChunk) + nextChunk->size + MemoryData(theEnv)->ChunkInfoSize); if (topChunk != NULL) { topChunk->prevChunk = chunkPtr; } else { return(FALSE); } if (nextChunk->lastFree != NULL) { nextChunk->lastFree->nextFree = nextChunk->nextFree; } if (nextChunk->nextFree != NULL) { nextChunk->nextFree->lastFree = nextChunk->lastFree; } } /*===========================================*/ /* Free the buffer if we can, but don't free */ /* the first buffer if it's the only one. */ /*===========================================*/ if ((chunkPtr->prevChunk == NULL) && (chunkPtr->size == blockPtr->size)) { if (blockPtr->prevBlock != NULL) { blockPtr->prevBlock->nextBlock = blockPtr->nextBlock; if (blockPtr->nextBlock != NULL) { blockPtr->nextBlock->prevBlock = blockPtr->prevBlock; } free((char *) blockPtr); } else { if (blockPtr->nextBlock != NULL) { blockPtr->nextBlock->prevBlock = NULL; MemoryData(theEnv)->TopMemoryBlock = blockPtr->nextBlock; free((char *) blockPtr); } } } return(TRUE); }
static void AllocateChunk( void *theEnv, struct blockInfo *parentBlock, struct chunkInfo *chunkPtr, size_t requestSize) { struct chunkInfo *splitChunk, *nextChunk; /*=============================================================*/ /* If the size of the memory chunk is an exact match for the */ /* requested amount of memory, then the chunk can be allocated */ /* without splitting it. */ /*=============================================================*/ if (requestSize == chunkPtr->size) { chunkPtr->size = - (long int) requestSize; if (chunkPtr->lastFree == NULL) { if (chunkPtr->nextFree != NULL) { parentBlock->nextFree = chunkPtr->nextFree; } else { parentBlock->nextFree = NULL; } } else { chunkPtr->lastFree->nextFree = chunkPtr->nextFree; } if (chunkPtr->nextFree != NULL) { chunkPtr->nextFree->lastFree = chunkPtr->lastFree; } chunkPtr->lastFree = NULL; chunkPtr->nextFree = NULL; return; } /*===========================================================*/ /* If the size of the memory chunk is larger than the memory */ /* request, then split the chunk into two pieces. */ /*===========================================================*/ nextChunk = (struct chunkInfo *) (((char *) chunkPtr) + MemoryData(theEnv)->ChunkInfoSize + chunkPtr->size); splitChunk = (struct chunkInfo *) (((char *) chunkPtr) + (MemoryData(theEnv)->ChunkInfoSize + requestSize)); splitChunk->size = (long) (chunkPtr->size - (requestSize + MemoryData(theEnv)->ChunkInfoSize)); splitChunk->prevChunk = chunkPtr; splitChunk->nextFree = chunkPtr->nextFree; splitChunk->lastFree = chunkPtr->lastFree; nextChunk->prevChunk = splitChunk; if (splitChunk->lastFree == NULL) { parentBlock->nextFree = splitChunk; } else { splitChunk->lastFree->nextFree = splitChunk; } if (splitChunk->nextFree != NULL) { splitChunk->nextFree->lastFree = splitChunk; } chunkPtr->size = - (long int) requestSize; chunkPtr->lastFree = NULL; chunkPtr->nextFree = NULL; return; }
globle intBool EnvGetConserveMemory( void *theEnv) { return(MemoryData(theEnv)->ConserveMemory); }
static int InitializeBlockMemory( void *theEnv, unsigned int requestSize) { struct chunkInfo *chunkPtr; unsigned int initialBlockSize, usableBlockSize; /*===========================================*/ /* The block memory routines depend upon the */ /* size of a character being 1 byte. */ /*===========================================*/ if (sizeof(char) != 1) { fprintf(stdout, "Size of character data is not 1\n"); fprintf(stdout, "Memory allocation functions may not work\n"); return(0); } MemoryData(theEnv)->ChunkInfoSize = sizeof(struct chunkInfo); MemoryData(theEnv)->ChunkInfoSize = (int) ((((MemoryData(theEnv)->ChunkInfoSize - 1) / STRICT_ALIGN_SIZE) + 1) * STRICT_ALIGN_SIZE); MemoryData(theEnv)->BlockInfoSize = sizeof(struct blockInfo); MemoryData(theEnv)->BlockInfoSize = (int) ((((MemoryData(theEnv)->BlockInfoSize - 1) / STRICT_ALIGN_SIZE) + 1) * STRICT_ALIGN_SIZE); initialBlockSize = (INITBLOCKSIZE > requestSize ? INITBLOCKSIZE : requestSize); initialBlockSize += MemoryData(theEnv)->ChunkInfoSize * 2 + MemoryData(theEnv)->BlockInfoSize; initialBlockSize = (((initialBlockSize - 1) / STRICT_ALIGN_SIZE) + 1) * STRICT_ALIGN_SIZE; usableBlockSize = initialBlockSize - (2 * MemoryData(theEnv)->ChunkInfoSize) - MemoryData(theEnv)->BlockInfoSize; /* make sure we get a buffer big enough to be usable */ if ((requestSize < INITBLOCKSIZE) && (usableBlockSize <= requestSize + MemoryData(theEnv)->ChunkInfoSize)) { initialBlockSize = requestSize + MemoryData(theEnv)->ChunkInfoSize * 2 + MemoryData(theEnv)->BlockInfoSize; initialBlockSize = (((initialBlockSize - 1) / STRICT_ALIGN_SIZE) + 1) * STRICT_ALIGN_SIZE; usableBlockSize = initialBlockSize - (2 * MemoryData(theEnv)->ChunkInfoSize) - MemoryData(theEnv)->BlockInfoSize; } MemoryData(theEnv)->TopMemoryBlock = (struct blockInfo *) malloc((STD_SIZE) initialBlockSize); if (MemoryData(theEnv)->TopMemoryBlock == NULL) { fprintf(stdout, "Unable to allocate initial memory pool\n"); return(0); } MemoryData(theEnv)->TopMemoryBlock->nextBlock = NULL; MemoryData(theEnv)->TopMemoryBlock->prevBlock = NULL; MemoryData(theEnv)->TopMemoryBlock->nextFree = (struct chunkInfo *) (((char *) MemoryData(theEnv)->TopMemoryBlock) + MemoryData(theEnv)->BlockInfoSize); MemoryData(theEnv)->TopMemoryBlock->size = (long) usableBlockSize; chunkPtr = (struct chunkInfo *) (((char *) MemoryData(theEnv)->TopMemoryBlock) + MemoryData(theEnv)->BlockInfoSize + MemoryData(theEnv)->ChunkInfoSize + usableBlockSize); chunkPtr->nextFree = NULL; chunkPtr->lastFree = NULL; chunkPtr->prevChunk = MemoryData(theEnv)->TopMemoryBlock->nextFree; chunkPtr->size = 0; MemoryData(theEnv)->TopMemoryBlock->nextFree->nextFree = NULL; MemoryData(theEnv)->TopMemoryBlock->nextFree->lastFree = NULL; MemoryData(theEnv)->TopMemoryBlock->nextFree->prevChunk = NULL; MemoryData(theEnv)->TopMemoryBlock->nextFree->size = (long) usableBlockSize; MemoryData(theEnv)->BlockMemoryInitialized = TRUE; return(1); }