/* * remove_freeblock - Removes the given free block pointed to by bp from the free list. * * The explicit free list is simply a doubly linked list. This function performs a removal * of the block from the doubly linked free list. */ static void remove_freeblock(void *bp) { if(bp) { if (PREV_FREE(bp)) NEXT_FREE(PREV_FREE(bp)) = NEXT_FREE(bp); else free_listp = NEXT_FREE(bp); if(NEXT_FREE(bp) != NULL) PREV_FREE(NEXT_FREE(bp)) = PREV_FREE(bp); } }
//Find free block size >= asize void * find_fit(size_t asize){ char *bp; //Scan free list, starting with freeStart and ending upon reaching the epilogue block //Note that the epilogue block is the only memeber of the free list whose allocate bit is high for (bp = freeStart; NEXT_FREE(bp) != NULL; bp = NEXT_FREE(bp)){ if (asize <= GET_SIZE(HDRP(bp))){ return bp; } } return NULL; //no fit, BUG allways returning NULL }
/* * delBlkFromFreeList - Removes a block from the free list * This function takes a block pointer of the block to remove, as a * parameter. This is basically a rearrangement of the next * and prev pointers. */ static void delBlkFromFreeList(void *bp) { if (bp == free_listp) free_listp = NEXT_FREE(bp); else /* Set next pointer of previous free block * to point to the next block(thereby skipping the current * block). */ NEXT_FREE(PREV_FREE(bp)) = NEXT_FREE(bp); /* The previous pointer of the next block points to * the previous block thereby skipping the current block. */ PREV_FREE(NEXT_FREE(bp)) = PREV_FREE(bp); }
/* * checkFreeNodes - function that checks correctness of the blocks in * the free list */ static void checkFreeNodes(void *bp) { /* Seperate condition for free_listp since it does not have a * previous pointer. */ if(bp == free_listp) { /* Checking that free_listp indeed points to a free block. */ if(GET_ALLOC(HDRP(bp))) printf("Error: Freelistp points to an allocated block.\n"); /* Free_listp must point to a valid block and must not be * out of bounds */ if(!(bp > mem_heap_lo() && bp < mem_heap_hi())) printf("Error: Free list pointer out of heap bounds.\n"); /* Previous pointer of free_listp * must point nowhere (nil). */ if(PREV_FREE(bp) != 0 ) printf("Error: Free pointer is not null.\n"); return; } /* Checking that bp is indeed pointing to a free block */ if(GET_ALLOC(HDRP(bp)) != 0) printf("Error: There exists an allocated block in the free list.\n"); /* Check that next and prev pointers in consecutive blocks are consistent * Next pointer of previous block points to current block and previous pointer * of next block points to current block */ // Split one print statement into 2 to not cross the 80 character limit. if(PREV_FREE(bp) && NEXT_FREE(PREV_FREE(bp)) != bp) { printf("Error: Next pointer of previous free block "); printf("not pointing to current block.\n"); } if(NEXT_FREE(bp) && PREV_FREE(NEXT_FREE(bp)) != bp) { printf("Error: Previous pointer of next free block "); printf("not pointing to current block.\n"); } /* Check that coalescing was correct at the free block pointed to by bp. The previous and next blocks must both be allocated.*/ if(!GET_ALLOC(HDRP(NEXT_BLKP(bp))) || !GET_ALLOC(HDRP(PREV_BLKP(bp)))) printf("Error: Contiguous free blocks in the heap\n"); }
/* * find_fit - Attempts to find a free block of at least the given size in the free list. * * This function implements a first-fit search strategy for an explicit free list, which * is simply a doubly linked list of free blocks. */ static void *find_fit(size_t size) { // First-fit search void *bp; /* Iterate through the free list and try to find a free block * large enough */ for (bp = free_listp; GET_ALLOC(HDRP(bp)) == 0; bp = NEXT_FREE(bp)) { if (size <= GET_SIZE(HDRP(bp))) return bp; } // Otherwise no free block was large enough return NULL; }
/* * coalesce - Coalesces the memory surrounding block bp using the Boundary Tag strategy * proposed in the text (Page 851, Section 9.9.11). * * Adjancent blocks which are free are merged together and the aggregate free block * is added to the free list. Any individual free blocks which were merged are removed * from the free list. */ static void *coalesce(void *bp) { // Determine the current allocation state of the previous and next blocks size_t prev_alloc = GET_ALLOC(FTRP(PREV_BLKP(bp))) || PREV_BLKP(bp) == bp; size_t next_alloc = GET_ALLOC(HDRP(NEXT_BLKP(bp))); // Get the size of the current free block size_t size = GET_SIZE(HDRP(bp)); /* If the next block is free, then coalesce the current block * (bp) and the next block */ if (prev_alloc && !next_alloc) { // Case 2 (in text) size += GET_SIZE(HDRP(NEXT_BLKP(bp))); remove_freeblock(NEXT_BLKP(bp)); PUT(HDRP(bp), PACK(size, 0)); PUT(FTRP(bp), PACK(size, 0)); } /* If the previous block is free, then coalesce the current * block (bp) and the previous block */ else if (!prev_alloc && next_alloc) { // Case 3 (in text) size += GET_SIZE(HDRP(PREV_BLKP(bp))); bp = PREV_BLKP(bp); remove_freeblock(bp); PUT(HDRP(bp), PACK(size, 0)); PUT(FTRP(bp), PACK(size, 0)); } /* If the previous block and next block are free, coalesce * both */ else if (!prev_alloc && !next_alloc) { // Case 4 (in text) size += GET_SIZE(HDRP(PREV_BLKP(bp))) + GET_SIZE(HDRP(NEXT_BLKP(bp))); remove_freeblock(PREV_BLKP(bp)); remove_freeblock(NEXT_BLKP(bp)); bp = PREV_BLKP(bp); PUT(HDRP(bp), PACK(size, 0)); PUT(FTRP(bp), PACK(size, 0)); } // Insert the coalesced block at the front of the free list NEXT_FREE(bp) = free_listp; PREV_FREE(free_listp) = bp; PREV_FREE(bp) = NULL; free_listp = bp; // Return the coalesced block return bp; }
static void delete_free_block(void * ptr){ //fix foward pointer of previous block if (PREV_FREE(ptr) == NULL){ //then we're deleting the first element of the free list PREV_FREE(NEXT_FREE(ptr)) = NULL; //fix backpointer freeStart = NEXT_FREE(ptr); //fix freeStart } else if(PREV_FREE(ptr) != NULL && NEXT_FREE(ptr) != NULL){ //not at the beginning or end of the free list PREV_FREE(NEXT_FREE(ptr)) = PREV_FREE(ptr); NEXT_FREE(PREV_FREE(ptr)) = NEXT_FREE(ptr); //fix back pointer of next block } else{ //we are deleting the last element of the list NEXT_FREE(PREV_FREE(ptr)) = NULL; } }
/* * insertAtFront - Inserts a block pointed to * by bp at the front of the free list * (LIFO policy) */ static void insertAtFront(void *bp) { /* Make the next pointer of the block point to * start of the list i.e. free_listp */ NEXT_FREE(bp) = free_listp; /* Previous pointer of bp should not point * anywhere. Set to 0 */ PREV_FREE(bp) = 0; /* Set free_list prev to point to bp. * This is how we include bp into the list. * Since free_listp must always point to the * first free block, and bp is the first free block, * we set free_listp = bp */ PREV_FREE(free_listp) = bp; free_listp = bp; }
/* * mm_checkheap - Checks the invariants of the heap * This function checks the invariants of the heap such as header-footer match, * absence of contiguous blocks of free memory and confirmation that the * block pointers are within the heaps boundaries. */ void mm_checkheap(int verbose) { void *bp = heap_listp; //Points to the first block in the heap verbose = verbose; /* If first block's header's size or allocation bit is wrong, * the prologue header is incorrect. */ if ((GET_SIZE(HDRP(heap_listp)) != MINBLOCKSIZE) || !GET_ALLOC(HDRP(heap_listp))) printf("Bad prologue header\n"); checkblock(bp); for (bp = heap_listp; GET_SIZE(HDRP(bp)) > 0; bp = NEXT_BLKP(bp)) { if (verbose) printblock(bp); if(GET_SIZE(HDRP(bp)) == 0) printf("Error: block has zero size\n"); checkblock(bp); /* Checking to see if free block in the free list */ if(!GET_ALLOC(HDRP(bp))) checkInFreeList(bp); } /* If last block's header's size or allocation bit is wrong, * the epilogue's header is wrong. We also check the specific location * of the epilogue header with respect to the last byte of the heap. * mem_heap_hi() and bp(at this point) both point to the same word, * but mem_heap_hi() points to the last byte and hence we must add 3 to * the address of the header of bp to check this condition. */ if (GET_SIZE(HDRP(bp)) != 0 || (GET_ALLOC(HDRP(bp)) != 1) || (HDRP(bp) + WSIZE - 1) != mem_heap_hi()) printf("Bad epilogue header\n"); for(bp = free_listp; GET_ALLOC(HDRP(bp)) == 0; bp = NEXT_FREE(bp)) checkFreeNodes(bp); }
/* * findFit * findFit finds a free block that has size at least asize bytes. * It uses an algorithm that is a slight combination of best fit * and first fit. The function traverses the list from the free_listp * and once it hits a free block of large enough size we traverse a * CONSTANT number of times. I used trial and error to find a constant * that would give me the most throughput. */ static void *findFit(size_t asize) { void *bp = NULL; void *temp = free_listp; size_t minSize = mem_heapsize(); // maximum size /* First fit search */ size_t size; int counter = 0; /* counter for CONSTANT number of traversals */ int flag = 0; /* flag is set if we come across a fit. */ while(!GET_ALLOC(HDRP(temp))) /* While we are pointing to a free block */ { if(asize <= (size = (size_t)GET_SIZE(HDRP(temp))) && size < minSize) { /* If we have a block that fits perfectly, * then there is no point in searching for * a smaller block because we have found the smallest possible one */ if(asize == size) return temp; bp = temp; minSize = size; flag = 1; } if(flag == 1) counter++; /* We have traversed enough. */ if(counter == CONSTANT) return bp; temp = NEXT_FREE(temp); } return bp; }
/*FUNCTION*----------------------------------------------------- * * Function Name : _mem_alloc_internal_align * Returned Value : pointer. NULL is returned upon error. * Comments : * Allocate a aligned block of memory for a task from the free list * * *END*---------------------------------------------------------*/ pointer _mem_alloc_internal_align ( /* [IN] the size of the memory block */ _mem_size requested_size, /* [IN] requested alignement (e.g. 8 for alignement to 8 bytes) */ _mem_size req_align, /* [IN] owner TD */ TD_STRUCT_PTR td_ptr, /* [IN] which pool to allocate from */ MEMPOOL_STRUCT_PTR mem_pool_ptr, /* [OUT] error code for operation */ _mqx_uint_ptr error_ptr ) { /* Body */ STOREBLOCK_STRUCT_PTR block_ptr, free_block_ptr; STOREBLOCK_STRUCT_PTR next_block_ptr = NULL; STOREBLOCK_STRUCT_PTR next_next_block_ptr; _mem_size block_size; _mem_size next_block_size; _mem_size shift; *error_ptr = MQX_OK; /* ** Adjust message size to allow for block management overhead ** and force size to be aligned. */ requested_size += (_mem_size)(FIELD_OFFSET(STOREBLOCK_STRUCT,USER_AREA)); #if MQX_CHECK_ERRORS if (requested_size < MQX_MIN_MEMORY_STORAGE_SIZE) { requested_size = MQX_MIN_MEMORY_STORAGE_SIZE; } /* Endif */ #endif _MEMORY_ALIGN_VAL_LARGER(requested_size); block_ptr = mem_pool_ptr->POOL_FREE_LIST_PTR; while ( TRUE ) { /* ** Save the current block pointer. ** We will be enabling access to higher priority tasks. ** A higher priority task may pre-empt the current task ** and may do a memory allocation. If this is true, ** the higher priority task will reset the POOL_ALLOC_CURRENT_BLOCK ** upon exit, and the current task will start the search over ** again. */ mem_pool_ptr->POOL_ALLOC_CURRENT_BLOCK = block_ptr; /* allow pending interrupts */ _int_enable(); _int_disable(); /* Get block pointer in case reset by a higher priority task */ block_ptr = mem_pool_ptr->POOL_ALLOC_CURRENT_BLOCK; if (block_ptr == NULL) { /* Null pointer */ mem_pool_ptr->POOL_BLOCK_IN_ERROR = block_ptr; *error_ptr = MQX_OUT_OF_MEMORY; return( NULL ); /* request failed */ } /* Endif */ #if MQX_CHECK_VALIDITY if ( !_MEMORY_ALIGNED(block_ptr) || BLOCK_IS_USED(block_ptr) ) { mem_pool_ptr->POOL_BLOCK_IN_ERROR = block_ptr; *error_ptr = MQX_CORRUPT_STORAGE_POOL_FREE_LIST; return((pointer)NULL); } if ( ! VALID_CHECKSUM(block_ptr) ) { mem_pool_ptr->POOL_BLOCK_IN_ERROR = block_ptr; *error_ptr = MQX_INVALID_CHECKSUM; return((pointer)NULL); } #endif block_size = block_ptr->BLOCKSIZE; shift = (((_mem_size)&block_ptr->USER_AREA + req_align) & ~(req_align - 1)) - (_mem_size)&block_ptr->USER_AREA; if (shift < (2 * MQX_MIN_MEMORY_STORAGE_SIZE)) { shift = (((_mem_size)&block_ptr->USER_AREA + (3 * MQX_MIN_MEMORY_STORAGE_SIZE) + req_align) & ~(req_align - 1)) - (_mem_size)&block_ptr->USER_AREA; } if (block_size >= requested_size + shift) { /* request fits into this block */ // create new free block free_block_ptr = (STOREBLOCK_STRUCT_PTR)((char _PTR_)block_ptr); block_ptr = (STOREBLOCK_STRUCT_PTR)(((char _PTR_)block_ptr) + shift); block_ptr->PREVBLOCK = (STOREBLOCK_STRUCT_PTR)free_block_ptr; next_block_size = block_size - requested_size - shift; if (next_block_size >= (2 * MQX_MIN_MEMORY_STORAGE_SIZE) ) { /* ** The current block is big enough to split. ** into 2 blocks.... the part to be allocated is one block, ** and the rest remains as a free block on the free list. */ next_block_ptr = (STOREBLOCK_STRUCT_PTR)((char _PTR_)block_ptr + requested_size); /* Initialize the new physical block values */ next_block_ptr->BLOCKSIZE = next_block_size; next_block_ptr->PREVBLOCK = (STOREBLOCK_STRUCT_PTR)block_ptr; MARK_BLOCK_AS_FREE(next_block_ptr); CALC_CHECKSUM(next_block_ptr); /* Link new block into the free list */ next_block_ptr->NEXTBLOCK = free_block_ptr->NEXTBLOCK; block_ptr->NEXTBLOCK = (pointer)next_block_ptr; next_block_ptr->USER_AREA = (pointer)free_block_ptr; if (next_block_ptr->NEXTBLOCK != NULL ) { ((STOREBLOCK_STRUCT_PTR)next_block_ptr->NEXTBLOCK)->USER_AREA = (pointer)next_block_ptr; } /* ** Modify the current block, to point to this newly created ** block which is now the next physical block. */ block_ptr->BLOCKSIZE = requested_size; /* ** Modify the block on the other side of the next block ** (the next next block) so that it's previous block pointer ** correctly point to the next block. */ next_next_block_ptr = (STOREBLOCK_STRUCT_PTR)NEXT_PHYS(next_block_ptr); PREV_PHYS(next_next_block_ptr) = next_block_ptr; CALC_CHECKSUM(next_next_block_ptr); } else { /* Take the entire block */ requested_size = next_block_size; } /* Endif */ /* modify the new physical block values */ free_block_ptr->BLOCKSIZE = shift; free_block_ptr->NEXTBLOCK = (pointer)next_block_ptr; //free_block_ptr->USER_AREA MARK_BLOCK_AS_FREE(free_block_ptr); CALC_CHECKSUM(free_block_ptr); /* Set the size of the block */ block_ptr->BLOCKSIZE = requested_size; block_ptr->PREVBLOCK = (STOREBLOCK_STRUCT_PTR)free_block_ptr; block_ptr->MEM_TYPE = 0; MARK_BLOCK_AS_USED(block_ptr, td_ptr->TASK_ID); CALC_CHECKSUM(block_ptr); /* Remember some statistics */ next_block_ptr = NEXT_PHYS(block_ptr); if ( (char _PTR_)(next_block_ptr) > (char _PTR_)mem_pool_ptr->POOL_HIGHEST_MEMORY_USED ) { mem_pool_ptr->POOL_HIGHEST_MEMORY_USED = ((char _PTR_)(next_block_ptr) - 1); } /* Endif */ /* Link the block onto the task descriptor. */ block_ptr->NEXTBLOCK = td_ptr->MEMORY_RESOURCE_LIST; td_ptr->MEMORY_RESOURCE_LIST = (pointer)(&block_ptr->USER_AREA); block_ptr->MEM_POOL_PTR = (pointer)mem_pool_ptr; #if MQX_CHECK_VALIDITY /* Check that user area is aligned on a cache line boundary */ if ( !_MEMORY_ALIGNED(&block_ptr->USER_AREA) ) { *error_ptr = MQX_INVALID_CONFIGURATION; return((pointer)NULL); } /* Endif */ #endif return( (pointer)(&block_ptr->USER_AREA ) ); } else { block_ptr = (STOREBLOCK_STRUCT_PTR)NEXT_FREE(block_ptr); } } #ifdef lint return( NULL ); /* to satisfy lint */ #endif }
pointer _mem_alloc_internal ( /* [IN] the size of the memory block */ _mem_size requested_size, /* [IN] owner TD */ TD_STRUCT_PTR td_ptr, /* [IN] which pool to allocate from */ MEMPOOL_STRUCT_PTR mem_pool_ptr, /* [OUT] error code for operation */ _mqx_uint_ptr error_ptr ) { /* Body */ STOREBLOCK_STRUCT_PTR block_ptr; STOREBLOCK_STRUCT_PTR next_block_ptr; STOREBLOCK_STRUCT_PTR next_next_block_ptr; _mem_size block_size; _mem_size next_block_size; *error_ptr = MQX_OK; /* ** Adjust message size to allow for block management overhead ** and force size to be aligned. */ requested_size += (_mem_size)(FIELD_OFFSET(STOREBLOCK_STRUCT,USER_AREA)); #if MQX_CHECK_ERRORS if (requested_size < MQX_MIN_MEMORY_STORAGE_SIZE) { requested_size = MQX_MIN_MEMORY_STORAGE_SIZE; } /* Endif */ #endif _MEMORY_ALIGN_VAL_LARGER(requested_size); block_ptr = mem_pool_ptr->POOL_FREE_LIST_PTR; while ( TRUE ) { /* ** Save the current block pointer. ** We will be enabling access to higher priority tasks. ** A higher priority task may pre-empt the current task ** and may do a memory allocation. If this is true, ** the higher priority task will reset the POOL_ALLOC_CURRENT_BLOCK ** upon exit, and the current task will start the search over ** again. */ mem_pool_ptr->POOL_ALLOC_CURRENT_BLOCK = block_ptr; /* allow pending interrupts */ _int_enable(); _int_disable(); /* Get block pointer in case reset by a higher priority task */ block_ptr = mem_pool_ptr->POOL_ALLOC_CURRENT_BLOCK; if (block_ptr == NULL) { /* Null pointer */ mem_pool_ptr->POOL_BLOCK_IN_ERROR = block_ptr; *error_ptr = MQX_OUT_OF_MEMORY; return( NULL ); /* request failed */ } /* Endif */ #if MQX_CHECK_VALIDITY if ( !_MEMORY_ALIGNED(block_ptr) || BLOCK_IS_USED(block_ptr) ) { mem_pool_ptr->POOL_BLOCK_IN_ERROR = block_ptr; *error_ptr = MQX_CORRUPT_STORAGE_POOL_FREE_LIST; return((pointer)NULL); } /* Endif */ #endif #if MQX_CHECK_VALIDITY if ( ! VALID_CHECKSUM(block_ptr) ) { mem_pool_ptr->POOL_BLOCK_IN_ERROR = block_ptr; *error_ptr = MQX_INVALID_CHECKSUM; return((pointer)NULL); } /* Endif */ #endif block_size = block_ptr->BLOCKSIZE; if (block_size >= requested_size) { /* request fits into this block */ next_block_size = block_size - requested_size; if ( next_block_size >= (2 * MQX_MIN_MEMORY_STORAGE_SIZE) ) { /* ** The current block is big enough to split. ** into 2 blocks.... the part to be allocated is one block, ** and the rest remains as a free block on the free list. */ next_block_ptr = (STOREBLOCK_STRUCT_PTR) ((char _PTR_)block_ptr + requested_size); /* Initialize the new physical block values */ next_block_ptr->BLOCKSIZE = next_block_size; next_block_ptr->PREVBLOCK = (STOREBLOCK_STRUCT_PTR)block_ptr; MARK_BLOCK_AS_FREE(next_block_ptr); CALC_CHECKSUM(next_block_ptr); /* Link new block into the free list */ next_block_ptr->NEXTBLOCK = block_ptr->NEXTBLOCK; block_ptr->NEXTBLOCK = (pointer)next_block_ptr; next_block_ptr->USER_AREA = (pointer)block_ptr; if ( next_block_ptr->NEXTBLOCK != NULL ) { ((STOREBLOCK_STRUCT_PTR)next_block_ptr->NEXTBLOCK)-> USER_AREA = (pointer)next_block_ptr; } /* Endif */ /* ** Modify the block on the other side of the next block ** (the next next block) so that it's previous block pointer ** correctly point to the next block. */ next_next_block_ptr = (STOREBLOCK_STRUCT_PTR) NEXT_PHYS(next_block_ptr); PREV_PHYS(next_next_block_ptr) = next_block_ptr; CALC_CHECKSUM(next_next_block_ptr); } else { /* Take the entire block */ requested_size = block_size; } /* Endif */ /* Set the size of the block */ block_ptr->BLOCKSIZE = requested_size; /* Indicate the block is in use */ MARK_BLOCK_AS_USED(block_ptr, td_ptr->TASK_ID); block_ptr->MEM_TYPE = 0; CALC_CHECKSUM(block_ptr); /* Unlink the block from the free list */ if ( block_ptr == mem_pool_ptr->POOL_FREE_LIST_PTR ) { /* At the head of the free list */ mem_pool_ptr->POOL_FREE_LIST_PTR = (STOREBLOCK_STRUCT_PTR) NEXT_FREE(block_ptr); if (mem_pool_ptr->POOL_FREE_LIST_PTR != NULL ) { PREV_FREE(mem_pool_ptr->POOL_FREE_LIST_PTR) = 0; } /* Endif */ } else { /* ** NOTE: PREV_FREE guaranteed to be non-zero ** Have to make the PREV_FREE of this block ** point to the NEXT_FREE of this block */ NEXT_FREE(PREV_FREE(block_ptr)) = NEXT_FREE(block_ptr); if ( NEXT_FREE(block_ptr) != NULL ) { /* ** Now have to make the NEXT_FREE of this block ** point to the PREV_FREE of this block */ PREV_FREE(NEXT_FREE(block_ptr)) = PREV_FREE(block_ptr); } /* Endif */ } /* Endif */ #if MQX_MEMORY_FREE_LIST_SORTED == 1 if ( block_ptr == mem_pool_ptr->POOL_FREE_CURRENT_BLOCK ) { /* Reset the freelist insertion sort by _mem_free */ mem_pool_ptr->POOL_FREE_CURRENT_BLOCK = mem_pool_ptr->POOL_FREE_LIST_PTR; } /* Endif */ #endif /* Reset the __mem_test freelist pointer */ mem_pool_ptr->POOL_FREE_CHECK_BLOCK = mem_pool_ptr->POOL_FREE_LIST_PTR; /* ** Set the curent pool block to the start of the free list, so ** that if this task pre-empted another that was performing a ** _mem_alloc, the other task will restart it's search for a block */ mem_pool_ptr->POOL_ALLOC_CURRENT_BLOCK = mem_pool_ptr->POOL_FREE_LIST_PTR; /* Remember some statistics */ next_block_ptr = NEXT_PHYS(block_ptr); if ( (char _PTR_)(next_block_ptr) > (char _PTR_) mem_pool_ptr->POOL_HIGHEST_MEMORY_USED ) { mem_pool_ptr->POOL_HIGHEST_MEMORY_USED = ((char _PTR_)(next_block_ptr) - 1); } /* Endif */ /* Link the block onto the task descriptor. */ block_ptr->NEXTBLOCK = td_ptr->MEMORY_RESOURCE_LIST; td_ptr->MEMORY_RESOURCE_LIST = (pointer)(&block_ptr->USER_AREA); block_ptr->MEM_POOL_PTR = (pointer)mem_pool_ptr; #if MQX_CHECK_VALIDITY /* Check that user area is aligned on a cache line boundary */ if ( !_MEMORY_ALIGNED(&block_ptr->USER_AREA) ) { *error_ptr = MQX_INVALID_CONFIGURATION; return((pointer)NULL); } /* Endif */ #endif return( (pointer)(&block_ptr->USER_AREA ) ); } else { block_ptr = (STOREBLOCK_STRUCT_PTR)NEXT_FREE(block_ptr); } /* Endif */ } /* Endwhile */ #ifdef lint return( NULL ); /* to satisfy lint */ #endif } /* Endbody */
_mqx_uint _mem_extend_pool_internal ( /* [IN] the address of the start of the memory pool addition */ pointer start_of_pool, /* [IN] the size of the memory pool addition */ _mem_size size, /* [IN] the memory pool to extend */ MEMPOOL_STRUCT_PTR mem_pool_ptr ) { /* Body */ KERNEL_DATA_STRUCT_PTR kernel_data; STOREBLOCK_STRUCT_PTR block_ptr; STOREBLOCK_STRUCT_PTR end_ptr; STOREBLOCK_STRUCT_PTR free_ptr; STOREBLOCK_STRUCT_PTR tmp_ptr; MEMPOOL_EXTENSION_STRUCT_PTR ext_ptr; uchar_ptr real_start_ptr; uchar_ptr end_of_pool; _mem_size block_size; _mem_size real_size; _mem_size free_block_size; _GET_KERNEL_DATA(kernel_data); #if MQX_CHECK_ERRORS if (size < (_mem_size)(3*MQX_MIN_MEMORY_STORAGE_SIZE)) { /* Pool must be big enough to hold at least 3 memory blocks */ return(MQX_INVALID_SIZE); }/* Endif */ #endif #if MQX_CHECK_VALIDITY if (mem_pool_ptr->VALID != MEMPOOL_VALID) { return(MQX_INVALID_COMPONENT_HANDLE); }/* Endif */ #endif ext_ptr = (MEMPOOL_EXTENSION_STRUCT_PTR) _ALIGN_ADDR_TO_HIGHER_MEM(start_of_pool); real_start_ptr = (uchar_ptr)ext_ptr + sizeof(MEMPOOL_EXTENSION_STRUCT); real_start_ptr = (uchar_ptr)_ALIGN_ADDR_TO_HIGHER_MEM(real_start_ptr); end_of_pool = (uchar_ptr)start_of_pool + size; end_of_pool = (uchar_ptr)_ALIGN_ADDR_TO_LOWER_MEM(end_of_pool); real_size = (_mem_size)(end_of_pool - real_start_ptr); ext_ptr->START = start_of_pool; ext_ptr->SIZE = size; ext_ptr->REAL_START = real_start_ptr; block_ptr = (STOREBLOCK_STRUCT_PTR)real_start_ptr; block_size = MQX_MIN_MEMORY_STORAGE_SIZE; free_ptr = (STOREBLOCK_STRUCT_PTR)((uchar_ptr)block_ptr + block_size); free_block_size = real_size - (_mem_size)(2 * MQX_MIN_MEMORY_STORAGE_SIZE); end_ptr = (STOREBLOCK_STRUCT_PTR)((uchar_ptr)free_ptr + free_block_size); /* ** Make a small minimal sized memory block to be as ** the first block in the pool. This will be an in-use block ** and will thus avoid problems with memory co-allescing during ** memory frees */ block_ptr->BLOCKSIZE = block_size; block_ptr->MEM_TYPE = 0; block_ptr->USER_AREA = 0; block_ptr->PREVBLOCK = (struct storeblock_struct _PTR_)NULL; block_ptr->NEXTBLOCK = free_ptr; MARK_BLOCK_AS_USED(block_ptr, SYSTEM_TASK_ID(kernel_data)); CALC_CHECKSUM(block_ptr); /* ** Let the next block be the actual free block that will be added ** to the free list */ free_ptr->BLOCKSIZE = free_block_size; free_ptr->MEM_TYPE = 0; free_ptr->USER_AREA = 0; free_ptr->PREVBLOCK = block_ptr; free_ptr->NEXTBLOCK = end_ptr; MARK_BLOCK_AS_FREE(free_ptr); CALC_CHECKSUM(free_ptr); /* ** Set up a minimal sized block at the end of the pool, and also ** mark it as being allocated. Again this is to comply with the ** _mem_free algorithm */ end_ptr->BLOCKSIZE = block_size; end_ptr->MEM_TYPE = 0; end_ptr->USER_AREA = 0; end_ptr->PREVBLOCK = free_ptr; end_ptr->NEXTBLOCK = NULL; MARK_BLOCK_AS_USED(end_ptr, SYSTEM_TASK_ID(kernel_data)); CALC_CHECKSUM(end_ptr); _int_disable(); /* Add the block to the free list */ tmp_ptr = mem_pool_ptr->POOL_FREE_LIST_PTR; mem_pool_ptr->POOL_FREE_LIST_PTR = free_ptr; if (tmp_ptr != NULL) { PREV_FREE(tmp_ptr) = free_ptr; } /* Endif */ PREV_FREE(free_ptr) = NULL; NEXT_FREE(free_ptr) = tmp_ptr; /* Reset the free list queue walker for some other task */ mem_pool_ptr->POOL_FREE_CURRENT_BLOCK = mem_pool_ptr->POOL_FREE_LIST_PTR; /* Link in the extension */ _QUEUE_ENQUEUE(&mem_pool_ptr->EXT_LIST, &ext_ptr->LINK); _int_enable(); return(MQX_OK); } /* Endbody */
boolean _mem_check_coalesce_internal ( /* ** [IN] the address of a memory block, whose neighbours have ** to be checked to see if they are free. */ STOREBLOCK_STRUCT_PTR passed_block_ptr ) { /* Body */ register STOREBLOCK_STRUCT_PTR block_ptr; register STOREBLOCK_STRUCT_PTR prev_block_ptr; register STOREBLOCK_STRUCT_PTR next_block_ptr; MEMPOOL_STRUCT_PTR mem_pool_ptr; boolean have_coalesced = FALSE; block_ptr = passed_block_ptr; mem_pool_ptr = (MEMPOOL_STRUCT_PTR)block_ptr->MEM_POOL_PTR; /* Check the previous physical neighbour */ prev_block_ptr = PREV_PHYS(block_ptr); if ((prev_block_ptr != NULL) && BLOCK_IS_FREE(prev_block_ptr)){ /* the block previous to this one is free */ /* make the current block a free block so it can't be freed again */ block_ptr->NEXTBLOCK = NULL; MARK_BLOCK_AS_FREE(block_ptr); /* Add the current block to the previous block */ prev_block_ptr->BLOCKSIZE += block_ptr->BLOCKSIZE; /* Modify the next physical block to point to the previous block */ next_block_ptr = NEXT_PHYS(block_ptr); PREV_PHYS(next_block_ptr) = prev_block_ptr; CALC_CHECKSUM(prev_block_ptr); CALC_CHECKSUM(next_block_ptr); block_ptr = prev_block_ptr; /* Set up as the current block */ have_coalesced = TRUE; } /* Endif */ /* Now, check the next block to see if it is free */ next_block_ptr = NEXT_PHYS(block_ptr); if ( BLOCK_IS_FREE(next_block_ptr) ) { /* the next block is free */ if ( mem_pool_ptr->POOL_ALLOC_CURRENT_BLOCK == next_block_ptr ) { /* We must modify the _mem_alloc pointer to not point ** at the next block */ mem_pool_ptr->POOL_ALLOC_CURRENT_BLOCK = block_ptr; } /* Endif */ if (have_coalesced) { /* the current block is already on the free list */ /* Remove the block from the free list */ if ( block_ptr == mem_pool_ptr->POOL_FREE_LIST_PTR ) { mem_pool_ptr->POOL_FREE_LIST_PTR = (STOREBLOCK_STRUCT_PTR)NEXT_FREE(block_ptr); if ( NEXT_FREE(block_ptr) != NULL ) { PREV_FREE(NEXT_FREE(block_ptr)) = 0; } /* Endif */ } else { NEXT_FREE(PREV_FREE(block_ptr)) = NEXT_FREE(block_ptr); if ( NEXT_FREE(block_ptr) != NULL ) { PREV_FREE(NEXT_FREE(block_ptr)) = PREV_FREE(block_ptr); } /* Endif */ } /* Endif */ } else { /* Make the block a free block */ block_ptr->NEXTBLOCK = NULL; MARK_BLOCK_AS_FREE(block_ptr); } /* Endif */ /* ** The current block is now a free block not on the free list . ** the freelist pointers have to be modified so that the next ** block is removed from the list, replace with the current block. */ /* set the next free block to be the same as the one on the free list */ NEXT_FREE(block_ptr) = NEXT_FREE(next_block_ptr); /* ** And set the back pointer of the block after the next free block ** to point back to the current block */ if ( NEXT_FREE(block_ptr) != NULL ) { PREV_FREE(NEXT_FREE(block_ptr)) = (STOREBLOCK_STRUCT_PTR)block_ptr; } /* Endif */ if (next_block_ptr == mem_pool_ptr->POOL_FREE_LIST_PTR) { /* ** If the next block pointer was at the head of the free list, ** the kernel free list pointer must be updated */ mem_pool_ptr->POOL_FREE_LIST_PTR = block_ptr; PREV_FREE(block_ptr) = NULL; } else { /* ** Otherwise we need to adjust the pointers of the block that ** was previous to the next block on the free list */ PREV_FREE(block_ptr) = PREV_FREE(next_block_ptr); if ( PREV_FREE(block_ptr) != NULL ) { NEXT_FREE(PREV_FREE(block_ptr)) = (pointer)block_ptr; } /* Endif */ } /* Endif */ /* Add the next block onto the current block */ block_ptr->BLOCKSIZE += next_block_ptr->BLOCKSIZE; /* ** Reset the previous physical block pointer of ** the block after the next block (ie the next next block) */ prev_block_ptr = NEXT_PHYS(next_block_ptr); PREV_PHYS(prev_block_ptr) = block_ptr; CALC_CHECKSUM(prev_block_ptr); CALC_CHECKSUM(block_ptr); have_coalesced = TRUE; } /* Endif */ if (have_coalesced) { /* Reset the _mem_test pointers */ mem_pool_ptr->POOL_PHYSICAL_CHECK_BLOCK = (STOREBLOCK_STRUCT_PTR)mem_pool_ptr->POOL_PTR; mem_pool_ptr->POOL_FREE_CHECK_BLOCK = mem_pool_ptr->POOL_FREE_LIST_PTR; #if MQX_MEMORY_FREE_LIST_SORTED == 1 /* ** Reset the freelist current block pointer in case we pre-empted ** another task */ mem_pool_ptr->POOL_FREE_CURRENT_BLOCK = mem_pool_ptr->POOL_FREE_LIST_PTR; #endif } /* Endif */ return (have_coalesced); } /* Endbody */
void moveStart(void *ptr){ //puts thing at pointer bp in front of free list NEXT_FREE(ptr) = freeStart; //attach to old front of list PREV_FREE(ptr) = NULL; //first element of free list has no predecessor PREV_FREE(freeStart) = ptr; freeStart = ptr; //ptr is now the start of the free list }