diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2010-06-07 09:35:01 +0000 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2010-06-07 09:35:01 +0000 |
commit | b2a0214d4395787eca8e74375d283bf26c9ca4a1 (patch) | |
tree | eb91086d7da6342ea88ad774939bb90afcfd3e4f /cpukit/score/src/heap.c | |
parent | 2010-06-07 Sebastian Huber <sebastian.huber@embedded-brains.de> (diff) | |
download | rtems-b2a0214d4395787eca8e74375d283bf26c9ca4a1.tar.bz2 |
2010-06-07 Sebastian Huber <sebastian.huber@embedded-brains.de>
* score/include/rtems/score/heap.h: Declare
_Heap_Get_first_and_last_block(). Removed Heap_Extend_status.
Changed return type of _Heap_Extend() to bool.
* score/inline/rtems/score/heap.inl: Define
_Heap_Set_last_block_size().
* score/src/heap.c: Define and use _Heap_Get_first_and_last_block().
* score/src/heapgetinfo.c: Removed assert statements. Do not count
the last block. This ensures that all size values are an integral
multiple of the page size which is consistent with the other
statistics.
* score/src/heapextend.c: Implemented support for scattered heap
areas.
* score/src/heapwalk.c: Dump also last block. Changes for new first
and last block values.
* ./score/src/pheapextend.c, rtems/src/regionextend.c: Update for
_Heap_Extend() changes.
Diffstat (limited to 'cpukit/score/src/heap.c')
-rw-r--r-- | cpukit/score/src/heap.c | 92 |
1 files changed, 60 insertions, 32 deletions
diff --git a/cpukit/score/src/heap.c b/cpukit/score/src/heap.c index c851334679..a0efe71cdd 100644 --- a/cpukit/score/src/heap.c +++ b/cpukit/score/src/heap.c @@ -10,7 +10,7 @@ * COPYRIGHT (c) 1989-2009. * On-Line Applications Research Corporation (OAR). * - * Copyright (c) 2009 embedded brains GmbH. + * Copyright (c) 2009, 2010 embedded brains GmbH. * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at @@ -123,6 +123,43 @@ static uint32_t instance = 0; * */ +bool _Heap_Get_first_and_last_block( + uintptr_t heap_area_begin, + uintptr_t heap_area_size, + uintptr_t page_size, + uintptr_t min_block_size, + Heap_Block **first_block_ptr, + Heap_Block **last_block_ptr +) +{ + uintptr_t const heap_area_end = heap_area_begin + heap_area_size; + uintptr_t const alloc_area_begin = + _Heap_Align_up( heap_area_begin + HEAP_BLOCK_HEADER_SIZE, page_size ); + uintptr_t const first_block_begin = + alloc_area_begin - HEAP_BLOCK_HEADER_SIZE; + uintptr_t const overhead = + HEAP_BLOCK_HEADER_SIZE + (first_block_begin - heap_area_begin); + uintptr_t const first_block_size = + _Heap_Align_down( heap_area_size - overhead, page_size ); + Heap_Block *const first_block = (Heap_Block *) first_block_begin; + Heap_Block *const last_block = + _Heap_Block_at( first_block, first_block_size ); + + if ( + heap_area_end < heap_area_begin + || heap_area_size <= overhead + || first_block_size < min_block_size + ) { + /* Invalid area or area too small */ + return false; + } + + *first_block_ptr = first_block; + *last_block_ptr = last_block; + + return true; +} + uintptr_t _Heap_Initialize( Heap_Control *heap, void *heap_area_begin_ptr, @@ -133,12 +170,11 @@ uintptr_t _Heap_Initialize( Heap_Statistics *const stats = &heap->stats; uintptr_t const heap_area_begin = (uintptr_t) heap_area_begin_ptr; uintptr_t const heap_area_end = heap_area_begin + heap_area_size; - uintptr_t alloc_area_begin = heap_area_begin + HEAP_BLOCK_HEADER_SIZE; - uintptr_t alloc_area_size = 0; uintptr_t first_block_begin = 0; uintptr_t first_block_size = 0; + uintptr_t last_block_begin = 0; uintptr_t min_block_size = 0; - uintptr_t overhead = 0; + bool area_ok = false; Heap_Block *first_block = NULL; Heap_Block *last_block = NULL; @@ -154,41 +190,28 @@ uintptr_t _Heap_Initialize( } min_block_size = _Heap_Align_up( sizeof( Heap_Block ), page_size ); - alloc_area_begin = _Heap_Align_up( alloc_area_begin, page_size ); - first_block_begin = alloc_area_begin - HEAP_BLOCK_HEADER_SIZE; - overhead = HEAP_BLOCK_HEADER_SIZE + (first_block_begin - heap_area_begin); - first_block_size = heap_area_size - overhead; - first_block_size = _Heap_Align_down ( first_block_size, page_size ); - alloc_area_size = first_block_size - HEAP_BLOCK_HEADER_SIZE; - - if ( - heap_area_end < heap_area_begin - || heap_area_size <= overhead - || first_block_size < min_block_size - ) { - /* Invalid area or area too small */ + area_ok = _Heap_Get_first_and_last_block( + heap_area_begin, + heap_area_size, + page_size, + min_block_size, + &first_block, + &last_block + ); + if ( !area_ok ) { return 0; } + first_block_begin = (uintptr_t) first_block; + last_block_begin = (uintptr_t) last_block; + first_block_size = last_block_begin - first_block_begin; + /* First block */ - first_block = (Heap_Block *) first_block_begin; - first_block->prev_size = page_size; + first_block->prev_size = heap_area_end; first_block->size_and_flag = first_block_size | HEAP_PREV_BLOCK_USED; first_block->next = _Heap_Free_list_tail( heap ); first_block->prev = _Heap_Free_list_head( heap ); - /* - * Last block. - * - * The next block of the last block is the first block. Since the first - * block indicates that the previous block is used, this ensures that the - * last block appears as used for the _Heap_Is_used() and _Heap_Is_free() - * functions. - */ - last_block = _Heap_Block_at( first_block, first_block_size ); - last_block->prev_size = first_block_size; - last_block->size_and_flag = first_block_begin - (uintptr_t) last_block; - /* Heap control */ heap->page_size = page_size; heap->min_block_size = min_block_size; @@ -199,6 +222,11 @@ uintptr_t _Heap_Initialize( _Heap_Free_list_head( heap )->next = first_block; _Heap_Free_list_tail( heap )->prev = first_block; + /* Last block */ + last_block->prev_size = first_block_size; + last_block->size_and_flag = 0; + _Heap_Set_last_block_size( heap ); + /* Statistics */ stats->size = first_block_size; stats->free_size = first_block_size; @@ -222,7 +250,7 @@ uintptr_t _Heap_Initialize( _Heap_Is_aligned( _Heap_Alloc_area_of_block( last_block ), page_size ) ); - return alloc_area_size; + return first_block_size; } void _Heap_Block_split( |