📄 malloc.c
字号:
while (block) { if (!block->used && (block->size >= size)) return (block); block = block->next; } return (block = NULL);}static void *allocateBlock(unsigned size, const char *function){ // Find a block of unused memory, and return the start pointer. int status = 0; mallocBlock *block = NULL; // Make sure we do allocations on nice boundaries if (size % sizeof(int)) size += (sizeof(int) - (size % sizeof(int))); // Make sure there's enough heap memory. This will get called the first // time we're invoked, as totalMemory will be zero. if ((size > (totalMemory - usedMemory)) || ((block = findFree(size)) == NULL)) { status = growHeap(size); if (status < 0) { errno = status; return (NULL); } block = findFree(size); if (block == NULL) { // Something really wrong. error("Unable to allocate block of size %u (%s)", size, function); return (NULL); } } block->used = 1; block->function = function; block->process = procid(); // If part of this block will be unused, we will need to create a free // block for the remainder if (block->size > size) { if (addBlock(0 /* unused */, (block->start + size), (block->size - size), block->heapAlloc) < 0) return (NULL); block->size = size; } usedMemory += size; return ((void *) block->start);}static void mergeFree(mallocBlock *block){ // Merge this free block with the previous and/or next blocks if they // are also free. if (block->prev && !block->prev->used && (blockEnd(block->prev) == (block->start - 1)) && (block->prev->heapAlloc == block->heapAlloc)) { block->start = block->prev->start; block->size += block->prev->size; putBlock(block->prev); } if (block->next && !block->next->used && (blockEnd(block) == (block->next->start - 1)) && (block->next->heapAlloc == block->heapAlloc)) { block->size += block->next->size; putBlock(block->next); }}static void cleanupHeap(mallocBlock *block){ // If the supplied free block comprises an entire heap allocation, // return that heap memory and get rid of the block. if (block->prev && (block->prev->heapAlloc == block->heapAlloc)) return; if (block->next && (block->next->heapAlloc == block->heapAlloc)) return; // Looks like we can return this memory. memory_release((void *) block->start); totalMemory -= block->size; putBlock(block);}static int deallocateBlock(void *start, const char *function){ // Find an allocated (used) block and deallocate it. int status = 0; mallocBlock *block = blockList; while (block) { if (block->start == (unsigned) start) { if (!block->used) { error("Block at %p is not allocated (%s)", start, function); return (status = ERR_ALREADY); } // Clear out the memory bzero(start, block->size); block->used = 0; block->process = 0; block->function = NULL; usedMemory -= block->size; // Merge free blocks on either side of this one mergeFree(block); // Can the heap be deallocated? cleanupHeap(block); return (status = 0); } block = block->next; } error("No such memory block %u to deallocate (%s)", (unsigned) start, function); return (status = ERR_NOSUCHENTRY);}static inline void mallocBlock2MemoryBlock(mallocBlock *maBlock, memoryBlock *meBlock){ meBlock->processId = maBlock->process; strncpy(meBlock->description, (maBlock->used? maBlock->function : "--free--"), MEMORY_MAX_DESC_LENGTH); meBlock->description[MEMORY_MAX_DESC_LENGTH - 1] = '\0'; meBlock->startLocation = maBlock->start; meBlock->endLocation = blockEnd(maBlock);}////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Below here, the functions are exported for external use////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////void *_doMalloc(unsigned size, const char *function __attribute__((unused))){ // These are the guts of malloc() and kernelMalloc() int status = 0; void *address = NULL; // If the requested block size is zero, forget it. We can probably // assume something has gone wrong in the calling program if (size == 0) { error("Can't allocate 0 bytes (%s)", function); errno = ERR_INVALID; return (address = NULL); } status = lock_get(&blocksLock); if (status < 0) { error("Can't get memory lock"); errno = status; return (address = NULL); } // Find a free block big enough address = allocateBlock(size, function); lock_release(&blocksLock); return (address);}void *_malloc(size_t size, const char *function){ // User space wrapper for _doMalloc() so we can ensure kernel-space calls // use kernelMalloc() if (visopsys_in_kernel) { error("Cannot call malloc() directly from kernel space (%s)", function); return (NULL); } else return (_doMalloc(size, function));}void _doFree(void *start, const char *function __attribute__((unused))){ // These are the guts of free() and kernelFree() int status = 0; if (start == NULL) { error("Can't free NULL pointer (%s)", function); errno = ERR_INVALID; return; } // Make sure we've been initialized if (!usedBlocks) { error("Malloc not initialized"); errno = ERR_NOTINITIALIZED; return; } status = lock_get(&blocksLock); if (status < 0) { error("Can't get memory lock"); errno = status; return; } status = deallocateBlock(start, function); lock_release(&blocksLock); if (status < 0) errno = status; return;}void _free(void *start, const char *function){ // User space wrapper for _doFree() so we can ensure kernel-space calls // use kernelFree() if (visopsys_in_kernel) { error("Cannot call free() directly from kernel space (%s)", function); return; } else return (_doFree(start, function));}int _mallocBlockInfo(void *start, memoryBlock *meBlock){ // Try to find the block that starts at the supplied address and fill out // the structure with information about it. int status = 0; mallocBlock *maBlock = blockList; // Check params if ((start == NULL) || (meBlock == NULL)) return (status = ERR_NULLPARAMETER); // Loop through the block list while (maBlock) { if (maBlock->start == (unsigned) start) { mallocBlock2MemoryBlock(maBlock, meBlock); return (status = 0); } maBlock = maBlock->next; } // Fell through -- no such block return (status = ERR_NOSUCHENTRY);}int _mallocGetStats(memoryStats *stats){ // Return malloc memory usage statistics int status = 0; // Check params if (stats == NULL) { error("Stats structure pointer is NULL"); return (status = ERR_NULLPARAMETER); } stats->totalBlocks = totalBlocks; stats->usedBlocks = usedBlocks; stats->totalMemory = totalMemory; stats->usedMemory = usedMemory; return (status = 0);}int _mallocGetBlocks(memoryBlock *blocksArray, int doBlocks){ // Fill a memoryBlock array with 'doBlocks' used malloc blocks information int status = 0; mallocBlock *block = blockList; int count; // Check params if (blocksArray == NULL) { error("Blocks array pointer is NULL"); return (status = ERR_NULLPARAMETER); } // Loop through the block list for (count = 0; (block && (count < doBlocks)); count ++) { mallocBlock2MemoryBlock(block, &(blocksArray[count])); block = block->next; } return (status = 0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -