summaryrefslogtreecommitdiffstats
path: root/cpukit/score
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2012-08-09 16:48:00 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2012-10-25 14:54:06 +0200
commit47a3cd8f73780bad3eff5135f0eb58e8c98af91d (patch)
tree8acdfc6ebe5d596f9c6b974e6c460dc69e824e3c /cpukit/score
parentscore: Append to free list in _Heap_Extend() (diff)
downloadrtems-47a3cd8f73780bad3eff5135f0eb58e8c98af91d.tar.bz2
score: Work area initialization API change
The work areas (RTEMS work space and C program heap) will be initialized now in a separate step and are no longer part of rtems_initialize_data_structures(). Initialization is performed with tables of Heap_Area entries. This allows usage of scattered memory areas present on various small scale micro-controllers. The sbrk() support API changes also. The bsp_sbrk_init() must now deal with a minimum size for the first memory chunk to take the configured work space size into account.
Diffstat (limited to '')
-rw-r--r--cpukit/score/include/rtems/score/heap.h30
-rw-r--r--cpukit/score/include/rtems/score/interr.h3
-rw-r--r--cpukit/score/include/rtems/score/wkspace.h14
-rw-r--r--cpukit/score/inline/rtems/score/heap.inl14
-rw-r--r--cpukit/score/src/wkspace.c67
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
);
+ }
}
/*