?? memalloc.c
字號:
/*======================================*/ 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); }/*******************************************************//* RequestChunk: Allocates memory by returning a chunk *//* of memory from a larger block of memory. *//*******************************************************/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,"MEMORY",2); EnvExitRouter(theEnv,EXIT_FAILURE); return(NULL); /* Unreachable, but prevents warning. */ }/********************************************//* AllocateChunk: Allocates a chunk from an *//* existing chunk in a block of memory. *//********************************************/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; }/***********************************************************//* ReturnChunk: Frees memory allocated using RequestChunk. *//***********************************************************/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); }/***********************************************//* ReturnAllBlocks: Frees all allocated blocks *//* back to the operating system. *//***********************************************/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; }#endif
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -