/*************************************************************************** * Project : shakti devt board * Name of the file : malloc_firstfit.c * Brief Description of file : Malloc using First-fit algorithm code. * Name of Author : Abhinav Ramnath * Email ID : abhinavramnath13@gmail.com Copyright (C) 2019 IIT Madras. All rights reserved. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . ***************************************************************************/ /** @file malloc_firstfit.c @brief Malloc using First-fit algorithm code. @detail This algorithm implements the malloc function using the first-fit algorithm. It allocates and frees blocks of memory for usage. */ #include #include #include "platform.h" #include "defines.h" #include "log.h" extern char* _HEAP_SIZE[]; char* HEAP_SIZE = (char *)&_HEAP_SIZE; //Header block denotes start of the segment struct Header { size_t size; int free; struct Header* next; }; struct Header* global_base=NULL; /** @fn struct Header* allocate_block(struct Header* last, size_t size) * @brief it allocates a block of given size * @detail it allocates a block of the given size after receiving the parameter of the last allocated block * @param struct Header* last - pointer to the last allocated memory or the end of the heap * @param size_t size - specifes the size of the block to be allocated * @return returns a pointer to the newly allocated block * returns null if mmemory allocated or block allocation fails */ struct Header* allocate_block(struct Header* last, size_t size) { uintptr_t x=0; log_trace("\nFunction allocate_block entered"); if(last->size > size) { struct Header* newblock; void *p = last; p += size + sizeof(struct Header); x = p; x = ((( x) + ((REGSIZE) - 1)) & ~((REGSIZE) - 1)); p = x; newblock = p; newblock->size = last->size - size - sizeof(struct Header); last->size = size; last->free = 0; last->next = newblock; newblock->free = 1; newblock->next = NULL; return last; } else return NULL; log_trace("\nFunction allocate_block entered"); } //We search for free blocks /** @fn struct Header *find_free_block(struct Header **last, size_t size) * @brief finds free blocks from the linked list of blocks in the memory * @detail iterates through the linked list to find a block of required size that is free * @param struct Header **last - pointer to the heap * @param size_t size - size of the block * @return returns a free block if available * returns null if unavailable */ struct Header *find_free_block(struct Header **last, size_t size) { log_trace("\nfind free entered"); struct Header *current = global_base; while (current && !(current->free && current->size >= size)) { log_debug("\n Inside Loop %d %d %x %x",current->size,size,current,*last); *last = current; current = current->next; } log_debug("\n After Loop %d %d %x %x",current->size,size,current,*last); if(current && current->size>=size) { *last=current; return current; } else return NULL; log_trace("\nfind free exited"); } //Creating a new block /** @fn struct Header* request_heap() * @brief requests memory from the heap * @detail this function requests memory from the heap using the brk function * @return returns a pointer to the allocated heap * returns NULL if heap is unable to be allocated */ struct Header* request_heap() { struct Header *block; block = m_sbrk(0); void *request = m_sbrk(HEAP_SIZE); if((void*)block == request); // Not thread safe. block=request; log_debug("\nInitial Heap start address =%x",block); if (request == (void*) -1) { log_error("\nNo space left to allocate memory"); return NULL; // sbrk failed. } block->size = HEAP_SIZE; block->next = NULL; block->free = 1; log_debug("\nBlock Assigned"); return block; } //malloc function to allocate space /** @fn void *malloc(size_t size) * @brief this function is used to dynamically allocate memory * @detail when this function is called memory is allocated in the heap during runtime * @param size_t size - size of the block to be allocated * @return returns a pointer to the assigned block * returns NULL if allocation fails */ void *malloc(size_t size) { struct Header *block; if (size <= 0) { return NULL; } log_info("\n global_base: %x",global_base); if(global_base==0x00000000) { // First call. global_base is empty log_debug("\n Requesting block"); block = request_heap(); log_debug("\n block=%x",block); if (!block) { return NULL; } global_base = block; } struct Header *last = global_base; block = find_free_block(&last, size); if(!block) { log_error("\n No free blocks"); return NULL; } log_debug("\nBlock = %x Block Size = %d Size = %d",block,block->size,size); if (block->size>size) { // Failed to find free block. block = allocate_block(last,size); if (!block) { return NULL; } } else if(block->size==size) { // Found free block log_debug("\nFound free block of same size"); block->free = 0; } return(block+1); } /** @fn struct Header *get_block_ptr(void *ptr) * @brief function to get block pointer * @detail function returns the pointer to the block * @param void* ptr - pointer to the block * @return returns pointer to the block */ struct Header *get_block_ptr(void *ptr) { return (struct Header*)ptr - 1; } //free to free the memory allocated by malloc /** @fn void free(void *ptr) * @brief frees the memory assigned by malloc * @detail frees the memory assigned by malloc and when freed this memory is added back to the list to be reused * @param void *ptr - pointer to the memory assigned by malloc */ void free(void *ptr) { if (!ptr) { log_error("\n Wrong value passed to free"); return; } struct Header* block_ptr = get_block_ptr(ptr); log_debug("\n %x is freed",block_ptr); if(block_ptr->free==0) block_ptr->free = 1; }