Ejemplo n.º 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);
  }
}
Ejemplo n.º 2
0
//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
}
Ejemplo n.º 3
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);
}
Ejemplo n.º 4
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");


}
Ejemplo n.º 5
0
/*
 * 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; 
}
Ejemplo n.º 6
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;
}
Ejemplo n.º 7
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;
  }
}
Ejemplo n.º 8
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;
}
Ejemplo n.º 9
0
/*
 * 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);

}
Ejemplo n.º 10
0
/*
 * 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;
}
Ejemplo n.º 11
0
/*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
}
Ejemplo n.º 12
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 */
Ejemplo n.º 13
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 */
Ejemplo n.º 14
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 */
Ejemplo n.º 15
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
}