diff options
Diffstat (limited to 'cpukit/score')
-rw-r--r-- | cpukit/score/include/rtems/score/heap.h | 30 | ||||
-rw-r--r-- | cpukit/score/include/rtems/score/interr.h | 3 | ||||
-rw-r--r-- | cpukit/score/include/rtems/score/wkspace.h | 14 | ||||
-rw-r--r-- | cpukit/score/inline/rtems/score/heap.inl | 14 | ||||
-rw-r--r-- | cpukit/score/src/wkspace.c | 67 |
5 files changed, 95 insertions, 33 deletions
diff --git a/cpukit/score/include/rtems/score/heap.h b/cpukit/score/include/rtems/score/heap.h index 964386a36f..36ef48f3b6 100644 --- a/cpukit/score/include/rtems/score/heap.h +++ b/cpukit/score/include/rtems/score/heap.h @@ -675,6 +675,36 @@ Heap_Resize_status _Heap_Resize_block( uintptr_t *new_size ); +RTEMS_INLINE_ROUTINE uintptr_t _Heap_Align_up( + uintptr_t value, + uintptr_t alignment +) +{ + uintptr_t remainder = value % alignment; + + if ( remainder != 0 ) { + return value - remainder + alignment; + } else { + return value; + } +} + +/** + * @brief Returns the worst case overhead to manage a memory area. + */ +RTEMS_INLINE_ROUTINE uintptr_t _Heap_Area_overhead( + uintptr_t page_size +) +{ + if ( page_size != 0 ) { + page_size = _Heap_Align_up( page_size, CPU_ALIGNMENT ); + } else { + page_size = CPU_ALIGNMENT; + } + + return 2 * (page_size - 1) + HEAP_BLOCK_HEADER_SIZE; +} + #if !defined(__RTEMS_APPLICATION__) #include <rtems/score/heap.inl> diff --git a/cpukit/score/include/rtems/score/interr.h b/cpukit/score/include/rtems/score/interr.h index 19342a3db8..2a21fe01eb 100644 --- a/cpukit/score/include/rtems/score/interr.h +++ b/cpukit/score/include/rtems/score/interr.h @@ -72,7 +72,8 @@ typedef enum { INTERNAL_ERROR_UNLIMITED_AND_MAXIMUM_IS_0, INTERNAL_ERROR_SHUTDOWN_WHEN_NOT_UP, INTERNAL_ERROR_GXX_KEY_ADD_FAILED, - INTERNAL_ERROR_GXX_MUTEX_INIT_FAILED + INTERNAL_ERROR_GXX_MUTEX_INIT_FAILED, + INTERNAL_ERROR_NO_MEMORY_FOR_HEAP } Internal_errors_Core_list; typedef uint32_t Internal_errors_t; diff --git a/cpukit/score/include/rtems/score/wkspace.h b/cpukit/score/include/rtems/score/wkspace.h index 10b80ccaab..db6eb38f96 100644 --- a/cpukit/score/include/rtems/score/wkspace.h +++ b/cpukit/score/include/rtems/score/wkspace.h @@ -36,19 +36,23 @@ extern "C" { #include <rtems/score/interr.h> /** - * @brief Executive Workspace Control + * @brief Executive workspace control. * - * The is the heap control structure that used to manage the - * RTEMS Executive Workspace. + * This is the heap control structure used to manage the RTEMS Executive + * Workspace. */ -SCORE_EXTERN Heap_Control _Workspace_Area; /* executive heap header */ +SCORE_EXTERN Heap_Control _Workspace_Area; /** * @brief Workspace Handler Initialization * * This routine performs the initialization necessary for this handler. */ -void _Workspace_Handler_initialization(void); +void _Workspace_Handler_initialization( + Heap_Area *areas, + size_t area_count, + Heap_Initialization_or_extend_handler extend +); /** * @brief Allocate Memory from Workspace diff --git a/cpukit/score/inline/rtems/score/heap.inl b/cpukit/score/inline/rtems/score/heap.inl index b9553714c4..59bdd7b142 100644 --- a/cpukit/score/inline/rtems/score/heap.inl +++ b/cpukit/score/inline/rtems/score/heap.inl @@ -108,20 +108,6 @@ RTEMS_INLINE_ROUTINE bool _Heap_Is_aligned( return (value % alignment) == 0; } -RTEMS_INLINE_ROUTINE uintptr_t _Heap_Align_up( - uintptr_t value, - uintptr_t alignment -) -{ - uintptr_t remainder = value % alignment; - - if ( remainder != 0 ) { - return value - remainder + alignment; - } else { - return value; - } -} - RTEMS_INLINE_ROUTINE uintptr_t _Heap_Align_down( uintptr_t value, uintptr_t alignment diff --git a/cpukit/score/src/wkspace.c b/cpukit/score/src/wkspace.c index 842cade81b..7e58585173 100644 --- a/cpukit/score/src/wkspace.c +++ b/cpukit/score/src/wkspace.c @@ -28,28 +28,69 @@ /* * _Workspace_Handler_initialization */ -void _Workspace_Handler_initialization(void) +void _Workspace_Handler_initialization( + Heap_Area *areas, + size_t area_count, + Heap_Initialization_or_extend_handler extend +) { - uintptr_t memory_available = 0; - void *starting_address = rtems_configuration_get_work_space_start(); - uintptr_t size = rtems_configuration_get_work_space_size(); + Heap_Initialization_or_extend_handler init_or_extend = _Heap_Initialize; + uintptr_t remaining = rtems_configuration_get_work_space_size(); + bool do_zero = rtems_configuration_get_do_zero_of_workspace(); + bool unified = rtems_configuration_get_unified_work_area(); + uintptr_t page_size = CPU_HEAP_ALIGNMENT; + uintptr_t overhead = _Heap_Area_overhead( page_size ); + size_t i; + + for (i = 0; i < area_count; ++i) { + Heap_Area *area = &areas [i]; + + if ( do_zero ) { + memset( area->begin, 0, area->size ); + } + + if ( area->size > overhead ) { + uintptr_t space_available; + uintptr_t size; + + if ( unified ) { + size = area->size; + } else { + if ( remaining > 0 ) { + size = remaining < area->size - overhead ? + remaining + overhead : area->size; + } else { + size = 0; + } + } + + space_available = (*init_or_extend)( + &_Workspace_Area, + area->begin, + size, + page_size + ); + + area->begin = (char *) area->begin + size; + area->size -= size; - if ( rtems_configuration_get_do_zero_of_workspace() ) - memset( starting_address, 0, size ); + if ( space_available < remaining ) { + remaining -= space_available; + } else { + remaining = 0; + } - memory_available = _Heap_Initialize( - &_Workspace_Area, - starting_address, - size, - CPU_HEAP_ALIGNMENT - ); + init_or_extend = extend; + } + } - if ( memory_available == 0 ) + if ( remaining > 0 ) { _Internal_error_Occurred( INTERNAL_ERROR_CORE, true, INTERNAL_ERROR_TOO_LITTLE_WORKSPACE ); + } } /* |