forked from Imagelibrary/rtems
2009-09-09 Christian Mauderer <christian.mauderer@embedded-brains.de>
* heapwalk/init.c, heapwalk/heapwalk.scn, malloctest/init.c, malloctest/malloctest.scn: New test cases. * stackchk/blow.c, stackchk/stackchk.scn: Update for heap API changes.
This commit is contained in:
@@ -1,3 +1,9 @@
|
||||
2009-09-09 Christian Mauderer <christian.mauderer@embedded-brains.de>
|
||||
|
||||
* heapwalk/init.c, heapwalk/heapwalk.scn, malloctest/init.c,
|
||||
malloctest/malloctest.scn: New test cases.
|
||||
* stackchk/blow.c, stackchk/stackchk.scn: Update for heap API changes.
|
||||
|
||||
2009-09-03 Christian Mauderer <christian.mauderer@embedded-brains.de>
|
||||
|
||||
* malloctest/init.c: New test cases. Update for heap API changes.
|
||||
|
||||
@@ -1,6 +1,36 @@
|
||||
*** HEAP WALK TEST ***
|
||||
Calling Heap Walk without initialising
|
||||
PASS: 1 !HEAP_PREV_USED flag of 1st block isn't set
|
||||
start with a system state != SYSTEM_STATE_UP
|
||||
testing the _Heap_Walk_check_control() function
|
||||
test what happens if page size = 0
|
||||
set page size to a not CPU-aligned value
|
||||
set minimal block size to a not page aligned value
|
||||
let the alloc area of the first block be not page-aligned
|
||||
clear the previous used flag of the first block
|
||||
set the previous block size of the first block to an invalid value
|
||||
set invalid next block for last block
|
||||
testing the _Heap_Walk_check_free_list() function
|
||||
no free blocks
|
||||
create a loop in the free list
|
||||
put a block outside the heap to the free list
|
||||
put a block on the free list, which is not page-aligned
|
||||
put a used block on the free list
|
||||
Walk freshly initialized heap
|
||||
Passing negative value for source
|
||||
Test the main loop
|
||||
set the blocksize so, that the next block is outside the heap
|
||||
walk a heap with blocks with different states of the previous-used flag
|
||||
create a block with a not page aligned size
|
||||
create a block with a size smaller than the min_block_size
|
||||
make a block with a size, so that the block reaches into the next block
|
||||
make a block with a size, so that it includes the next block
|
||||
test the _Heap_Walk_check_free_block() function
|
||||
set a previous size for the next block which is not equal to the size of the actual block
|
||||
clear the previous_used flag of the first free block after an used block
|
||||
take a free block out of the free list
|
||||
test the output-function for the _Heap_Walk()
|
||||
therefore use the (already tested) case with a page size of 0
|
||||
PASS[0]: page size 0, min block size 16
|
||||
area begin 0x????????, area end 0x????????
|
||||
first block 0x????????, last block 0x????????
|
||||
first free 0x????????, last free 0x????????
|
||||
FAIL[0]: page size is zero
|
||||
*** END OF HEAP WALK TEST ***
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
* COPYRIGHT (c) 1989-2009.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
*
|
||||
* Copyright (c) 2009 embedded brains GmbH.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
@@ -23,137 +25,286 @@
|
||||
#include <rtems/dumpbuf.h>
|
||||
|
||||
#define TEST_HEAP_SIZE 1024
|
||||
#define TEST_DEFAULT_PAGESIZE 128
|
||||
#define DUMP false
|
||||
|
||||
unsigned TestHeapMemory[TEST_HEAP_SIZE];
|
||||
Heap_Control TestHeap;
|
||||
|
||||
static void test_heap_init(void)
|
||||
static void test_heap_init_with_page_size( uintptr_t page_size )
|
||||
{
|
||||
memset( TestHeapMemory, '\0', sizeof(TestHeapMemory) );
|
||||
_Heap_Initialize( &TestHeap, TestHeapMemory, sizeof(TestHeapMemory), 0 );
|
||||
memset( TestHeapMemory, 0xFF, sizeof(TestHeapMemory) );
|
||||
_Heap_Initialize( &TestHeap, TestHeapMemory, sizeof(TestHeapMemory), page_size );
|
||||
}
|
||||
|
||||
void test_heap_walk_body( int source, bool do_dump );
|
||||
|
||||
static void test_heap_walk( int source )
|
||||
static void test_heap_init_default(void)
|
||||
{
|
||||
test_heap_walk_body( source, true );
|
||||
test_heap_walk_body( source, false );
|
||||
test_heap_init_with_page_size( 0 );
|
||||
}
|
||||
|
||||
void test_heap_walk_body( int source, bool do_dump )
|
||||
static void test_heap_init_custom(void)
|
||||
{
|
||||
unsigned i, j, original;
|
||||
test_heap_init_with_page_size( TEST_DEFAULT_PAGESIZE );
|
||||
}
|
||||
|
||||
_Heap_Walk( &TestHeap, source, do_dump );
|
||||
static void test_call_heap_walk( bool expectet_retval )
|
||||
{
|
||||
bool retval = _Heap_Walk( &TestHeap, 0, DUMP );
|
||||
rtems_test_assert( retval == expectet_retval );
|
||||
}
|
||||
|
||||
static void *test_allocate_block(void)
|
||||
{
|
||||
return _Heap_Allocate_aligned_with_boundary( &TestHeap, 1, 0, 0 );
|
||||
}
|
||||
|
||||
static void test_create_heap_with_gaps()
|
||||
{
|
||||
void *p1 = test_allocate_block();
|
||||
void *p2 = test_allocate_block();
|
||||
void *p3 = test_allocate_block();
|
||||
void *p4 = test_allocate_block();
|
||||
void *p5 = test_allocate_block();
|
||||
void *p6 = test_allocate_block();
|
||||
_Heap_Free( &TestHeap, p1 );
|
||||
_Heap_Free( &TestHeap, p3 );
|
||||
_Heap_Free( &TestHeap, p5 );
|
||||
}
|
||||
|
||||
static void *test_fill_heap()
|
||||
{
|
||||
void *p1 = NULL;
|
||||
void *p2 = NULL;
|
||||
|
||||
do {
|
||||
p2 = p1;
|
||||
p1 = test_allocate_block();
|
||||
}while( p1 != NULL );
|
||||
|
||||
return p2;
|
||||
}
|
||||
|
||||
static void test_system_not_up(void)
|
||||
{
|
||||
rtems_interrupt_level level;
|
||||
|
||||
puts( "start with a system state != SYSTEM_STATE_UP" );
|
||||
|
||||
rtems_interrupt_disable( level );
|
||||
System_state_Codes state = _System_state_Get();
|
||||
_System_state_Set( SYSTEM_STATE_FAILED );
|
||||
test_call_heap_walk( true );
|
||||
_System_state_Set( state );
|
||||
rtems_interrupt_enable( level );
|
||||
}
|
||||
|
||||
static void test_check_control(void)
|
||||
{
|
||||
puts( "testing the _Heap_Walk_check_control() function" );
|
||||
|
||||
puts( "\ttest what happens if page size = 0" );
|
||||
test_heap_init_default();
|
||||
TestHeap.page_size = 0;
|
||||
test_call_heap_walk( false );
|
||||
|
||||
puts( "\tset page size to a not CPU-aligned value" );
|
||||
test_heap_init_default();
|
||||
TestHeap.page_size = 3 * (CPU_ALIGNMENT) / 2;
|
||||
test_call_heap_walk( false );
|
||||
|
||||
puts( "\tset minimal block size to a not page aligned value" );
|
||||
test_heap_init_custom();
|
||||
TestHeap.min_block_size = TEST_DEFAULT_PAGESIZE / 2;
|
||||
test_call_heap_walk( false );
|
||||
|
||||
/*
|
||||
* Now corrupt all non-zero values
|
||||
* Set the page size to a value, other than the first block alloc area. Set
|
||||
* even the min_block_size to that value to avoid it being not alligned.
|
||||
*/
|
||||
for (i=0 ; i<TEST_HEAP_SIZE ; i++) {
|
||||
original = TestHeapMemory[i];
|
||||
if ( original == 0 )
|
||||
continue;
|
||||
puts( "\tlet the alloc area of the first block be not page-aligned" );
|
||||
test_heap_init_custom();
|
||||
TestHeap.page_size = (uintptr_t) TestHeap.first_block + CPU_ALIGNMENT;
|
||||
TestHeap.min_block_size = TestHeap.page_size;
|
||||
test_call_heap_walk( false );
|
||||
|
||||
/* mark it free -- may or may not have already been */
|
||||
TestHeapMemory[i] &= ~0x01U;
|
||||
_Heap_Walk( &TestHeap, source, do_dump );
|
||||
puts( "\tclear the previous used flag of the first block" );
|
||||
test_heap_init_default();
|
||||
TestHeap.first_block->size_and_flag &= ~HEAP_PREV_BLOCK_USED;
|
||||
test_call_heap_walk( false );
|
||||
|
||||
/* mark it used -- may or may not have already been */
|
||||
TestHeapMemory[i] |= 0x01;
|
||||
_Heap_Walk( &TestHeap, source, do_dump );
|
||||
puts( "\tset the previous block size of the first block to an invalid value" );
|
||||
test_heap_init_custom();
|
||||
TestHeap.first_block->prev_size = 0;
|
||||
test_call_heap_walk( false );
|
||||
|
||||
/* try values of 2-7 in the last three bits -- push alignment issues */
|
||||
for (j=2 ; j<=7 ; j++) {
|
||||
TestHeapMemory[i] = (TestHeapMemory[i] & ~0x7U) | j;
|
||||
_Heap_Walk( &TestHeap, source, do_dump );
|
||||
}
|
||||
|
||||
|
||||
/* try 0 and see what that does */
|
||||
TestHeapMemory[i] = 0x00;
|
||||
_Heap_Walk( &TestHeap, source, do_dump );
|
||||
|
||||
/* try 0xffffffff and see what that does */
|
||||
TestHeapMemory[i] = 0xffffffff;
|
||||
_Heap_Walk( &TestHeap, source, do_dump );
|
||||
|
||||
TestHeapMemory[i] = original;
|
||||
}
|
||||
puts( "\tset invalid next block for last block" );
|
||||
test_heap_init_custom();
|
||||
TestHeap.last_block->size_and_flag = 0;
|
||||
test_call_heap_walk( false );
|
||||
}
|
||||
|
||||
static void test_walk_freshly_initialized(void)
|
||||
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 );
|
||||
}
|
||||
|
||||
static void test_freshly_initialized(void)
|
||||
{
|
||||
puts( "Walk freshly initialized heap" );
|
||||
test_heap_init();
|
||||
test_heap_walk(1);
|
||||
test_heap_init_default();
|
||||
test_call_heap_walk( true );
|
||||
}
|
||||
|
||||
static void test_negative_source_value(void)
|
||||
static void test_main_loop(void)
|
||||
{
|
||||
/*
|
||||
* Passing a negative value for source so that
|
||||
* the control enters the if block on line 67
|
||||
*/
|
||||
puts( "Passing negative value for source" );
|
||||
test_heap_init();
|
||||
test_heap_walk( -1 );
|
||||
void *p1 = NULL;
|
||||
void *p2 = NULL;
|
||||
Heap_Block *block = NULL;
|
||||
Heap_Block *next_block = NULL;
|
||||
|
||||
puts( "Test the main loop" );
|
||||
|
||||
puts( "\tset the blocksize so, that the next block is outside the heap" );
|
||||
test_heap_init_custom();
|
||||
/* use all blocks */
|
||||
p1 = test_fill_heap();
|
||||
block = _Heap_Block_of_alloc_area( (uintptr_t) p1, TestHeap.page_size );
|
||||
block->size_and_flag = ( 2 * _Heap_Block_size( block ) ) | HEAP_PREV_BLOCK_USED;
|
||||
test_call_heap_walk( false );
|
||||
|
||||
puts( "\twalk a heap with blocks with different states of the previous-used flag" );
|
||||
test_heap_init_custom();
|
||||
test_create_heap_with_gaps();
|
||||
test_allocate_block(); /* fill one gap */
|
||||
test_call_heap_walk( true );
|
||||
|
||||
puts( "\tcreate a block with a not page aligned size" );
|
||||
test_heap_init_custom();
|
||||
p1 = test_allocate_block();
|
||||
p2 = test_allocate_block();
|
||||
_Heap_Free( &TestHeap, p1 );
|
||||
block = _Heap_Block_of_alloc_area( (uintptr_t) p2, TestHeap.page_size );
|
||||
block->size_and_flag = (3 * TestHeap.page_size / 2) & ~HEAP_PREV_BLOCK_USED;
|
||||
test_call_heap_walk( false );
|
||||
|
||||
puts( "\tcreate a block with a size smaller than the min_block_size" );
|
||||
test_heap_init_default();
|
||||
p1 = test_allocate_block();
|
||||
p2 = test_allocate_block();
|
||||
_Heap_Free( &TestHeap, p1 );
|
||||
block = _Heap_Block_of_alloc_area( (uintptr_t) p2, TestHeap.page_size );
|
||||
block->size_and_flag = 0;
|
||||
test_call_heap_walk( false );
|
||||
|
||||
puts( "\tmake a block with a size, so that the block reaches into the next block" );
|
||||
test_heap_init_default();
|
||||
p1 = test_allocate_block();
|
||||
p2 = test_allocate_block();
|
||||
block = _Heap_Block_of_alloc_area( (uintptr_t) p1, TestHeap.page_size );
|
||||
block->size_and_flag = ( 3 * _Heap_Block_size( block ) / 2 ) | HEAP_PREV_BLOCK_USED;
|
||||
test_call_heap_walk( false );
|
||||
|
||||
puts( "\tmake a block with a size, so that it includes the next block" );
|
||||
test_heap_init_default();
|
||||
p1 = test_allocate_block();
|
||||
p2 = test_allocate_block();
|
||||
block = _Heap_Block_of_alloc_area( (uintptr_t) p1, TestHeap.page_size );
|
||||
next_block = _Heap_Block_at( block, _Heap_Block_size( block ) );
|
||||
block->size_and_flag = ( _Heap_Block_size( block ) + _Heap_Block_size( next_block ) ) | HEAP_PREV_BLOCK_USED;
|
||||
test_call_heap_walk( true );
|
||||
}
|
||||
|
||||
static void test_prev_block_flag_check(void)
|
||||
static void test_check_free_block(void)
|
||||
{
|
||||
/* Calling heapwalk without initialising the heap.
|
||||
* Covers line 80 and 85 on heapwalk.
|
||||
* Actually covers more than that.
|
||||
*/
|
||||
puts( "Calling Heap Walk without initialising" );
|
||||
test_heap_walk( 1 );
|
||||
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 );
|
||||
}
|
||||
|
||||
static void test_not_aligned(void)
|
||||
static void test_output(void)
|
||||
{
|
||||
/*
|
||||
* Hack to get to the error case where the blocks are
|
||||
* not on the page size. We initialize a heap with
|
||||
* default settings and change the page size to something
|
||||
* large.
|
||||
*/
|
||||
puts( "Testing case of blocks not on page size" );
|
||||
test_heap_init();
|
||||
TestHeap.page_size = 128;
|
||||
test_heap_walk( -1 );
|
||||
}
|
||||
|
||||
static void test_first_block_not_aligned(void)
|
||||
{
|
||||
/*
|
||||
* Hack to get to the error case where the blocks are
|
||||
* not on the page size. We initialize a heap with
|
||||
* default settings and change the page size to something
|
||||
* large.
|
||||
*/
|
||||
puts( "Testing case of blocks not on page size" );
|
||||
test_heap_init();
|
||||
_Heap_Free_list_head(&TestHeap)->next = (void *)1;
|
||||
test_heap_walk( -1 );
|
||||
}
|
||||
|
||||
static void test_not_in_free_list(void)
|
||||
{
|
||||
void *p1, *p2, *p3;
|
||||
|
||||
/*
|
||||
* Hack to get to the error case where the blocks are
|
||||
* not on the page size. We initialize a heap with
|
||||
* default settings and change the page size to something
|
||||
* large.
|
||||
*/
|
||||
puts( "Testing case of blocks not on page size" );
|
||||
test_heap_init();
|
||||
p1 =_Heap_Allocate( &TestHeap, 32 );
|
||||
p2 =_Heap_Allocate( &TestHeap, 32 );
|
||||
p3 =_Heap_Allocate( &TestHeap, 32 );
|
||||
_Heap_Free( &TestHeap, p2 );
|
||||
test_heap_walk( -1 );
|
||||
puts( "test the output-function for the _Heap_Walk()" );
|
||||
puts( "therefore use the (already tested) case with a page size of 0" );
|
||||
/* use simple case where one PASS and one FAIL will be put out */
|
||||
test_heap_init_default();
|
||||
TestHeap.page_size = 0;
|
||||
test_call_heap_walk( false );
|
||||
_Heap_Walk( &TestHeap, 0, true );
|
||||
}
|
||||
|
||||
rtems_task Init(
|
||||
@@ -162,12 +313,13 @@ rtems_task Init(
|
||||
{
|
||||
puts( "\n\n*** HEAP WALK TEST ***" );
|
||||
|
||||
test_prev_block_flag_check();
|
||||
test_walk_freshly_initialized();
|
||||
test_negative_source_value();
|
||||
test_not_aligned();
|
||||
test_not_in_free_list();
|
||||
test_first_block_not_aligned();
|
||||
test_system_not_up();
|
||||
test_check_control();
|
||||
test_check_free_list();
|
||||
test_freshly_initialized();
|
||||
test_main_loop();
|
||||
test_check_free_block();
|
||||
test_output();
|
||||
|
||||
puts( "*** END OF HEAP WALK TEST ***" );
|
||||
rtems_test_exit(0);
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
* COPYRIGHT (c) 1989-2009.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
*
|
||||
* Copyright (c) 2009 embedded brains GmbH.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
@@ -108,13 +110,13 @@ static void test_realloc(void)
|
||||
p4 = realloc( test_realloc, 32 );
|
||||
}
|
||||
|
||||
#define TEST_HEAP_SIZE 1024
|
||||
#define TEST_HEAP_SIZE 2048
|
||||
|
||||
uint8_t TestHeapMemory[TEST_HEAP_SIZE];
|
||||
|
||||
Heap_Control TestHeap;
|
||||
|
||||
static void test_heap_default_init()
|
||||
static void test_heap_default_init(void)
|
||||
{
|
||||
memset( &TestHeapMemory, 0x7f, TEST_HEAP_SIZE );
|
||||
_Heap_Initialize( &TestHeap, TestHeapMemory, TEST_HEAP_SIZE, 0 );
|
||||
@@ -125,7 +127,7 @@ static void test_free( void *addr )
|
||||
rtems_test_assert( _Heap_Free( &TestHeap, addr ) );
|
||||
}
|
||||
|
||||
static void test_heap_cases_1()
|
||||
static void test_heap_cases_1(void)
|
||||
{
|
||||
void *p1, *p2, *p3, *p4;
|
||||
intptr_t u1, u2;
|
||||
@@ -169,7 +171,7 @@ static void test_heap_cases_1()
|
||||
*/
|
||||
test_heap_default_init();
|
||||
puts( "Heap Initialized" );
|
||||
p1 = _Heap_Allocate( &TestHeap, 500 );
|
||||
p1 = _Heap_Allocate( &TestHeap, 400 );
|
||||
rtems_test_assert( p1 != NULL );
|
||||
p2 = _Heap_Allocate( &TestHeap, 496 );
|
||||
rtems_test_assert( p2 != NULL );
|
||||
@@ -357,7 +359,46 @@ static uintptr_t test_page_size(void)
|
||||
return TestHeap.page_size;
|
||||
}
|
||||
|
||||
static void test_heap_cases_2()
|
||||
static void test_heap_do_initialize(
|
||||
uintptr_t area_size,
|
||||
uintptr_t page_size,
|
||||
uintptr_t success_expected
|
||||
)
|
||||
{
|
||||
uintptr_t rv =
|
||||
_Heap_Initialize( &TestHeap, TestHeapMemory, area_size, page_size );
|
||||
|
||||
if ( success_expected ) {
|
||||
rtems_test_assert( rv > 0 && _Heap_Walk( &TestHeap, 0, false ) );
|
||||
} else {
|
||||
rtems_test_assert( rv == 0 );
|
||||
}
|
||||
}
|
||||
|
||||
static void test_heap_initialize(void)
|
||||
{
|
||||
uintptr_t rv = 0;
|
||||
|
||||
puts( "run tests for _Heap_Initialize()" );
|
||||
|
||||
test_heap_do_initialize( TEST_HEAP_SIZE, 0, true );
|
||||
|
||||
test_heap_do_initialize( TEST_HEAP_SIZE, TEST_DEFAULT_PAGE_SIZE, true );
|
||||
|
||||
test_heap_do_initialize( 0, 0, false );
|
||||
|
||||
test_heap_do_initialize( (uintptr_t) -1, 0, false );
|
||||
|
||||
test_heap_do_initialize( TEST_HEAP_SIZE, (uintptr_t) -1, false );
|
||||
|
||||
test_heap_do_initialize(
|
||||
TEST_HEAP_SIZE,
|
||||
(uintptr_t) (-2 * CPU_ALIGNMENT),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
static void test_heap_allocate(void)
|
||||
{
|
||||
void *p1 = NULL;
|
||||
void *p2 = NULL;
|
||||
@@ -540,60 +581,350 @@ static void test_heap_cases_2()
|
||||
p1 = test_init_and_alloc( alloc_size, alignment, boundary, NULL );
|
||||
}
|
||||
|
||||
static void test_block_alloc( uintptr_t alloc_begin, uintptr_t alloc_size )
|
||||
static void *test_create_used_block( void )
|
||||
{
|
||||
uintptr_t const alloc_size = 3 * TEST_DEFAULT_PAGE_SIZE;
|
||||
uintptr_t const alignment = 0;
|
||||
uintptr_t const boundary = 0;
|
||||
|
||||
return test_alloc_simple( alloc_size, alignment, boundary );
|
||||
}
|
||||
|
||||
static void test_block_alloc(
|
||||
int free_variant,
|
||||
int alloc_variant,
|
||||
uintptr_t alloc_begin,
|
||||
uintptr_t alloc_size
|
||||
)
|
||||
{
|
||||
void *p1 = NULL;
|
||||
void *p2 = NULL;
|
||||
void *p3 = NULL;
|
||||
|
||||
uintptr_t size_fresh_heap = 0;
|
||||
uintptr_t pages_per_default_block = 0;
|
||||
uint32_t exp_free_pages = 0;
|
||||
uint32_t exp_free_blocks = 0;
|
||||
uint32_t exp_used_blocks = 0;
|
||||
|
||||
test_heap_init( TEST_DEFAULT_PAGE_SIZE );
|
||||
|
||||
size_fresh_heap = _Heap_Get_size( &TestHeap );
|
||||
exp_free_pages = size_fresh_heap / TestHeap.page_size;
|
||||
|
||||
p1 = test_create_used_block();
|
||||
p2 = test_create_used_block();
|
||||
p3 = test_create_used_block();
|
||||
|
||||
pages_per_default_block = _Heap_Block_size(
|
||||
_Heap_Block_of_alloc_area( (uintptr_t) p1, TestHeap.page_size )
|
||||
) / TestHeap.page_size;
|
||||
|
||||
if (free_variant == 1) {
|
||||
test_free( p1 );
|
||||
} else if (free_variant == 2) {
|
||||
test_free( p3 );
|
||||
} else if (free_variant == 3) {
|
||||
test_free( p2 );
|
||||
test_free( p3 );
|
||||
}
|
||||
|
||||
_Heap_Block_allocate(
|
||||
&TestHeap,
|
||||
TestHeap.first_block,
|
||||
_Heap_Block_of_alloc_area( (uintptr_t) p2, test_page_size()),
|
||||
alloc_begin,
|
||||
alloc_size
|
||||
);
|
||||
|
||||
test_check_alloc_simple( (void *) alloc_begin, alloc_size, 0, 0 );
|
||||
|
||||
/* check statistics */
|
||||
switch( free_variant ) {
|
||||
case 1:
|
||||
exp_free_pages = exp_free_pages - 2 * pages_per_default_block;
|
||||
exp_used_blocks = 2;
|
||||
|
||||
switch( alloc_variant ) {
|
||||
case 1:
|
||||
/* allocate block full space */
|
||||
exp_free_blocks = 2;
|
||||
break;
|
||||
case 2:
|
||||
/* allocate block in the middle */
|
||||
exp_free_pages = exp_free_pages + pages_per_default_block - 1;
|
||||
exp_free_blocks = 3;
|
||||
break;
|
||||
case 3:
|
||||
/* allocate block at the end */
|
||||
exp_free_pages = exp_free_pages + pages_per_default_block - 2;
|
||||
exp_free_blocks = 2;
|
||||
break;
|
||||
default:
|
||||
/* allocate block at the beginning */
|
||||
exp_free_pages = exp_free_pages + pages_per_default_block - 1;
|
||||
exp_free_blocks = 3;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
exp_free_pages = exp_free_pages - 2 * pages_per_default_block;
|
||||
exp_used_blocks = 2;
|
||||
|
||||
switch( alloc_variant ) {
|
||||
case 1:
|
||||
/* allocate block full space */
|
||||
exp_free_blocks = 1;
|
||||
break;
|
||||
case 2:
|
||||
/* allocate block in the middle */
|
||||
exp_free_pages = exp_free_pages + pages_per_default_block - 1;
|
||||
exp_free_blocks = 2;
|
||||
break;
|
||||
case 3:
|
||||
/* allocate block at the end */
|
||||
exp_free_pages = exp_free_pages + pages_per_default_block - 1;
|
||||
exp_free_blocks = 2;
|
||||
break;
|
||||
default:
|
||||
/* allocate block at the beginning */
|
||||
exp_free_pages = exp_free_pages + pages_per_default_block - 1;
|
||||
exp_free_blocks = 1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
exp_free_pages = exp_free_pages - pages_per_default_block;
|
||||
exp_used_blocks = 2;
|
||||
|
||||
switch( alloc_variant ) {
|
||||
case 1:
|
||||
/* allocate block full space */
|
||||
exp_free_pages = exp_free_pages - pages_per_default_block;
|
||||
exp_free_blocks = 1;
|
||||
break;
|
||||
case 2:
|
||||
/* allocate block in the middle */
|
||||
exp_free_pages = exp_free_pages - 1;
|
||||
exp_free_blocks = 2;
|
||||
break;
|
||||
case 3:
|
||||
/* allocate block at the end */
|
||||
exp_free_pages = exp_free_pages - 2;
|
||||
exp_free_blocks = 2;
|
||||
break;
|
||||
default:
|
||||
/* allocate block at the beginning */
|
||||
exp_free_pages = exp_free_pages - 1;
|
||||
exp_free_blocks = 1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
exp_free_pages = exp_free_pages - 3 * pages_per_default_block;
|
||||
exp_used_blocks = 3;
|
||||
|
||||
switch( alloc_variant ) {
|
||||
case 1:
|
||||
/* allocate block full space */
|
||||
exp_free_blocks = 1;
|
||||
break;
|
||||
case 2:
|
||||
/* allocate block in the middle */
|
||||
exp_free_blocks = 3;
|
||||
exp_free_pages = exp_free_pages + pages_per_default_block - 1;
|
||||
break;
|
||||
case 3:
|
||||
/* allocate block at the end */
|
||||
exp_free_blocks = 2;
|
||||
exp_free_pages = exp_free_pages + pages_per_default_block - 1;
|
||||
break;
|
||||
default:
|
||||
/* allocate block at the beginning */
|
||||
exp_free_blocks = 2;
|
||||
exp_free_pages = exp_free_pages + pages_per_default_block - 1;
|
||||
}
|
||||
}
|
||||
|
||||
rtems_test_assert( TestHeap.stats.free_size == exp_free_pages * TestHeap.page_size );
|
||||
rtems_test_assert( TestHeap.stats.free_blocks == exp_free_blocks );
|
||||
rtems_test_assert( TestHeap.stats.used_blocks == exp_used_blocks );
|
||||
}
|
||||
|
||||
static void test_heap_cases_block_allocate()
|
||||
static void test_heap_do_block_allocate( int variant, void *p2 )
|
||||
{
|
||||
Heap_Block *const block =
|
||||
_Heap_Block_of_alloc_area( (uintptr_t) p2, test_page_size());
|
||||
uintptr_t const alloc_box_begin = _Heap_Alloc_area_of_block( block );
|
||||
uintptr_t const alloc_box_size = _Heap_Block_size( block );
|
||||
uintptr_t const alloc_box_end = alloc_box_begin + alloc_box_size;
|
||||
uintptr_t alloc_begin = 0;
|
||||
uintptr_t alloc_size = 0;
|
||||
uintptr_t alloc_box_begin = 0;
|
||||
uintptr_t alloc_box_end = 0;
|
||||
uintptr_t alloc_box_size = 0;
|
||||
|
||||
test_heap_init( TEST_DEFAULT_PAGE_SIZE );
|
||||
|
||||
alloc_box_begin = _Heap_Alloc_area_of_block( TestHeap.first_block );
|
||||
alloc_box_size = _Heap_Block_size( TestHeap.first_block );
|
||||
alloc_box_end = alloc_box_begin + alloc_box_size;
|
||||
|
||||
puts( "run tests for _Heap_Block_allocate()" );
|
||||
|
||||
puts( "\tallocate block at the beginning");
|
||||
alloc_begin = alloc_box_begin;
|
||||
alloc_size = 0;
|
||||
test_block_alloc( alloc_begin, alloc_size );
|
||||
test_block_alloc( variant, 0, alloc_begin, alloc_size );
|
||||
|
||||
puts( "\tallocate block full space");
|
||||
alloc_begin = alloc_box_begin;
|
||||
alloc_size = alloc_box_size + HEAP_BLOCK_SIZE_OFFSET
|
||||
- HEAP_BLOCK_HEADER_SIZE;
|
||||
test_block_alloc( alloc_begin, alloc_size );
|
||||
test_block_alloc( variant, 1, alloc_begin, alloc_size );
|
||||
|
||||
puts( "\tallocate block in the middle");
|
||||
alloc_begin = alloc_box_begin + TEST_DEFAULT_PAGE_SIZE;
|
||||
alloc_size = 0;
|
||||
test_block_alloc( alloc_begin, alloc_size );
|
||||
test_block_alloc( variant, 2, alloc_begin, alloc_size );
|
||||
|
||||
puts( "\tallocate block at the end");
|
||||
alloc_begin = alloc_box_end - TEST_DEFAULT_PAGE_SIZE;
|
||||
alloc_size = TEST_DEFAULT_PAGE_SIZE + HEAP_BLOCK_SIZE_OFFSET
|
||||
- HEAP_BLOCK_HEADER_SIZE;
|
||||
test_block_alloc( alloc_begin, alloc_size );
|
||||
test_block_alloc( variant, 3, alloc_begin, alloc_size );
|
||||
}
|
||||
|
||||
static void test_heap_extend()
|
||||
static void test_heap_block_allocate( void )
|
||||
{
|
||||
void *p2 = NULL;
|
||||
|
||||
puts( "run tests for _Heap_Block_allocate()" );
|
||||
|
||||
test_heap_init( TEST_DEFAULT_PAGE_SIZE );
|
||||
|
||||
test_create_used_block();
|
||||
p2 = test_create_used_block();
|
||||
|
||||
test_heap_do_block_allocate( 0, p2 );
|
||||
test_heap_do_block_allocate( 1, p2 );
|
||||
test_heap_do_block_allocate( 2, p2 );
|
||||
test_heap_do_block_allocate( 3, p2 );
|
||||
}
|
||||
|
||||
static void *test_alloc_one_page()
|
||||
{
|
||||
void *alloc_begin_ptr = _Heap_Allocate_aligned_with_boundary(
|
||||
&TestHeap,
|
||||
1,
|
||||
0,
|
||||
0
|
||||
);
|
||||
|
||||
test_check_alloc_simple(
|
||||
alloc_begin_ptr,
|
||||
1,
|
||||
0,
|
||||
0
|
||||
);
|
||||
|
||||
rtems_test_assert( alloc_begin_ptr != NULL );
|
||||
|
||||
return alloc_begin_ptr;
|
||||
}
|
||||
|
||||
static void *test_alloc_two_pages()
|
||||
{
|
||||
void *alloc_begin_ptr = _Heap_Allocate_aligned_with_boundary(
|
||||
&TestHeap,
|
||||
3 * TestHeap.page_size / 2,
|
||||
0,
|
||||
0
|
||||
);
|
||||
|
||||
test_check_alloc_simple(
|
||||
alloc_begin_ptr,
|
||||
3 * TestHeap.page_size / 2,
|
||||
0,
|
||||
0
|
||||
);
|
||||
|
||||
rtems_test_assert( alloc_begin_ptr != NULL );
|
||||
|
||||
return alloc_begin_ptr;
|
||||
}
|
||||
|
||||
static void test_simple_resize_block(
|
||||
void *alloc_pointer,
|
||||
uintptr_t new_alloc_size,
|
||||
Heap_Resize_status expected_status
|
||||
)
|
||||
{
|
||||
uintptr_t old_size = 0;
|
||||
uintptr_t new_size = 0;
|
||||
|
||||
Heap_Resize_status status = _Heap_Resize_block(
|
||||
&TestHeap,
|
||||
alloc_pointer,
|
||||
new_alloc_size,
|
||||
&old_size,
|
||||
&new_size
|
||||
);
|
||||
|
||||
rtems_test_assert( status == expected_status );
|
||||
}
|
||||
|
||||
static void test_heap_resize_block()
|
||||
{
|
||||
void *p1, *p2, *p3;
|
||||
uintptr_t new_alloc_size = 0;
|
||||
uintptr_t old_size = 0;
|
||||
uintptr_t new_size = 0;
|
||||
Heap_Block *block = NULL;
|
||||
|
||||
puts( "run tests for _Heap_Resize_Block()" );
|
||||
|
||||
puts( "\tgive a block outside the heap to the function" );
|
||||
test_heap_init( TEST_DEFAULT_PAGE_SIZE );
|
||||
p1 = TestHeap.first_block - TEST_DEFAULT_PAGE_SIZE;
|
||||
new_alloc_size = 1;
|
||||
test_simple_resize_block( p1, new_alloc_size, HEAP_RESIZE_FATAL_ERROR );
|
||||
|
||||
puts( "\tincrease size");
|
||||
|
||||
puts( "\t\tlet the next block be used alredy and try to get a size bigger than the actual block" );
|
||||
test_heap_init( TEST_DEFAULT_PAGE_SIZE );
|
||||
p1 = test_alloc_one_page();
|
||||
p2 = test_alloc_one_page();
|
||||
new_alloc_size = 3 * TEST_DEFAULT_PAGE_SIZE / 2;
|
||||
test_simple_resize_block( p1, new_alloc_size, HEAP_RESIZE_UNSATISFIED );
|
||||
|
||||
puts( "\t\tnext block not used and try to set the new allocation size between the page-alignments" );
|
||||
test_heap_init( TEST_DEFAULT_PAGE_SIZE );
|
||||
p1 = test_alloc_one_page();
|
||||
new_alloc_size = 3 * TEST_DEFAULT_PAGE_SIZE / 2;
|
||||
test_simple_resize_block( p1, new_alloc_size, HEAP_RESIZE_SUCCESSFUL );
|
||||
|
||||
puts( "\t\tlet the block after the next be used and try to allocate more then one pagesize more" );
|
||||
test_heap_init( TEST_DEFAULT_PAGE_SIZE );
|
||||
p1 = test_alloc_one_page();
|
||||
p2 = test_alloc_one_page();
|
||||
p3 = test_alloc_one_page();
|
||||
_Heap_Free( &TestHeap, p2 );
|
||||
new_alloc_size = 5 * TEST_DEFAULT_PAGE_SIZE / 2;
|
||||
test_simple_resize_block( p1, new_alloc_size, HEAP_RESIZE_UNSATISFIED );
|
||||
|
||||
puts( "\ttry to resize to the same size" );
|
||||
test_heap_init( TEST_DEFAULT_PAGE_SIZE );
|
||||
p1 = test_alloc_one_page();
|
||||
block = _Heap_Block_of_alloc_area( (uintptr_t) p1, TestHeap.page_size );
|
||||
new_alloc_size = _Heap_Block_size( block );
|
||||
test_simple_resize_block( p1, new_alloc_size, HEAP_RESIZE_SUCCESSFUL );
|
||||
|
||||
puts( "\tdecrease size");
|
||||
|
||||
puts( "\t\tdecrease a block with two pages to one page" );
|
||||
test_heap_init( TEST_DEFAULT_PAGE_SIZE );
|
||||
p1 = test_alloc_two_pages();
|
||||
new_alloc_size = 1;
|
||||
test_simple_resize_block( p1, new_alloc_size, HEAP_RESIZE_SUCCESSFUL );
|
||||
|
||||
puts( "\t\tresize the block to the size 0" );
|
||||
test_heap_init( TEST_DEFAULT_PAGE_SIZE );
|
||||
p1 = test_alloc_one_page();
|
||||
new_alloc_size = 0;
|
||||
test_simple_resize_block( p1, new_alloc_size, HEAP_RESIZE_SUCCESSFUL );
|
||||
}
|
||||
|
||||
static void test_heap_extend(void)
|
||||
{
|
||||
void *p1, *p2, *p3, *p4;
|
||||
uint32_t u1, u2;
|
||||
@@ -675,25 +1006,6 @@ static void test_protected_heap_info(void)
|
||||
rtems_test_assert( rc == false );
|
||||
}
|
||||
|
||||
static void test_heap_resize(void)
|
||||
{
|
||||
Heap_Resize_status rc;
|
||||
void *p1;
|
||||
intptr_t oldsize;
|
||||
intptr_t avail;
|
||||
|
||||
puts( "Initialize Test Heap" );
|
||||
test_heap_default_init();
|
||||
|
||||
puts( "Allocate most of heap" );
|
||||
p1 = _Heap_Allocate( &TestHeap, TEST_HEAP_SIZE - 32 );
|
||||
rtems_test_assert( p1 != NULL );
|
||||
|
||||
puts( "Resize (shrink) the area to 8 bytes to ensure remainder gets freed" );
|
||||
rc = _Heap_Resize_block( &TestHeap, p1, 8, &oldsize, &avail );
|
||||
rtems_test_assert( rc == HEAP_RESIZE_SUCCESSFUL );
|
||||
}
|
||||
|
||||
/*
|
||||
* A simple test of posix_memalign
|
||||
*/
|
||||
@@ -756,14 +1068,15 @@ rtems_task Init(
|
||||
status = rtems_clock_set( &time );
|
||||
directive_failed( status, "rtems_clock_set" );
|
||||
|
||||
test_heap_cases_2();
|
||||
test_heap_cases_block_allocate();
|
||||
test_heap_initialize();
|
||||
test_heap_block_allocate();
|
||||
test_heap_allocate();
|
||||
test_heap_resize_block();
|
||||
test_realloc();
|
||||
test_heap_cases_1();
|
||||
test_heap_extend();
|
||||
test_heap_info();
|
||||
test_protected_heap_info();
|
||||
test_heap_resize();
|
||||
|
||||
test_posix_memalign();
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -30,7 +30,8 @@ b();
|
||||
|
||||
area = (unsigned char *)_Thread_Executing->Start.Initial_stack.area;
|
||||
|
||||
low = (volatile uint32_t *) (area + HEAP_BLOCK_HEADER_SIZE);
|
||||
/* Look in the stack checker implementation for this magic offset */
|
||||
low = (volatile uint32_t *) (area + sizeof(Heap_Block) - HEAP_BLOCK_HEADER_SIZE);
|
||||
high = (volatile uint32_t *)
|
||||
(area + _Thread_Executing->Start.Initial_stack.size - 16);
|
||||
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
*** TEST STACK CHECKER ***
|
||||
TA1 - rtems_clock_get - 09:00:00 12/31/1988
|
||||
TA2 - rtems_clock_get - 09:00:00 12/31/1988
|
||||
TA3 - rtems_clock_get - 09:00:00 12/31/1988
|
||||
TA1 - rtems_clock_get - 09:00:05 12/31/1988
|
||||
TA1 - rtems_clock_get - 09:00:10 12/31/1988
|
||||
TA2 - rtems_clock_get - 09:00:10 12/31/1988
|
||||
TA1 - rtems_clock_get - 09:00:15 12/31/1988
|
||||
---> error indication similar to:
|
||||
BLOWN STACK!!! Offending task(0x23EE7A0): id=0x0A010002; name=0x54413120
|
||||
stack covers range 0x23F1BD0 - 0x23F4BDF (12304 bytes)
|
||||
Damaged pattern begins at 0x023F1BD8 and is 16 bytes long
|
||||
TA1 - rtems_clock_get_tod - 09:00:00 12/31/1988
|
||||
TA2 - rtems_clock_get_tod - 09:00:00 12/31/1988
|
||||
TA3 - rtems_clock_get_tod - 09:00:00 12/31/1988
|
||||
TA1 - rtems_clock_get_tod - 09:00:05 12/31/1988
|
||||
TA1 - rtems_clock_get_tod - 09:00:10 12/31/1988
|
||||
TA2 - rtems_clock_get_tod - 09:00:10 12/31/1988
|
||||
TA1 - rtems_clock_get_tod - 09:00:15 12/31/1988
|
||||
BLOWN STACK!!!
|
||||
task control block: 0x????????
|
||||
task ID: 0x0A010002
|
||||
task name: 0x????????
|
||||
task name string: TA1
|
||||
task stack area (????? Bytes): 0x???????? .. 0x????????
|
||||
damaged pattern area (16 Bytes): 0x???????? .. 0x????????
|
||||
|
||||
Reference in New Issue
Block a user