示例#1
0
文件: init.c 项目: epicsdeb/rtems
static void test_check_free_block(void)
{
  Heap_Block *block = NULL;
  Heap_Block *next_block = NULL;
  Heap_Block *first_free_block = NULL;
  Heap_Block *secound_free_block = NULL;
  void *p1 = NULL;

  puts( "test the _Heap_Walk_check_free_block() function" );

  puts( "\tset a previous size for the next block which is not equal to the size of the actual block" );
  test_heap_init_default();
  block = _Heap_Free_list_first( &TestHeap );
  next_block = _Heap_Block_at( block, _Heap_Block_size( block ) );
  next_block->prev_size = _Heap_Block_size( block ) - 1;
  test_call_heap_walk( false );

  puts( "\tclear the previous_used flag of the first free block after an used block" );
  test_heap_init_default();
  p1 = test_allocate_block();
  block = _Heap_Block_of_alloc_area( (uintptr_t) p1, TestHeap.page_size );
  first_free_block = _Heap_Free_list_first( &TestHeap );
  first_free_block->size_and_flag &= ~HEAP_PREV_BLOCK_USED;
  first_free_block->prev_size = _Heap_Block_size( block );
  _Heap_Free_list_insert_after( first_free_block, block );
  test_call_heap_walk( false );

  puts( "\ttake a free block out of the free list" );
  test_heap_init_custom();
  test_create_heap_with_gaps();
  first_free_block = _Heap_Free_list_first( &TestHeap );
  secound_free_block = first_free_block->next;
  _Heap_Free_list_remove( secound_free_block );
  test_call_heap_walk( false );
}
示例#2
0
文件: init.c 项目: epicsdeb/rtems
static void test_check_free_list(void)
{
  void *p1 = NULL;
  Heap_Block *first_free_block = NULL;
  Heap_Block *secound_free_block = NULL;
  Heap_Block *third_free_block = NULL;
  Heap_Block *used_block = NULL;

  puts( "testing the _Heap_Walk_check_free_list() function" );

  puts( "\tno free blocks" );
  test_heap_init_custom();
  test_fill_heap();
  test_call_heap_walk( true );

  puts( "\tcreate a loop in the free list" );
  test_heap_init_default();
  test_create_heap_with_gaps();
  /* find free blocks */
  first_free_block = _Heap_Free_list_first( &TestHeap );
  secound_free_block = first_free_block->next;
  third_free_block = secound_free_block->next;
  /* create a loop */
  third_free_block->next = secound_free_block;
  secound_free_block->prev = third_free_block;
  test_call_heap_walk( false );

  puts( "\tput a block outside the heap to the free list" );
  test_heap_init_default();
  first_free_block = _Heap_Free_list_first( &TestHeap );
  first_free_block->next = TestHeap.first_block - 1;
  test_call_heap_walk( false );

  puts( "\tput a block on the free list, which is not page-aligned" );
  test_heap_init_custom();
  test_create_heap_with_gaps();
  first_free_block = _Heap_Free_list_first( &TestHeap );
  first_free_block->next = (Heap_Block *) ((uintptr_t) first_free_block->next + CPU_ALIGNMENT);
  first_free_block->next->prev = first_free_block;
  test_call_heap_walk( false );

  puts( "\tput a used block on the free list" );
  test_heap_init_custom();
  test_create_heap_with_gaps();
  p1 = test_allocate_block();
  first_free_block = _Heap_Free_list_first( &TestHeap );
  used_block = _Heap_Block_of_alloc_area( (uintptr_t) p1, TestHeap.page_size );
  _Heap_Free_list_insert_after( first_free_block, used_block );
  test_call_heap_walk( false );
}
void _Heap_Get_free_information(
  Heap_Control        *the_heap,
  Heap_Information    *info
)
{
  Heap_Block *the_block;
  Heap_Block *const tail = _Heap_Free_list_tail(the_heap);

  info->number = 0;
  info->largest = 0;
  info->total = 0;

  for(the_block = _Heap_Free_list_first(the_heap);
      the_block != tail;
      the_block = the_block->next)
  {
    uint32_t const the_size = _Heap_Block_size(the_block);

    /* As we always coalesce free blocks, prev block must have been used. */
    _HAssert(_Heap_Is_prev_used(the_block));

    info->number++;
    info->total += the_size;
    if ( info->largest < the_size )
        info->largest = the_size;
  }
}
示例#4
0
Heap_Block *_Heap_Greedy_allocate(
  Heap_Control *heap,
  const uintptr_t *block_sizes,
  size_t block_count
)
{
  Heap_Block *const free_list_tail = _Heap_Free_list_tail( heap );
  Heap_Block *allocated_blocks = NULL;
  Heap_Block *blocks = NULL;
  Heap_Block *current;
  size_t i;

  _Heap_Protection_free_all_delayed_blocks( heap );

  for (i = 0; i < block_count; ++i) {
    void *next = _Heap_Allocate( heap, block_sizes [i] );

    if ( next != NULL ) {
      Heap_Block *next_block = _Heap_Block_of_alloc_area(
        (uintptr_t) next,
        heap->page_size
      );

      next_block->next = allocated_blocks;
      allocated_blocks = next_block;
    }
  }

  while ( (current = _Heap_Free_list_first( heap )) != free_list_tail ) {
    _Heap_Block_allocate(
      heap,
      current,
      _Heap_Alloc_area_of_block( current ),
      _Heap_Block_size( current ) - HEAP_BLOCK_HEADER_SIZE
    );

    current->next = blocks;
    blocks = current;
  }

  while ( allocated_blocks != NULL ) {
    current = allocated_blocks;
    allocated_blocks = allocated_blocks->next;
    _Heap_Free( heap, (void *) _Heap_Alloc_area_of_block( current ) );
  }

  return blocks;
}
示例#5
0
文件: heapwalk.c 项目: chch1028/rtems
static bool _Heap_Walk_is_in_free_list(
  Heap_Control *heap,
  Heap_Block *block
)
{
  const Heap_Block *const free_list_tail = _Heap_Free_list_tail( heap );
  const Heap_Block *free_block = _Heap_Free_list_first( heap );

  while ( free_block != free_list_tail ) {
    if ( free_block == block ) {
      return true;
    }
    free_block = free_block->next;
  }

  return false;
}
示例#6
0
static void _Heap_Free_block( Heap_Control *heap, Heap_Block *block )
{
  Heap_Statistics *const stats = &heap->stats;
  Heap_Block *first_free;

  /* Statistics */
  ++stats->used_blocks;
  --stats->frees;

  /*
   * The _Heap_Free() will place the block to the head of free list.  We want
   * the new block at the end of the free list.  So that initial and earlier
   * areas are consumed first.
   */
  _Heap_Free( heap, (void *) _Heap_Alloc_area_of_block( block ) );
  _Heap_Protection_free_all_delayed_blocks( heap );
  first_free = _Heap_Free_list_first( heap );
  _Heap_Free_list_remove( first_free );
  _Heap_Free_list_insert_before( _Heap_Free_list_tail( heap ), first_free );
}
示例#7
0
void *_Heap_Allocate_aligned_with_boundary(
  Heap_Control *heap,
  uintptr_t alloc_size,
  uintptr_t alignment,
  uintptr_t boundary
)
{
  Heap_Statistics *const stats = &heap->stats;
  uintptr_t const block_size_floor = alloc_size + HEAP_BLOCK_HEADER_SIZE
    - HEAP_ALLOC_BONUS;
  uintptr_t const page_size = heap->page_size;
  Heap_Block *block = NULL;
  uintptr_t alloc_begin = 0;
  uint32_t search_count = 0;
  bool search_again = false;

  if ( block_size_floor < alloc_size ) {
    /* Integer overflow occured */
    return NULL;
  }

  if ( boundary != 0 ) {
    if ( boundary < alloc_size ) {
      return NULL;
    }

    if ( alignment == 0 ) {
      alignment = page_size;
    }
  }

  do {
    Heap_Block *const free_list_tail = _Heap_Free_list_tail( heap );

    block = _Heap_Free_list_first( heap );
    while ( block != free_list_tail ) {
      _HAssert( _Heap_Is_prev_used( block ) );

      _Heap_Protection_block_check( heap, block );

      /*
       * The HEAP_PREV_BLOCK_USED flag is always set in the block size_and_flag
       * field.  Thus the value is about one unit larger than the real block
       * size.  The greater than operator takes this into account.
       */
      if ( block->size_and_flag > block_size_floor ) {
        if ( alignment == 0 ) {
          alloc_begin = _Heap_Alloc_area_of_block( block );
        } else {
          alloc_begin = _Heap_Check_block(
            heap,
            block,
            alloc_size,
            alignment,
            boundary
          );
        }
      }

      /* Statistics */
      ++search_count;

      if ( alloc_begin != 0 ) {
        break;
      }

      block = block->next;
    }

    search_again = _Heap_Protection_free_delayed_blocks( heap, alloc_begin );
  } while ( search_again );

  if ( alloc_begin != 0 ) {
    /* Statistics */
    ++stats->allocs;
    stats->searches += search_count;

    block = _Heap_Block_allocate( heap, block, alloc_begin, alloc_size );

    _Heap_Check_allocation(
      heap,
      block,
      alloc_begin,
      alloc_size,
      alignment,
      boundary
    );
  }

  /* Statistics */
  if ( stats->max_search < search_count ) {
    stats->max_search = search_count;
  }

  return (void *) alloc_begin;
}
示例#8
0
文件: heapwalk.c 项目: chch1028/rtems
static bool _Heap_Walk_check_free_list(
  int source,
  Heap_Walk_printer printer,
  Heap_Control *heap
)
{
  uintptr_t const page_size = heap->page_size;
  const Heap_Block *const free_list_tail = _Heap_Free_list_tail( heap );
  const Heap_Block *const first_free_block = _Heap_Free_list_first( heap );
  const Heap_Block *prev_block = free_list_tail;
  const Heap_Block *free_block = first_free_block;

  while ( free_block != free_list_tail ) {
    if ( !_Heap_Is_block_in_heap( heap, free_block ) ) {
      (*printer)(
        source,
        true,
        "free block 0x%08x: not in heap\n",
        free_block
      );

      return false;
    }

    if (
      !_Heap_Is_aligned( _Heap_Alloc_area_of_block( free_block ), page_size )
    ) {
      (*printer)(
        source,
        true,
        "free block 0x%08x: alloc area not page aligned\n",
        free_block
      );

      return false;
    }

    if ( _Heap_Is_used( free_block ) ) {
      (*printer)(
        source,
        true,
        "free block 0x%08x: is used\n",
        free_block
      );

      return false;
    }

    if ( free_block->prev != prev_block ) {
      (*printer)(
        source,
        true,
        "free block 0x%08x: invalid previous block 0x%08x\n",
        free_block,
        free_block->prev
      );

      return false;
    }

    prev_block = free_block;
    free_block = free_block->next;
  }

  return true;
}
示例#9
0
文件: heapwalk.c 项目: chch1028/rtems
static bool _Heap_Walk_check_free_block(
  int source,
  Heap_Walk_printer printer,
  Heap_Control *heap,
  Heap_Block *block
)
{
  Heap_Block *const free_list_tail = _Heap_Free_list_tail( heap );
  Heap_Block *const free_list_head = _Heap_Free_list_head( heap );
  Heap_Block *const first_free_block = _Heap_Free_list_first( heap );
  Heap_Block *const last_free_block = _Heap_Free_list_last( heap );
  bool const prev_used = _Heap_Is_prev_used( block );
  uintptr_t const block_size = _Heap_Block_size( block );
  Heap_Block *const next_block = _Heap_Block_at( block, block_size );

  (*printer)(
    source,
    false,
    "block 0x%08x: size %u, prev 0x%08x%s, next 0x%08x%s\n",
    block,
    block_size,
    block->prev,
    block->prev == first_free_block ?
      " (= first free)"
        : (block->prev == free_list_head ? " (= head)" : ""),
    block->next,
    block->next == last_free_block ?
      " (= last free)"
        : (block->next == free_list_tail ? " (= tail)" : "")
  );

  if ( block_size != next_block->prev_size ) {
    (*printer)(
      source,
      true,
      "block 0x%08x: size %u != size %u (in next block 0x%08x)\n",
      block,
      block_size,
      next_block->prev_size,
      next_block
    );

    return false;
  }

  if ( !prev_used ) {
    (*printer)(
      source,
      true,
      "block 0x%08x: two consecutive blocks are free\n",
      block
    );

    return false;
  }

  if ( !_Heap_Walk_is_in_free_list( heap, block ) ) {
    (*printer)(
      source,
      true,
      "block 0x%08x: free block not in free list\n",
      block
    );

    return false;
  }

  return true;
}
示例#10
0
文件: heapwalk.c 项目: chch1028/rtems
static bool _Heap_Walk_check_control(
  int source,
  Heap_Walk_printer printer,
  Heap_Control *heap
)
{
  uintptr_t const page_size = heap->page_size;
  uintptr_t const min_block_size = heap->min_block_size;
  Heap_Block *const first_free_block = _Heap_Free_list_first( heap );
  Heap_Block *const last_free_block = _Heap_Free_list_last( heap );
  Heap_Block *const first_block = heap->first_block;
  Heap_Block *const last_block = heap->last_block;

  (*printer)(
    source,
    false,
    "page size %u, min block size %u\n"
      "\tarea begin 0x%08x, area end 0x%08x\n"
      "\tfirst block 0x%08x, last block 0x%08x\n"
      "\tfirst free 0x%08x, last free 0x%08x\n",
    page_size, min_block_size,
    heap->area_begin, heap->area_end,
    first_block, last_block,
    first_free_block, last_free_block
  );

  if ( page_size == 0 ) {
    (*printer)( source, true, "page size is zero\n" );

    return false;
  }

  if ( !_Addresses_Is_aligned( (void *) page_size ) ) {
    (*printer)(
      source,
      true,
      "page size %u not CPU aligned\n",
      page_size
    );

    return false;
  }

  if ( !_Heap_Is_aligned( min_block_size, page_size ) ) {
    (*printer)(
      source,
      true,
      "min block size %u not page aligned\n",
      min_block_size
    );

    return false;
  }

  if (
    !_Heap_Is_aligned( _Heap_Alloc_area_of_block( first_block ), page_size )
  ) {
    (*printer)(
      source,
      true,
      "first block 0x%08x: alloc area not page aligned\n",
      first_block
    );

    return false;
  }

  if ( !_Heap_Is_prev_used( first_block ) ) {
    (*printer)(
      source,
      true,
      "first block: HEAP_PREV_BLOCK_USED is cleared\n"
    );

    return false;
  }

  if ( _Heap_Is_free( last_block ) ) {
    (*printer)(
      source,
      true,
      "last block: is free\n"
    );

    return false;
  }

  if (
    _Heap_Block_at( last_block, _Heap_Block_size( last_block ) ) != first_block
  ) {
    (*printer)(
      source,
      true,
      "last block: next block is not the first block\n"
    );

    return false;
  }

  return _Heap_Walk_check_free_list( source, printer, heap );
}