Example #1
0
/*
 * 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);
  }
}
Example #2
0
/*
 * 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);
}
Example #3
0
/*
 * 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");


}
Example #4
0
/*
 * 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;
}
Example #5
0
/*
 * 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;
}
Example #6
0
/*
 * 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;
}
Example #7
0
/*
 * 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;
    }
}
Example #8
0
/*
 * 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);
}
Example #9
0
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;
  }
}
Example #10
0
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 */
Example #11
0
/*
 * 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);
}
Example #12
0
_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 */
Example #13
0
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 */
Example #14
0
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
}