summaryrefslogtreecommitdiffstats
path: root/cpukit
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
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 'cpukit')
-rw-r--r--cpukit/libcsupport/Makefile.am4
-rw-r--r--cpukit/libcsupport/include/rtems/libcsupport.h6
-rw-r--r--cpukit/libcsupport/include/rtems/malloc.h45
-rw-r--r--cpukit/libcsupport/src/malloc.c3
-rw-r--r--cpukit/libcsupport/src/malloc_initialize.c115
-rw-r--r--cpukit/libcsupport/src/malloc_p.h5
-rw-r--r--cpukit/libcsupport/src/malloc_sbrk_helpers.c108
-rw-r--r--cpukit/libcsupport/src/mallocinfo.c6
-rw-r--r--cpukit/libcsupport/src/rtems_heap_extend_via_sbrk.c58
-rw-r--r--cpukit/libcsupport/src/rtems_heap_null_extend.c27
-rw-r--r--cpukit/libmisc/monitor/mon-config.c1
-rw-r--r--cpukit/sapi/include/confdefs.h9
-rw-r--r--cpukit/sapi/include/rtems/config.h10
-rw-r--r--cpukit/sapi/src/exinit.c6
-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
19 files changed, 270 insertions, 261 deletions
diff --git a/cpukit/libcsupport/Makefile.am b/cpukit/libcsupport/Makefile.am
index 04d2455dfd..703ef60199 100644
--- a/cpukit/libcsupport/Makefile.am
+++ b/cpukit/libcsupport/Makefile.am
@@ -98,8 +98,10 @@ MALLOC_C_FILES = src/malloc_initialize.c src/calloc.c src/malloc.c \
src/mallocinfo.c src/malloc_walk.c src/malloc_get_statistics.c \
src/malloc_report_statistics.c src/malloc_report_statistics_plugin.c \
src/malloc_statistics_helpers.c src/posix_memalign.c \
- src/rtems_memalign.c src/malloc_deferred.c src/malloc_sbrk_helpers.c \
+ src/rtems_memalign.c src/malloc_deferred.c \
src/malloc_dirtier.c src/malloc_p.h src/rtems_malloc.c \
+ src/rtems_heap_extend_via_sbrk.c \
+ src/rtems_heap_null_extend.c \
src/rtems_heap_extend.c \
src/rtems_heap_greedy.c
diff --git a/cpukit/libcsupport/include/rtems/libcsupport.h b/cpukit/libcsupport/include/rtems/libcsupport.h
index d2640476df..919b41eea3 100644
--- a/cpukit/libcsupport/include/rtems/libcsupport.h
+++ b/cpukit/libcsupport/include/rtems/libcsupport.h
@@ -27,12 +27,6 @@
extern "C" {
#endif
-void RTEMS_Malloc_Initialize(
- void *heap_begin,
- uintptr_t heap_size,
- size_t sbrk_amount
-);
-
extern void malloc_dump(void);
extern bool malloc_walk(int source, bool printf_enabled);
void malloc_set_heap_pointer(Heap_Control *new_heap);
diff --git a/cpukit/libcsupport/include/rtems/malloc.h b/cpukit/libcsupport/include/rtems/malloc.h
index d195b9fef1..9d475d33b1 100644
--- a/cpukit/libcsupport/include/rtems/malloc.h
+++ b/cpukit/libcsupport/include/rtems/malloc.h
@@ -26,6 +26,20 @@
extern "C" {
#endif
+/**
+ * @brief C program heap control.
+ *
+ * This is the pointer to the heap control structure used to manage the C
+ * program heap.
+ */
+extern Heap_Control *RTEMS_Malloc_Heap;
+
+void RTEMS_Malloc_Initialize(
+ const Heap_Area *areas,
+ size_t area_count,
+ Heap_Initialization_or_extend_handler extend
+);
+
/*
* Malloc Statistics Structure
*/
@@ -54,16 +68,29 @@ extern rtems_malloc_statistics_functions_t
rtems_malloc_statistics_helpers_table;
extern rtems_malloc_statistics_functions_t *rtems_malloc_statistics_helpers;
-/*
- * Malloc Heap Extension (sbrk) plugin
- */
-typedef struct {
- void *(*initialize)(void *, size_t);
- void *(*extend)(size_t);
-} rtems_malloc_sbrk_functions_t;
+extern ptrdiff_t RTEMS_Malloc_Sbrk_amount;
+
+static inline void rtems_heap_set_sbrk_amount( ptrdiff_t sbrk_amount )
+{
+ RTEMS_Malloc_Sbrk_amount = sbrk_amount;
+}
+
+typedef void *(*rtems_heap_extend_handler)(
+ Heap_Control *heap,
+ size_t alloc_size
+);
+
+void *rtems_heap_extend_via_sbrk(
+ Heap_Control *heap,
+ size_t alloc_size
+);
+
+void *rtems_heap_null_extend(
+ Heap_Control *heap,
+ size_t alloc_size
+);
-extern rtems_malloc_sbrk_functions_t rtems_malloc_sbrk_helpers_table;
-extern rtems_malloc_sbrk_functions_t *rtems_malloc_sbrk_helpers;
+extern const rtems_heap_extend_handler rtems_malloc_extend_handler;
/*
* Malloc Plugin to Dirty Memory at Allocation Time
diff --git a/cpukit/libcsupport/src/malloc.c b/cpukit/libcsupport/src/malloc.c
index 0fff1d011c..dea6f8f3c7 100644
--- a/cpukit/libcsupport/src/malloc.c
+++ b/cpukit/libcsupport/src/malloc.c
@@ -55,8 +55,7 @@ void *malloc(
return_this = _Protected_heap_Allocate( RTEMS_Malloc_Heap, size );
if ( !return_this ) {
- if (rtems_malloc_sbrk_helpers)
- return_this = (*rtems_malloc_sbrk_helpers->extend)( size );
+ return_this = (*rtems_malloc_extend_handler)( RTEMS_Malloc_Heap, size );
if ( !return_this ) {
errno = ENOMEM;
return (void *) 0;
diff --git a/cpukit/libcsupport/src/malloc_initialize.c b/cpukit/libcsupport/src/malloc_initialize.c
index fccddd1368..06263bda82 100644
--- a/cpukit/libcsupport/src/malloc_initialize.c
+++ b/cpukit/libcsupport/src/malloc_initialize.c
@@ -1,11 +1,11 @@
/**
* @file
*
- * @brief Malloc initialization implementation.
+ * @brief RTEMS_Malloc_Initialize() implementation.
*/
/*
- * COPYRIGHT (c) 1989-2007.
+ * COPYRIGHT (c) 1989-2012.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
@@ -14,93 +14,68 @@
*/
#if HAVE_CONFIG_H
-#include "config.h"
+ #include "config.h"
#endif
-#include <rtems.h>
#include <rtems/malloc.h>
-#include <rtems/score/wkspace.h>
+
#include "malloc_p.h"
-/* FIXME: Dummy function */
-#ifndef RTEMS_NEWLIB
-void RTEMS_Malloc_Initialize(
- void *heap_begin,
- uintptr_t heap_size,
- size_t sbrk_amount
-)
-{
-}
-#else
+#ifdef RTEMS_NEWLIB
rtems_malloc_statistics_t rtems_malloc_statistics;
void RTEMS_Malloc_Initialize(
- void *heap_begin,
- uintptr_t heap_size,
- size_t sbrk_amount
+ const Heap_Area *areas,
+ size_t area_count,
+ Heap_Initialization_or_extend_handler extend
)
{
- bool separate_areas = !rtems_configuration_get_unified_work_area();
- /*
- * If configured, initialize the statistics support
- */
- if ( rtems_malloc_statistics_helpers != NULL ) {
- (*rtems_malloc_statistics_helpers->initialize)();
- }
+ Heap_Control *heap = RTEMS_Malloc_Heap;
- /*
- * Initialize the optional sbrk support for extending the heap
- */
- if ( rtems_malloc_sbrk_helpers != NULL ) {
- void *new_heap_begin = (*rtems_malloc_sbrk_helpers->initialize)(
- heap_begin,
- sbrk_amount
- );
-
- heap_size -= (uintptr_t) new_heap_begin - (uintptr_t) heap_begin;
- heap_begin = new_heap_begin;
- }
+ if ( !rtems_configuration_get_unified_work_area() ) {
+ Heap_Initialization_or_extend_handler init_or_extend = _Heap_Initialize;
+ uintptr_t page_size = CPU_HEAP_ALIGNMENT;
+ size_t i;
- /*
- * If this system is configured to use the same heap for
- * the RTEMS Workspace and C Program Heap, then we need to
- * be very very careful about destroying the initialization
- * that has already been done.
- */
+ for (i = 0; i < area_count; ++i) {
+ const Heap_Area *area = &areas [i];
+ uintptr_t space_available = (*init_or_extend)(
+ heap,
+ area->begin,
+ area->size,
+ page_size
+ );
- /*
- * If the BSP is not clearing out the workspace, then it is most likely
- * not clearing out the initial memory for the heap. There is no
- * standard supporting zeroing out the heap memory. But much code
- * with UNIX history seems to assume that memory malloc'ed during
- * initialization (before any free's) is zero'ed. This is true most
- * of the time under UNIX because zero'ing memory when it is first
- * given to a process eliminates the chance of a process seeing data
- * left over from another process. This would be a security violation.
- */
+ if ( space_available > 0 ) {
+ init_or_extend = extend;
+ }
+ }
- if ( separate_areas && rtems_configuration_get_do_zero_of_workspace() ) {
- memset( heap_begin, 0, heap_size );
+ if ( init_or_extend == _Heap_Initialize ) {
+ _Internal_error_Occurred(
+ INTERNAL_ERROR_CORE,
+ true,
+ INTERNAL_ERROR_NO_MEMORY_FOR_HEAP
+ );
+ }
}
/*
- * Unfortunately we cannot use assert if this fails because if this
- * has failed we do not have a heap and if we do not have a heap
- * STDIO cannot work because there will be no buffers.
+ * If configured, initialize the statistics support
*/
-
- if ( separate_areas ) {
- uintptr_t status = _Protected_heap_Initialize(
- RTEMS_Malloc_Heap,
- heap_begin,
- heap_size,
- CPU_HEAP_ALIGNMENT
- );
- if ( status == 0 ) {
- rtems_fatal_error_occurred( RTEMS_NO_MEMORY );
- }
+ if ( rtems_malloc_statistics_helpers != NULL ) {
+ (*rtems_malloc_statistics_helpers->initialize)();
}
- MSBUMP( space_available, _Protected_heap_Get_size(RTEMS_Malloc_Heap) );
+ MSBUMP( space_available, _Protected_heap_Get_size( heap ) );
+}
+#else
+void RTEMS_Malloc_Initialize(
+ Heap_Area *areas,
+ size_t area_count,
+ Heap_Initialization_or_extend_handler extend
+)
+{
+ /* FIXME: Dummy function */
}
#endif
diff --git a/cpukit/libcsupport/src/malloc_p.h b/cpukit/libcsupport/src/malloc_p.h
index ea0709f0e7..6bd9a495f7 100644
--- a/cpukit/libcsupport/src/malloc_p.h
+++ b/cpukit/libcsupport/src/malloc_p.h
@@ -23,11 +23,6 @@
#include <rtems/chain.h>
/*
- * Basic management data
- */
-extern Heap_Control *RTEMS_Malloc_Heap;
-
-/*
* Malloc Statistics Structure
*/
extern rtems_malloc_statistics_t rtems_malloc_statistics;
diff --git a/cpukit/libcsupport/src/malloc_sbrk_helpers.c b/cpukit/libcsupport/src/malloc_sbrk_helpers.c
deleted file mode 100644
index 64572a154e..0000000000
--- a/cpukit/libcsupport/src/malloc_sbrk_helpers.c
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * RTEMS Malloc -- SBRK Support Plugin
- *
- * COPYRIGHT (c) 1989-2007.
- * On-Line Applications Research Corporation (OAR).
- *
- * 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.
- */
-
-#if HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <unistd.h> /* sbrk */
-
-#include <rtems.h>
-#include <rtems/malloc.h>
-#include "malloc_p.h"
-
-#include <errno.h>
-
-size_t RTEMS_Malloc_Sbrk_amount;
-
-static void *malloc_sbrk_initialize(
- void *starting_address,
- size_t length
-)
-{
- uintptr_t old_address;
- uintptr_t uaddress;
-
- RTEMS_Malloc_Sbrk_amount = length;
-
- /*
- * If the starting address is 0 then we are to attempt to
- * get length worth of memory using sbrk. Make sure we
- * align the address that we get back.
- */
-
- if (!starting_address) {
- uaddress = (uintptr_t)sbrk(length);
-
- if (uaddress == (uintptr_t) -1) {
- rtems_fatal_error_occurred( RTEMS_NO_MEMORY );
- /* DOES NOT RETURN!!! */
- }
-
- if (uaddress & (CPU_HEAP_ALIGNMENT-1)) {
- old_address = uaddress;
- uaddress = (uaddress + CPU_HEAP_ALIGNMENT) & ~(CPU_HEAP_ALIGNMENT-1);
-
- /*
- * adjust the length by whatever we aligned by
- */
- length -= uaddress - old_address;
- }
-
- starting_address = (void *)uaddress;
- }
- return starting_address;
-}
-
-static void *malloc_sbrk_extend_and_allocate(
- size_t size
-)
-{
- uint32_t sbrk_amount;
- void *starting_address;
- uint32_t the_size;
- void *return_this;
-
- /*
- * Round to the "requested sbrk amount" so hopefully we won't have
- * to grow again for a while. This effectively does sbrk() calls
- * in "page" amounts.
- */
-
- sbrk_amount = RTEMS_Malloc_Sbrk_amount;
-
- if ( sbrk_amount == 0 )
- return (void *) 0;
-
- the_size = ((size + sbrk_amount) / sbrk_amount * sbrk_amount);
-
- starting_address = (void *) sbrk(the_size);
- if ( starting_address == (void*) -1 )
- return (void *) 0;
-
- if ( !_Protected_heap_Extend(
- RTEMS_Malloc_Heap, starting_address, the_size) ) {
- sbrk(-the_size);
- errno = ENOMEM;
- return (void *) 0;
- }
-
- MSBUMP(space_available, the_size);
-
- return_this = _Protected_heap_Allocate( RTEMS_Malloc_Heap, size );
- return return_this;
-}
-
-
-rtems_malloc_sbrk_functions_t rtems_malloc_sbrk_helpers_table = {
- malloc_sbrk_initialize,
- malloc_sbrk_extend_and_allocate
-};
diff --git a/cpukit/libcsupport/src/mallocinfo.c b/cpukit/libcsupport/src/mallocinfo.c
index 47aefc3ff4..1532608420 100644
--- a/cpukit/libcsupport/src/mallocinfo.c
+++ b/cpukit/libcsupport/src/mallocinfo.c
@@ -14,13 +14,9 @@
#include "config.h"
#endif
-#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
-#include <rtems.h>
-#include <rtems/libcsupport.h>
+#include <rtems/malloc.h>
#include <rtems/score/protectedheap.h>
-extern Heap_Control *RTEMS_Malloc_Heap;
-
/*
* Find amount of free heap remaining
*/
diff --git a/cpukit/libcsupport/src/rtems_heap_extend_via_sbrk.c b/cpukit/libcsupport/src/rtems_heap_extend_via_sbrk.c
new file mode 100644
index 0000000000..831626b3d5
--- /dev/null
+++ b/cpukit/libcsupport/src/rtems_heap_extend_via_sbrk.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2012 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * 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.
+ */
+
+#if HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include <unistd.h>
+
+#include <rtems/malloc.h>
+
+#include "malloc_p.h"
+
+ptrdiff_t RTEMS_Malloc_Sbrk_amount;
+
+void *rtems_heap_extend_via_sbrk(
+ Heap_Control *heap,
+ size_t alloc_size
+)
+{
+ ptrdiff_t sbrk_amount = RTEMS_Malloc_Sbrk_amount;
+ ptrdiff_t sbrk_size = (ptrdiff_t) alloc_size;
+ ptrdiff_t misaligned = sbrk_size % sbrk_amount;
+ void *return_this = NULL;
+
+ if ( misaligned != 0 ) {
+ sbrk_size += sbrk_amount - misaligned;
+ }
+
+ if ( sbrk_size > 0 && sbrk_amount > 0 ) {
+ void *area_begin = sbrk( sbrk_size );
+
+ if ( area_begin != (void *) -1 ) {
+ bool ok = _Protected_heap_Extend( heap, area_begin, sbrk_size );
+
+ if ( ok ) {
+ MSBUMP( space_available, sbrk_size );
+
+ return_this = _Protected_heap_Allocate( heap, alloc_size );
+ } else {
+ sbrk( -sbrk_size );
+ }
+ }
+ }
+
+ return return_this;
+}
diff --git a/cpukit/libcsupport/src/rtems_heap_null_extend.c b/cpukit/libcsupport/src/rtems_heap_null_extend.c
new file mode 100644
index 0000000000..a821ef48f9
--- /dev/null
+++ b/cpukit/libcsupport/src/rtems_heap_null_extend.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2012 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * 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.
+ */
+
+#if HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include <rtems/malloc.h>
+
+void *rtems_heap_null_extend(
+ Heap_Control *heap __attribute__((unused)),
+ size_t alloc_size __attribute__((unused))
+)
+{
+ return NULL;
+}
diff --git a/cpukit/libmisc/monitor/mon-config.c b/cpukit/libmisc/monitor/mon-config.c
index 0df87d625f..b5bc31ce9d 100644
--- a/cpukit/libmisc/monitor/mon-config.c
+++ b/cpukit/libmisc/monitor/mon-config.c
@@ -33,7 +33,6 @@ rtems_monitor_config_canonical(
rtems_configuration_table *c = (rtems_configuration_table *) config_void;
rtems_api_configuration_table *r = &Configuration_RTEMS_API;
- canonical_config->work_space_start = c->work_space_start;
canonical_config->work_space_size = c->work_space_size;
canonical_config->maximum_tasks = r->maximum_tasks;
canonical_config->maximum_timers = r->maximum_timers;
diff --git a/cpukit/sapi/include/confdefs.h b/cpukit/sapi/include/confdefs.h
index d4f21ca376..09edc97770 100644
--- a/cpukit/sapi/include/confdefs.h
+++ b/cpukit/sapi/include/confdefs.h
@@ -901,11 +901,11 @@ rtems_fs_init_functions_t rtems_fs_init_helper =
* RAM to the malloc family implementation so sbrk()'ing to get
* more memory would always fail anyway.
*/
- rtems_malloc_sbrk_functions_t *rtems_malloc_sbrk_helpers =
- #ifndef CONFIGURE_MALLOC_BSP_SUPPORTS_SBRK
- NULL;
+ const rtems_heap_extend_handler rtems_malloc_extend_handler =
+ #ifdef CONFIGURE_MALLOC_BSP_SUPPORTS_SBRK
+ rtems_heap_extend_via_sbrk;
#else
- &rtems_malloc_sbrk_helpers_table;
+ rtems_heap_null_extend;
#endif
#endif
@@ -2318,7 +2318,6 @@ rtems_fs_init_functions_t rtems_fs_init_helper =
* This is the primary Configuration Table for this application.
*/
rtems_configuration_table Configuration = {
- NULL, /* filled in by BSP */
CONFIGURE_EXECUTIVE_RAM_SIZE, /* required RTEMS workspace */
CONFIGURE_STACK_SPACE_SIZE, /* required stack space */
CONFIGURE_MAXIMUM_USER_EXTENSIONS, /* maximum dynamic extensions */
diff --git a/cpukit/sapi/include/rtems/config.h b/cpukit/sapi/include/rtems/config.h
index 58b350da76..d0e181c781 100644
--- a/cpukit/sapi/include/rtems/config.h
+++ b/cpukit/sapi/include/rtems/config.h
@@ -124,10 +124,6 @@ typedef void (*rtems_stack_free_hook)( void *addr );
* + required number of each object type for each API configured
*/
typedef struct {
- /** This field specifies the base address of the RTEMS Workspace.
- */
- void *work_space_start;
-
/** This field specifies the size in bytes of the RTEMS Workspace.
*/
uintptr_t work_space_size;
@@ -266,12 +262,6 @@ extern rtems_configuration_table Configuration;
#define rtems_configuration_set_stack_space_size( _size ) \
do { Configuration.stack_space_size = (_size); } while (0)
-#define rtems_configuration_get_work_space_start() \
- (Configuration.work_space_start)
-
-#define rtems_configuration_set_work_space_start( _start ) \
- do { Configuration.work_space_start = (_start); } while (0)
-
#define rtems_configuration_get_work_space_size() \
(Configuration.work_space_size + \
(rtems_configuration_get_stack_allocator_avoids_work_space() ? \
diff --git a/cpukit/sapi/src/exinit.c b/cpukit/sapi/src/exinit.c
index 82e853a142..1aa7e544bb 100644
--- a/cpukit/sapi/src/exinit.c
+++ b/cpukit/sapi/src/exinit.c
@@ -111,12 +111,6 @@ void rtems_initialize_data_structures(void)
_Thread_Dispatch_initialization();
- /*
- * Before this is called, we are not allowed to allocate memory
- * from the Workspace because it is not initialized.
- */
- _Workspace_Handler_initialization();
-
#if defined(RTEMS_SMP)
_SMP_Handler_initialize();
#endif
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
);
+ }
}
/*