void * getNewMemChunkFromOS_and_Initialize() { //_mem gives the ADDRESS of the memory chunk given by OS. void * _mem = getMemoryFromOS( ArenaSize + (2*sizeof(ObjectHeader)) + (2*sizeof(ObjectFooter)) ); //establish fence posts //step1:fencepost1 struct ObjectFooter * fencepost1 = (struct ObjectFooter *)_mem; fencepost1->_allocated = 1; fencepost1->_objectSize = 123456789;//the size doesn't matter char * temp = (char *)_mem + (2*sizeof(struct ObjectFooter)) + sizeof(struct ObjectHeader) + ArenaSize; //step2 struct ObjectHeader * fencepost2 = (struct ObjectHeader *)temp; fencepost2->_allocated = 1; fencepost2->_objectSize = 123456789; fencepost2->_next = NULL; fencepost2->_prev = NULL; //initialize the list to point to the _mem //step3 temp = (char *) _mem + sizeof(struct ObjectFooter); ObjectHeader * currentHeader = (struct ObjectHeader *) temp; //step4 temp = (char *)_mem + sizeof(struct ObjectFooter) + sizeof(struct ObjectHeader) + ArenaSize; ObjectFooter * currentFooter = (struct ObjectFooter *) temp; //set the size currentHeader->_objectSize = ArenaSize + sizeof(struct ObjectHeader) + sizeof(struct ObjectFooter); //initially around 2MB currentHeader->_allocated = 0;//all as free memory, only 1 chunk currentFooter->_allocated = 0; currentFooter->_objectSize = currentHeader->_objectSize; //add to the exiting freelist ObjectHeader * lastNode = _freeList->_prev; lastNode->_next = currentHeader; currentHeader->_prev = lastNode; currentHeader->_next = _freeList; _freeList->_prev = currentHeader; //increase count of mem chunks that got from OS _numChunks++; return currentHeader; }
void initialize() { // Environment var VERBOSE prints stats at end and turns on debugging // Default is on _verbose = 1; const char * envverbose = getenv( "MALLOCVERBOSE" ); if ( envverbose && !strcmp( envverbose, "NO") ) { _verbose = 0; } pthread_mutex_init(&mutex, NULL); void * _mem = getMemoryFromOS( ArenaSize + (2*sizeof(struct ObjectHeader)) + (2*sizeof(struct ObjectFooter)) ); // In verbose mode register also printing statistics at exit atexit( atExitHandlerInC ); //establish fence posts struct ObjectFooter * fencepost1 = (struct ObjectFooter *)_mem; fencepost1->_allocated = 1; fencepost1->_objectSize = 123456789; char * temp = (char *)_mem + (2*sizeof(struct ObjectFooter)) + sizeof(struct ObjectHeader) + ArenaSize; struct ObjectHeader * fencepost2 = (struct ObjectHeader *)temp; fencepost2->_allocated = 1; fencepost2->_objectSize = 123456789; fencepost2->_next = NULL; fencepost2->_prev = NULL; //initialize the list to point to the _mem temp = (char *) _mem + sizeof(struct ObjectFooter); struct ObjectHeader * currentHeader = (struct ObjectHeader *) temp; temp = (char *)_mem + sizeof(struct ObjectFooter) + sizeof(struct ObjectHeader) + ArenaSize; struct ObjectFooter * currentFooter = (struct ObjectFooter *) temp; _freeList = &_freeListSentinel; currentHeader->_objectSize = ArenaSize + sizeof(struct ObjectHeader) + sizeof(struct ObjectFooter); //2MB currentHeader->_allocated = 0; currentHeader->_next = _freeList; currentHeader->_prev = _freeList; currentFooter->_allocated = 0; currentFooter->_objectSize = currentHeader->_objectSize; _freeList->_prev = currentHeader; _freeList->_next = currentHeader; _freeList->_allocated = 2; // sentinel. no coalescing. _freeList->_objectSize = 0; _memStart = (char*) currentHeader; }
struct ObjectHeader * findValidSpot(size_t size) { struct ObjectHeader * ptr = _freeList->_next; while(ptr != _freeList){ if (ptr->_allocated == 0) { if (ptr->_objectSize >= size){ //find the first block large enough to satisfy the request. return ptr; } } ptr = ptr->_next; } if (ptr == _freeList){ void * _mem = getMemoryFromOS( ArenaSize + (2*sizeof(struct ObjectHeader)) + (2*sizeof(struct ObjectFooter)) ); //establish fence posts struct ObjectFooter * fencepost1 = (struct ObjectFooter *)_mem; fencepost1->_allocated = 1; fencepost1->_objectSize = 123456789; char * temp = (char *)_mem + (2*sizeof(struct ObjectFooter)) + sizeof(struct ObjectHeader) + ArenaSize; struct ObjectHeader * fencepost2 = (struct ObjectHeader *)temp; fencepost2->_allocated = 1; fencepost2->_objectSize = 123456789; fencepost2->_next = NULL; fencepost2->_prev = NULL; //initialize the list to point to the _mem temp = (char *) _mem + sizeof(struct ObjectFooter); struct ObjectHeader * header = (struct ObjectHeader *) temp; temp = (char *)_mem + sizeof(struct ObjectFooter) + sizeof(struct ObjectHeader) + ArenaSize; struct ObjectFooter * footer = (struct ObjectFooter *) temp; header->_objectSize = ArenaSize + (sizeof(struct ObjectHeader)) + (sizeof(struct ObjectFooter)); header->_allocated = 0; footer->_allocated = 0; footer->_objectSize = header->_objectSize; struct ObjectHeader * tmp = _freeList->_prev->_prev; long offset = (long)tmp - (long)_memStart; offset = (long)header - (long)_memStart; offset = (long)_freeList - (long)_memStart; header->_next = _freeList; tmp->_next = header; header->_prev = tmp; _freeList->_prev = header; void * newptr = findValidSpot(size); return newptr; } return ptr; }
void initialize() { // Environment var VERBOSE prints stats at end and turns on debugging // Default is on _verbose = 1; const char * envverbose = getenv( "MALLOCVERBOSE" ); if ( envverbose && !strcmp( envverbose, "NO") ) { _verbose = 0; } pthread_mutex_init(&mutex, NULL); //_mem gives the ADDRESS of the memory chunk given by OS. void * _mem = getMemoryFromOS( ArenaSize + (2*sizeof(struct ObjectHeader)) + (2*sizeof(struct ObjectFooter)) ); // In verbose mode register also printing statistics at exit atexit( atExitHandlerInC ); /* the layout of the memory is like: sentinel --------- |header | |type | --------- | | linked | ----------------- | | ------------------------------------------------------------------------------------- | footer || header | usable memoryspace | footer || header | |(fencepost1) || | | || (fencepost2) | ------------------------------------------------------------------------------------- ^ ^ ^ ^ | | | | step1 step3 step4 step2 ------------------------>-------->------->------>--------->------------------------- address decreases i.e step2 = step1 - sizeof(fencepost1) NOTE: memory addresses increase from stack -> text stack has lower address, text has higher address, stack grows towards text: address increases heap grows towars stack: address decreases */ //establish fence posts //step1:fencepost1 struct ObjectFooter * fencepost1 = (ObjectFooter *)_mem; fencepost1->_allocated = 1; fencepost1->_objectSize = 123456789;//the size doesn't matter char * temp = (char *)_mem + (2*sizeof(ObjectFooter)) + sizeof(ObjectHeader) + ArenaSize; //step2 ObjectHeader * fencepost2 = (ObjectHeader *)temp; fencepost2->_allocated = 1; fencepost2->_objectSize = 123456789; fencepost2->_next = NULL; fencepost2->_prev = NULL; //initialize the list to point to the _mem //step3 temp = (char *) _mem + sizeof(ObjectFooter); struct ObjectHeader * currentHeader = (struct ObjectHeader *) temp; //step4 temp = (char *)_mem + sizeof(ObjectFooter) + sizeof(struct ObjectHeader) + ArenaSize; ObjectFooter * currentFooter = (struct ObjectFooter *) temp; //step5 //(*header) = &(header) _freeList = &_freeListSentinel; //step6 initialize the first header node currentHeader->_objectSize = ArenaSize + sizeof(ObjectHeader) + sizeof(ObjectFooter); //initially around 2MB currentHeader->_allocated = 0;//all as free memory, only 1 chunk currentHeader->_next = _freeList; currentHeader->_prev = _freeList; currentFooter->_allocated = 0; currentFooter->_objectSize = currentHeader->_objectSize; //step7 handle the sentinel node _freeList->_prev = currentHeader; _freeList->_next = currentHeader; _freeList->_allocated = 2; // sentinel. no coalescing. _freeList->_objectSize = 0; //step8 get the start point of usable memory as _memStart _memStart = (char*) currentHeader; }
void * allocateObject( size_t size ) { //Make sure that allocator is initialized if ( !_initialized ) { _initialized = 1; initialize(); } // Add the ObjectHeader/Footer to the size and round the total size up to a multiple of // 8 bytes for alignment. size_t roundedSize = (size + sizeof(struct ObjectHeader) + sizeof(struct ObjectFooter) + 7) & ~7; struct ObjectHeader * _tempFirstChunk = _freeList->_next; //pointing to the first header //Checking if the list is empty. If yes, then allocating a new 2MB chink if(_tempFirstChunk == _freeList) { void * newMemory = getMemoryFromOS( ArenaSize + (2*sizeof(struct ObjectHeader)) + (2*sizeof(struct ObjectFooter)) ); struct ObjectFooter * fencepost1 = (struct ObjectFooter *)newMemory; fencepost1->_allocated = 1; fencepost1->_objectSize = 123456789; char * temp = (char *)newMemory + (2*sizeof(struct ObjectFooter)) + sizeof(struct ObjectHeader) + ArenaSize; struct ObjectHeader * fencepost2 = (struct ObjectHeader *)temp; fencepost2->_allocated = 1; fencepost2->_objectSize = 123456789; fencepost2->_next = NULL; fencepost2->_prev = NULL; temp = (char *) newMemory + sizeof(struct ObjectFooter); struct ObjectHeader * nextListHeader = (struct ObjectHeader *) temp; temp = (char *) newMemory + sizeof(struct ObjectFooter) + sizeof(struct ObjectHeader) + ArenaSize; struct ObjectFooter * nextListFooter = (struct ObjectFooter *) temp; nextListHeader->_objectSize = ArenaSize + sizeof(struct ObjectHeader) + sizeof(struct ObjectFooter); //2MB nextListHeader->_allocated = 0; nextListFooter->_allocated = 0; nextListFooter->_objectSize = nextListHeader->_objectSize; //pointing the free list accordingly in the correct position _freeList->_next = nextListHeader; nextListHeader->_prev = _freeList; nextListHeader->_next = _freeList; _freeList->_prev = nextListHeader; //updating the looping variable _tempFirstChunk = nextListHeader; } while(_tempFirstChunk != _freeList) { // looping until the end if(_tempFirstChunk->_objectSize - roundedSize > min_size) { // if it qualifies to be split size_t block_size = _tempFirstChunk->_objectSize; // size of the block to be split void * marker = (void *)_tempFirstChunk; //marker for the block large enough /* Getting to the split point * Getting the footer in place * Marking the footer and original header to be allocated * Object size change */ char * temp = (char*)marker + roundedSize - sizeof(struct ObjectFooter); struct ObjectFooter * newFooter = (struct ObjectFooter *)temp; newFooter->_objectSize = roundedSize; _tempFirstChunk->_objectSize = newFooter->_objectSize; _tempFirstChunk->_allocated = 1; newFooter->_allocated = 1; /* end */ /* Getting to the new header placement for the remaining * New header's size and allocation settings */ temp = (char *)marker + roundedSize; struct ObjectHeader * newHeader = (struct ObjectHeader *) temp; newHeader->_objectSize = (block_size - roundedSize); newHeader->_allocated = 0; /* end */ /* Getting to the original footer to change settings * changing object size of this footer */ temp = (char *)marker + (block_size - sizeof(struct ObjectFooter)); struct ObjectFooter * prev_footer = (struct ObjectFooter *) temp; prev_footer->_objectSize = newHeader->_objectSize; prev_footer->_allocated = 0; /* end */ //deleting the allocated pointer newHeader->_prev = _tempFirstChunk->_prev; (_tempFirstChunk->_prev)->_next = newHeader; newHeader->_next = _tempFirstChunk->_next; (_tempFirstChunk->_next)->_prev = newHeader; break; } else if((_tempFirstChunk->_objectSize - (roundedSize)) <= min_size && (_tempFirstChunk->_objectSize - (roundedSize)) >= 0) { size_t current_size = _tempFirstChunk->_objectSize; //deleting the allocated pointer (_tempFirstChunk->_prev)->_next = (_tempFirstChunk->_next); (_tempFirstChunk->_next)->_prev = (_tempFirstChunk->_prev); //marking it and updating it to be allocated _tempFirstChunk->_allocated = 1; void * marker = (void *) _tempFirstChunk; char * temp = (char *) marker + current_size - sizeof(struct ObjectFooter); struct ObjectFooter * currentFooter = (struct ObjectFooter *)temp; currentFooter->_allocated = 1; currentFooter->_objectSize = current_size; break; } else { //if not found large enough _tempFirstChunk = _tempFirstChunk->_next; //if chunk is found large enough in the whole list, allocating a new 2 MB chunk if(_tempFirstChunk == _freeList) { void * newMemory = getMemoryFromOS( ArenaSize + (2*sizeof(struct ObjectHeader)) + (2*sizeof(struct ObjectFooter)) ); struct ObjectFooter * fencepost1 = (struct ObjectFooter *)newMemory; fencepost1->_allocated = 1; fencepost1->_objectSize = 123456789; char * temp = (char *)newMemory + (2*sizeof(struct ObjectFooter)) + sizeof(struct ObjectHeader) + ArenaSize; struct ObjectHeader * fencepost2 = (struct ObjectHeader *)temp; fencepost2->_allocated = 1; fencepost2->_objectSize = 123456789; fencepost2->_next = NULL; fencepost2->_prev = NULL; temp = (char *) newMemory + sizeof(struct ObjectFooter); struct ObjectHeader * nextListHeader = (struct ObjectHeader *) temp; temp = (char *) newMemory + sizeof(struct ObjectFooter) + sizeof(struct ObjectHeader) + ArenaSize; struct ObjectFooter * nextListFooter = (struct ObjectFooter *) temp; nextListHeader->_objectSize = ArenaSize + sizeof(struct ObjectHeader) + sizeof(struct ObjectFooter); //2MB nextListHeader->_allocated = 0; nextListFooter->_allocated = 0; nextListFooter->_objectSize = nextListHeader->_objectSize; //updating the freelist pointers according to the current and the new list (_tempFirstChunk->_prev)->_next = nextListHeader; nextListHeader->_prev = (_tempFirstChunk->_prev); nextListHeader->_next = _freeList; _freeList->_prev = nextListHeader; //updating the loop varaible _tempFirstChunk = nextListHeader; } } } pthread_mutex_unlock(&mutex); void * ret = (void *) _tempFirstChunk; char * temp = (char *) ret + sizeof(struct ObjectHeader); ret = (void *) temp; // Return a pointer to usable memory return (void *) (ret); }