/* * 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); } }
/* * 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"); }
/* * 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; }
/* * mm_check - heap consistency checker. return 0 if something is wrong, 1 otherwise. */ int mm_check(void) { void *cur, *end; if(!rb_check_preorder()){ return 0; } cur = mem_heap_lo() + MIN_BLOCK_SIZE; end = mem_heap_hi() - 3; while(cur < end){ if(CUR_FREE(cur)){ // cur is free block if(PREV_FREE(cur)){ // contiguous free block printf("%p, %p are consecutive, but both are free.\n", PREV_BLOCK(cur, CUR_SIZE_MASKED(cur)), cur); return 0; } if(IS_IN_RB(cur) && !rb_find_exact(cur)){ // cur is not in Red-black tree printf("%p is free block, but is not in Red-black tree.\n", cur); return 0; } }else{ // cur is allocated block } cur = NEXT_BLOCK(cur, CUR_SIZE_MASKED(cur)); } return 1; }
/* * 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; }
/* * checkInFreeList - checks that all free blocks are in the free list * This function checks if the free block pointed to by bp is in the free list. * By calling this function from mm_checkheap(int) everytime we come across a * free block we will get to know if it is definitely in the free list or not. * We just go to the previous free block and if we do not reach the free list * pointer, then we know the free block is not in the free list. */ static void checkInFreeList(void *bp) { void *temp = bp; if(temp == free_listp) return; while((temp = PREV_FREE(temp)) != 0) { if(temp == free_listp) return; } }
/* * mm_malloc - Allocate a block * * If there exists a free block where the request fits, get the smallest one, segment it and allocate. * If there is no such block, increase brk. */ void* mm_malloc(size_t size) { size_t block_size, next_block_size; void *free_block, *next_block; block_size = ALIGN(HEADER_SIZE + size); block_size = block_size < MIN_BLOCK_SIZE ? MIN_BLOCK_SIZE : block_size; free_block = rb_find(block_size); if(free_block == rb_null){ // proper free block not found /* set free_block to the end of last block in heap */ free_block = mem_heap_hi() - 3; if(PREV_FREE(free_block)){ // if the last block is free /* set free_block to the last block */ free_block -= PREV_SIZE_MASKED(free_block); if(IS_IN_RB(free_block)){ rb_delete(free_block); } /* this block is smaller than request, so increase brk */ mem_sbrk(block_size - CUR_SIZE_MASKED(free_block)); }else{ // if the last block is not free mem_sbrk(block_size); } }else{ /* will be allocated, so delete from tree first */ rb_delete(free_block); /* if the block is bigger than request, segment it */ if((next_block_size = CUR_SIZE_MASKED(free_block) - block_size) > 0){ next_block = NEXT_BLOCK(free_block, block_size); CUR_SIZE(next_block) = PREV_SIZE(NEXT_BLOCK(next_block, next_block_size)) = next_block_size | 1; if(IS_IN_RB(next_block)){ rb_insert(next_block); } } } CUR_SIZE(free_block) = PREV_SIZE(NEXT_BLOCK(free_block, block_size)) = block_size; #ifdef DEBUG printf("mm_malloc(%u) called\n", size); printf("free_block = %p\n", free_block); rb_print_preorder(); printf("\n"); #endif /* DEBUG */ #ifdef CHECK if(!mm_check()){ rb_print_preorder(); exit(0); } #endif /* CHECK */ return USER_BLOCK(free_block); }
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; } }
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 */
/* * mm_free - Coalesce with surrounding blocks, and put it to Red-black tree */ void mm_free(void *ptr) { size_t size, new_size; void *prev, *cur, *next, *new_block; cur = ptr - HEADER_SIZE; /* double free */ if(CUR_FREE(cur)){ printf("try to free a freed memory block(%p) is detected.\n", cur); return ; } new_block = cur; new_size = CUR_SIZE_MASKED(cur); /* coalesce with the previous block if free */ if(PREV_FREE(cur)){ size = PREV_SIZE_MASKED(cur); prev = PREV_BLOCK(cur, size); if(IS_IN_RB(prev)){ rb_delete(prev); } new_block = prev; new_size += size; } /* coalesce with the next block if exists and free */ size = CUR_SIZE_MASKED(cur); next = NEXT_BLOCK(cur, size); if(next + 4 <= mem_heap_hi() && CUR_FREE(next)){ size = CUR_SIZE_MASKED(next); if(IS_IN_RB(next)){ rb_delete(next); } new_size += size; } /* new free block setting */ CUR_SIZE(new_block) = PREV_SIZE(NEXT_BLOCK(new_block, new_size)) = new_size | 1; if(IS_IN_RB(new_block)){ rb_insert(new_block); } #ifdef DEBUG printf("mm_free(%p) called\n", ptr); printf("new_block = %p\n", new_block); rb_print_preorder(); printf("\n"); #endif /* DEBUG */ #ifdef CHECK if(!mm_check()){ rb_print_preorder(); exit(0); } #endif /* CHECK */ /* DON't MODIFY THIS STAGE AND LEAVE IT AS IT WAS */ if (gl_ranges) remove_range(gl_ranges, ptr); }
_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 }