📄 memory.c
字号:
TopMemoryBlock->size = usableBlockSize; chunkPtr = (struct chunkInfo *) (((char *) TopMemoryBlock) + BlockInfoSize + ChunkInfoSize + usableBlockSize); chunkPtr->nextFree = NULL; chunkPtr->lastFree = NULL; chunkPtr->prevChunk = TopMemoryBlock->nextFree; chunkPtr->size = 0; TopMemoryBlock->nextFree->nextFree = NULL; TopMemoryBlock->nextFree->lastFree = NULL; TopMemoryBlock->nextFree->prevChunk = NULL; TopMemoryBlock->nextFree->size = usableBlockSize; BlockMemoryInitialized = CLIPS_TRUE; return(1); }/***************************************************************************//* AllocateBlock: Adds a new block of memory to the list of memory blocks. *//***************************************************************************/static int AllocateBlock(blockPtr,requestSize) 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 += BlockInfoSize + ChunkInfoSize * 2; blockSize = (((blockSize - 1) / STRICT_ALIGN_SIZE) + 1) * STRICT_ALIGN_SIZE; usableBlockSize = blockSize - BlockInfoSize - (2 * ChunkInfoSize); /*=========================*/ /* Allocate the new block. */ /*=========================*/ newBlock = (struct blockInfo *) malloc((CLIPS_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) + BlockInfoSize); newBlock->size = usableBlockSize; blockPtr->nextBlock = newBlock; newTopChunk = (struct chunkInfo *) (((char *) newBlock) + BlockInfoSize + 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 = usableBlockSize; return(1); }/*******************************************************//* RequestChunk: Allocates memory by returning a chunk *//* of memory from a larger block of memory. *//*******************************************************/globle VOID *RequestChunk(requestSize) unsigned int requestSize; { struct chunkInfo *chunkPtr; struct blockInfo *blockPtr; /*==================================================*/ /* Allocate initial memory pool block if it has not */ /* already been allocated. */ /*==================================================*/ if (BlockMemoryInitialized == CLIPS_FALSE) { if (InitializeBlockMemory(requestSize) == 0) return(NULL); AddRouter("bmexit",-2000,NULL,NULL,NULL,NULL,BlockMemoryExitFunction); } /*====================================================*/ /* 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 = TopMemoryBlock; while (blockPtr != NULL) { chunkPtr = blockPtr->nextFree; while (chunkPtr != NULL) { if ((chunkPtr->size == requestSize) || (chunkPtr->size > (requestSize + ChunkInfoSize))) { AllocateChunk(blockPtr,chunkPtr,requestSize); return((VOID *) (((char *) chunkPtr) + ChunkInfoSize)); } chunkPtr = chunkPtr->nextFree; } if (blockPtr->nextBlock == NULL) { if (AllocateBlock(blockPtr,requestSize) == 0) /* get another block */ { return(NULL); } } blockPtr = blockPtr->nextBlock; } CLIPSSystemError("MEMORY",2); ExitCLIPS(1); return(NULL); /* Unreachable, but prevents warning. */ }/********************************************//* AllocateChunk: Allocates a chunk from an *//* existing chunk in a block of memory. *//********************************************/static VOID AllocateChunk(parentBlock,chunkPtr,requestSize) struct blockInfo *parentBlock; struct chunkInfo *chunkPtr; unsigned int 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) + ChunkInfoSize + chunkPtr->size); splitChunk = (struct chunkInfo *) (((char *) chunkPtr) + (ChunkInfoSize + requestSize)); splitChunk->size = chunkPtr->size - (requestSize + 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; }/***********************************************************//* ReturnChunk: Frees memory allocated using RequestChunk. *//***********************************************************/globle int ReturnChunk(memPtr,size) VOID *memPtr; unsigned int 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) - ChunkInfoSize); if (chunkPtr == NULL) { return(CLIPS_FALSE); } if (chunkPtr->size >= 0) { return(CLIPS_FALSE); } if (chunkPtr->size != - (long int) size) { return(CLIPS_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) - 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 += (ChunkInfoSize + chunkPtr->size); if (nextChunk != NULL) { nextChunk->prevChunk = lastChunk; } else { return(CLIPS_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(CLIPS_FALSE); if (chunkPtr == NULL) return(CLIPS_FALSE); if (nextChunk->size > 0) { chunkPtr->size += (ChunkInfoSize + nextChunk->size); topChunk = (struct chunkInfo *) (((char *) nextChunk) + nextChunk->size + ChunkInfoSize); if (topChunk != NULL) { topChunk->prevChunk = chunkPtr; } else { return(CLIPS_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; TopMemoryBlock = blockPtr->nextBlock; free((char *) blockPtr); } } } return(CLIPS_TRUE); }/***********************************************//* ReturnAllBlocks: Frees all allocated blocks *//* back to the operating system. *//***********************************************/static VOID ReturnAllBlocks() { struct blockInfo *theBlock, *nextBlock; struct longMemoryPtr *theLongMemory, *nextLongMemory; /*======================================*/ /* Free up int based memory allocation. */ /*======================================*/ theBlock = TopMemoryBlock; while (theBlock != NULL) { nextBlock = theBlock->nextBlock; free((char *) theBlock); theBlock = nextBlock; } TopMemoryBlock = NULL; /*=======================================*/ /* Free up long based memory allocation. */ /*=======================================*/ theLongMemory = TopLongMemoryPtr; while (theLongMemory != NULL) { nextLongMemory = theLongMemory->next; genlongfree(theLongMemory,theLongMemory->size); theLongMemory = nextLongMemory; } TopLongMemoryPtr = NULL; }/********************************************//* BlockMemoryExitFunction: Routine to free *//* block memory when exiting CLIPS. *//********************************************/static int BlockMemoryExitFunction(num) int num; { ReturnAllBlocks(); return(1); }#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -