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.
This commit is contained in:
Sebastian Huber
2012-08-09 16:48:00 +02:00
parent e4278f2050
commit 47a3cd8f73
51 changed files with 545 additions and 906 deletions

View File

@@ -11,21 +11,11 @@
extern void _end;
extern void __heap_limit;
/*
* This method returns the base address and size of the area which
* is to be allocated between the RTEMS Workspace and the C Program
* Heap.
*/
void bsp_get_work_area(
void **work_area_start,
uintptr_t *work_area_size,
void **heap_start,
uintptr_t *heap_size
)
void bsp_work_area_initialize(void)
{
*work_area_start = (void *)&_end;
*work_area_size = (uintptr_t)&__heap_limit - (uintptr_t)&_end;
*heap_start = BSP_BOOTCARD_HEAP_USES_WORK_AREA;
*heap_size = BSP_BOOTCARD_HEAP_SIZE_DEFAULT;
void *area_start = (void *)&_end;
uintptr_t area_size = (uintptr_t)&__heap_limit - (uintptr_t)&_end;
bsp_work_area_initialize_default( area_start, area_size );
}

View File

@@ -1,5 +1,5 @@
/*
* This routine is an implementation of the bsp_get_work_area()
* This routine is an implementation of the bsp_work_area_initialize()
* that can be used by all m68k BSPs following linkcmds conventions
* regarding heap, stack, and workspace allocation.
*
@@ -120,30 +120,10 @@ void bsp_size_memory(void)
bsp_mem_size = topAddr;
}
/*
* This method returns the base address and size of the area which
* is to be allocated between the RTEMS Workspace and the C Program
* Heap.
*/
void bsp_get_work_area(
void **work_area_start,
uintptr_t *work_area_size,
void **heap_start,
uintptr_t *heap_size
)
void bsp_work_area_initialize(void)
{
*work_area_start = (void *) rtemsWorkAreaStart;
*work_area_size = (uintptr_t) bsp_mem_size - (uintptr_t) rtemsWorkAreaStart;
*heap_start = BSP_BOOTCARD_HEAP_USES_WORK_AREA;
*heap_size = (uintptr_t) HeapSize;
void *area_start = (void *) rtemsWorkAreaStart;
uintptr_t work_area_size = (uintptr_t) bsp_mem_size - (uintptr_t) rtemsWorkAreaStart;
#ifdef BSP_GET_WORK_AREA_DEBUG
printk( "bsp_mem_size = 0x%08x\n", bsp_mem_size );
printk( "rtemsWorkAreaStart = 0x%08x\n", rtemsWorkAreaStart );
printk( "WorkArea Base = %p\n", *work_area_start );
printk( "WorkArea Size = 0x%08x\n", *work_area_size );
printk( "C Program Heap Base = %p\n", *heap_start );
printk( "C Program Heap Size = 0x%08x\n", *heap_size );
printk( "End of WorkArea = %p\n", *work_area_start + *work_area_size );
#endif
bsp_work_area_initialize_default( area_start, area_size );
}

View File

@@ -4,28 +4,12 @@
* http://www.rtems.com/license/LICENSE.
*/
/* #define BSP_GET_WORK_AREA_DEBUG */
#include <bsp.h>
#include <bsp/bootcard.h>
#include <stdint.h>
#ifdef BSP_GET_WORK_AREA_DEBUG
#include <rtems/bspIo.h>
#endif
extern void *__rtems_end;
/*
* This method returns the base address and size of the area which
* is to be allocated between the RTEMS Workspace and the C Program
* Heap.
*/
void bsp_get_work_area(
void **work_area_start,
uintptr_t *work_area_size,
void **heap_start,
uintptr_t *heap_size
)
void bsp_work_area_initialize(void)
{
uintptr_t work_size;
uintptr_t work_area;
@@ -34,36 +18,5 @@ void bsp_get_work_area(
rtems_configuration_get_interrupt_stack_size();
work_size = (uintptr_t)BSP_mem_size - work_area;
*work_area_start = (void *)work_area,
*work_area_size = work_size;
*heap_start = BSP_BOOTCARD_HEAP_USES_WORK_AREA;
*heap_size = BSP_BOOTCARD_HEAP_SIZE_DEFAULT;
/*
* The following may be helpful in debugging what goes wrong when
* you are allocating the Work Area in a new BSP.
*/
#ifdef BSP_GET_WORK_AREA_DEBUG
{
void *sp = __builtin_frame_address(0);
void *end = *work_area_start + *work_area_size;
printk(
"work_area_start = 0x%p\n"
"work_area_size = %d 0x%08x\n"
"end = 0x%p\n"
"heap_start = 0x%p\n"
"heap_size = %d\n"
"current stack pointer = 0x%p%s\n",
*work_area_start,
*work_area_size, /* decimal */
*work_area_size, /* hexadecimal */
end,
*heap_start,
*heap_size,
sp,
((sp >= *work_area_start && sp <= end) ? " OVERLAPS!" : "")
);
}
#endif
bsp_work_area_initialize_default((void *) work_area, work_size);
}

View File

@@ -61,15 +61,15 @@
* for module code.
*/
#include <rtems.h>
#include <signal.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
static void * remaining_start=(void*)-1LL;
static uintptr_t remaining_size=0;
#include <bsp/bootcard.h>
#define INVALID_REMAINING_START ((uintptr_t) -1)
static uintptr_t remaining_start = INVALID_REMAINING_START;
static uintptr_t remaining_size = 0;
/* App. may provide a value by defining the BSP_sbrk_policy
* variable.
@@ -81,24 +81,24 @@ static uintptr_t remaining_size=0;
*/
extern uintptr_t BSP_sbrk_policy __attribute__((weak));
#define LIMIT_32M ((void*)0x02000000)
#define LIMIT_32M 0x02000000
uintptr_t bsp_sbrk_init(
void *heap_start,
uintptr_t *heap_size_p
)
ptrdiff_t bsp_sbrk_init(Heap_Area *area, uintptr_t min_size)
{
uintptr_t rval=0;
uintptr_t rval = 0;
uintptr_t policy;
uintptr_t remaining_end;
remaining_start = heap_start;
remaining_size = *heap_size_p;
remaining_start = (uintptr_t) area->begin;
remaining_size = area->size;
remaining_end = remaining_start + remaining_size;
if (remaining_start < LIMIT_32M &&
remaining_start + remaining_size > LIMIT_32M) {
remaining_end > LIMIT_32M &&
min_size <= LIMIT_32M - remaining_start) {
/* clip at LIMIT_32M */
rval = remaining_start + remaining_size - LIMIT_32M;
*heap_size_p = LIMIT_32M - remaining_start;
rval = remaining_end - LIMIT_32M;
area->size = LIMIT_32M - remaining_start;
remaining_start = LIMIT_32M;
remaining_size = rval;
}
@@ -106,8 +106,8 @@ uintptr_t bsp_sbrk_init(
policy = (0 == &BSP_sbrk_policy ? (uintptr_t)(-1) : BSP_sbrk_policy);
switch ( policy ) {
case (uintptr_t)(-1):
*heap_size_p += rval;
remaining_start = heap_start + *heap_size_p;
area->size += rval;
remaining_start = (uintptr_t) area->begin + area->size;
remaining_size = 0;
break;
@@ -121,7 +121,7 @@ uintptr_t bsp_sbrk_init(
break;
}
return rval;
return (ptrdiff_t) (rval <= PTRDIFF_MAX ? rval : rval / 2);
}
/*
@@ -129,14 +129,13 @@ uintptr_t bsp_sbrk_init(
* should just use the default implementation in this file.
*/
void *sbrk(ptrdiff_t incr) __attribute__ (( weak, alias("bsp_sbrk") ));
void *bsp_sbrk(ptrdiff_t incr)
static void *bsp_sbrk(ptrdiff_t incr)
{
void *rval=(void*)-1;
/* FIXME: BEWARE if size >2G */
if ( remaining_start != (void*)-1LL && incr <= remaining_size) {
if ( remaining_start != INVALID_REMAINING_START && incr <= remaining_size) {
remaining_size-=incr;
rval = remaining_start;
rval = (void *) remaining_start;
remaining_start += incr;
} else {
errno = ENOMEM;

View File

@@ -7,12 +7,13 @@
*/
/*
* Copyright (c) 2008
* Embedded Brains GmbH
* Copyright (c) 2008-2012 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
* Obere Lagerstr. 30
* D-82178 Puchheim
* 82178 Puchheim
* Germany
* rtems@embedded-brains.de
* <rtems@embedded-brains.de>
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
@@ -24,17 +25,11 @@
#include <bsp.h>
#include <bsp/bootcard.h>
void bsp_get_work_area(
void **work_area_start,
uintptr_t *work_area_size,
void **heap_start,
uintptr_t *heap_size
)
void bsp_work_area_initialize(void)
{
char *ram_end = (char *) (TQM_BD_INFO.sdram_size - (uint32_t)TopRamReserved);
void *area_start = bsp_work_area_start;
uintptr_t area_size = (uintptr_t) ram_end - (uintptr_t) bsp_work_area_start;
*work_area_start = bsp_work_area_start;
*work_area_size = ram_end - bsp_work_area_start;
*heap_start = BSP_BOOTCARD_HEAP_USES_WORK_AREA;
*heap_size = BSP_BOOTCARD_HEAP_SIZE_DEFAULT;
bsp_work_area_initialize_default( area_start, area_size );
}

View File

@@ -63,41 +63,6 @@
*/
const char *bsp_boot_cmdline;
/*
* These are the prototypes and helper routines which are used
* when the BSP lets the framework handle RAM allocation between
* the RTEMS Workspace and C Program Heap.
*/
static void bootcard_bsp_libc_helper(
void *work_area_start,
uintptr_t work_area_size,
void *heap_start,
uintptr_t heap_size,
uintptr_t sbrk_amount
)
{
if ( heap_start == BSP_BOOTCARD_HEAP_USES_WORK_AREA ) {
if ( !rtems_configuration_get_unified_work_area() ) {
uintptr_t work_space_size = rtems_configuration_get_work_space_size();
heap_start = (char *) work_area_start + work_space_size;
if (heap_size == BSP_BOOTCARD_HEAP_SIZE_DEFAULT) {
uintptr_t heap_size_default = work_area_size - work_space_size;
heap_size = heap_size_default;
}
} else {
heap_start = work_area_start;
if (heap_size == BSP_BOOTCARD_HEAP_SIZE_DEFAULT) {
heap_size = work_area_size;
}
}
}
bsp_libc_init(heap_start, heap_size, sbrk_amount);
}
/*
* This is the initialization framework routine that weaves together
* calls to RTEMS and the BSP in the proper sequence to initialize
@@ -109,12 +74,6 @@ uint32_t boot_card(
)
{
rtems_interrupt_level bsp_isr_level;
void *work_area_start = NULL;
uintptr_t work_area_size = 0;
void *heap_start = NULL;
uintptr_t heap_size = 0;
uintptr_t sbrk_amount = 0;
uintptr_t work_space_size = 0;
uint32_t status = 0;
/*
@@ -138,74 +97,9 @@ uint32_t boot_card(
bsp_start();
/*
* Find out where the block of memory the BSP will use for
* the RTEMS Workspace and the C Program Heap is.
* Initialize the RTEMS Workspace and the C Program Heap.
*/
bsp_get_work_area(&work_area_start, &work_area_size,
&heap_start, &heap_size);
#ifdef CONFIGURE_MALLOC_BSP_SUPPORTS_SBRK
/* This routine may reduce the work area size with the
* option to extend it later via sbrk(). If the application
* was configured w/o CONFIGURE_MALLOC_BSP_SUPPORTS_SBRK then
* omit this step.
*/
if ( rtems_malloc_sbrk_helpers ) {
sbrk_amount = bsp_sbrk_init(work_area_start, &work_area_size);
work_space_size = rtems_configuration_get_work_space_size();
if ( work_area_size < work_space_size && sbrk_amount > 0 ) {
/* Need to use sbrk right now */
uintptr_t sbrk_now;
sbrk_now = (work_space_size - work_area_size) / sbrk_amount;
sbrk( sbrk_now * sbrk_amount );
}
}
#else
if ( rtems_malloc_sbrk_helpers ) {
printk("Configuration error!\n"
"Application was configured with CONFIGURE_MALLOC_BSP_SUPPORTS_SBRK\n"
"but BSP was configured w/o sbrk support\n");
status = 1;
bsp_cleanup( status );
return status;
}
#endif
/*
* If the user has configured a set of objects which will require more
* workspace than is actually available, print a message indicating
* such and return to the invoking initialization code.
*
* NOTE: Output from printk() may not work at this point on some BSPs.
*
* NOTE: Use cast to (void *) and %p since these are uintptr_t types.
*/
work_space_size = rtems_configuration_get_work_space_size();
if ( work_area_size <= work_space_size ) {
printk(
"bootcard: work space too big for work area: %p >= %p\n",
(void *) work_space_size,
(void *) work_area_size
);
status = 1;
bsp_cleanup( status );
return status;
}
if ( !rtems_configuration_get_unified_work_area() ) {
rtems_configuration_set_work_space_start( work_area_start );
} else {
rtems_configuration_set_work_space_start( work_area_start );
rtems_configuration_set_work_space_size( work_area_size );
if ( !rtems_configuration_get_stack_allocator_avoids_work_space() ) {
rtems_configuration_set_stack_space_size( 0 );
}
}
#if (BSP_DIRTY_MEMORY == 1)
memset( work_area_start, 0xCF, work_area_size );
#endif
bsp_work_area_initialize();
/*
* Initialize RTEMS data structures
@@ -216,13 +110,7 @@ uint32_t boot_card(
* Initialize the C library for those BSPs using the shared
* framework.
*/
bootcard_bsp_libc_helper(
work_area_start,
work_area_size,
heap_start,
heap_size,
sbrk_amount
);
bsp_libc_init();
/*
* Let the BSP do any required initialization now that RTEMS

View File

@@ -1,25 +1,20 @@
/*
* This routine is an implementation of the bsp_get_work_area()
* This routine is an implementation of the bsp_work_area_initialize()
* that can be used by all BSPs following linkcmds conventions
* regarding heap, stack, and workspace allocation.
*
* COPYRIGHT (c) 1989-2008.
* On-Line Applications Research Corporation (OAR).
*
* Copyright (c) 2011 embedded brains GmbH.
* Copyright (c) 2011-2012 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.
*/
/* #define BSP_GET_WORK_AREA_DEBUG */
#include <bsp.h>
#include <bsp/bootcard.h>
#ifdef BSP_GET_WORK_AREA_DEBUG
#include <rtems/bspIo.h>
#endif
#ifdef BSP_INTERRUPT_STACK_AT_WORK_AREA_BEGIN
#include <rtems/config.h>
#endif
@@ -32,7 +27,6 @@
* These are provided by the linkcmds for ALL of the BSPs which use this file.
*/
extern char WorkAreaBase[];
extern char HeapSize[];
/*
* We may get the size information from U-Boot or the linker scripts.
@@ -44,17 +38,7 @@ extern char HeapSize[];
extern char RamSize[];
#endif
/*
* This method returns the base address and size of the area which
* is to be allocated between the RTEMS Workspace and the C Program
* Heap.
*/
void bsp_get_work_area(
void **work_area_start,
uintptr_t *work_area_size,
void **heap_start,
uintptr_t *heap_size
)
void bsp_work_area_initialize(void)
{
uintptr_t work_base = (uintptr_t) WorkAreaBase;
uintptr_t ram_end;
@@ -70,35 +54,5 @@ void bsp_get_work_area(
work_base += Configuration.interrupt_stack_size;
#endif
*work_area_start = (void *) work_base;
*work_area_size = ram_end - work_base;
*heap_start = BSP_BOOTCARD_HEAP_USES_WORK_AREA;
*heap_size = (uintptr_t) HeapSize;
/*
* The following may be helpful in debugging what goes wrong when
* you are allocating the Work Area in a new BSP.
*/
#ifdef BSP_GET_WORK_AREA_DEBUG
{
void *sp = __builtin_frame_address(0);
void *end = *work_area_start + *work_area_size;
printk(
"work_area_start = 0x%p\n"
"work_area_size = %d 0x%08x\n"
"end = 0x%p\n"
"heap_start = 0x%p\n"
"heap_size = %d\n"
"current stack pointer = 0x%p%s\n",
*work_area_start,
*work_area_size, /* decimal */
*work_area_size, /* hexadecimal */
end,
*heap_start,
*heap_size,
sp,
((sp >= *work_area_start && sp <= end) ? " OVERLAPS!" : "")
);
}
#endif
bsp_work_area_initialize_default( (void *) work_base, ram_end - work_base );
}

View File

@@ -9,14 +9,8 @@
#include <bsp/bootcard.h>
void bsp_libc_init(
void *heap_begin,
uintptr_t heap_size,
size_t sbrk_amount
)
void bsp_libc_init(void)
{
RTEMS_Malloc_Initialize( heap_begin, heap_size, sbrk_amount );
/*
* Init the RTEMS libio facility to provide UNIX-like system
* calls for use by newlib (ie: provide open, close, etc)

View File

@@ -7,12 +7,13 @@
*/
/*
* Copyright (c) 2008
* Embedded Brains GmbH
* Copyright (c) 2008-2012 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
* Obere Lagerstr. 30
* D-82178 Puchheim
* 82178 Puchheim
* Germany
* rtems@embedded-brains.de
* <rtems@embedded-brains.de>
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
@@ -25,6 +26,20 @@
* @brief Board support package dependent code.
*/
#ifndef LIBBSP_SHARED_BOOTCARD_H
#define LIBBSP_SHARED_BOOTCARD_H
#include <unistd.h>
#include <rtems/malloc.h>
#include <rtems/bspIo.h>
#include <bspopts.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/**
* @defgroup bsp_bootcard Bootcard
*
@@ -35,19 +50,6 @@
* @{
*/
#ifndef LIBBSP_SHARED_BOOTCARD_H
#define LIBBSP_SHARED_BOOTCARD_H
#include <stddef.h>
#include <stdint.h>
#include <sys/types.h>
#include <bspopts.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/**
* @brief Global pointer to the command line of boot_card().
*/
@@ -65,45 +67,6 @@ void bsp_cleanup(uint32_t status);
void bsp_reset(void);
/**
* @brief Should be used as the heap begin address in bsp_get_work_area() if
* the heap area is contained in the work area.
*/
#define BSP_BOOTCARD_HEAP_USES_WORK_AREA NULL
/**
* @brief Should be used to request the default heap size in bsp_get_work_area().
*
* In case that the heap area is contained in the work area this heap size
* value indicates that the area outside the work space should be used as heap
* space.
*/
#define BSP_BOOTCARD_HEAP_SIZE_DEFAULT 0
void bsp_get_work_area(
void **work_area_begin,
uintptr_t *work_area_size,
void **heap_begin,
uintptr_t *heap_size
);
/**
* @brief Gives the BSP a chance to reduce the work area size with sbrk() adding more later.
*
* bsp_sbrk_init() may reduce the work area size passed in. The routine
* returns the 'sbrk_amount' to be used when extending the heap.
* Note that the return value may be zero.
*
*/
#ifdef CONFIGURE_MALLOC_BSP_SUPPORTS_SBRK
uintptr_t bsp_sbrk_init(
void *work_area_begin,
uintptr_t *work_area_size_p
);
#endif
/**
* @brief Standard system initialization procedure.
*
@@ -120,11 +83,10 @@ uintptr_t bsp_sbrk_init(
* - disable interrupts, interrupts will be enabled during the first context
* switch
* - bsp_start() - more advanced initialization
* - obtain information on BSP memory via bsp_get_work_area() and allocate
* RTEMS Workspace
* - bsp_work_area_initialize() - initialize the RTEMS Workspace and the C
* Program Heap
* - rtems_initialize_data_structures()
* - allocate memory for C Program Heap
* - initialize C Library and C Program Heap
* - initialize C Library
* - bsp_pretasking_hook()
* - if defined( RTEMS_DEBUG )
* - rtems_debug_enable( RTEMS_DEBUG_ALL_MASK )
@@ -147,9 +109,94 @@ uintptr_t bsp_sbrk_init(
*/
uint32_t boot_card(const char *cmdline);
/** @} */
#ifdef CONFIGURE_MALLOC_BSP_SUPPORTS_SBRK
/**
* @brief Gives the BSP a chance to reduce the work area size with sbrk()
* adding more later.
*
* bsp_sbrk_init() may reduce the work area size passed in. The routine
* returns the 'sbrk_amount' to be used when extending the heap. Note that
* the return value may be zero.
*
* In case the @a area size is altered, then the remaining size of the
* @a area must be greater than or equal to @a min_size.
*/
ptrdiff_t bsp_sbrk_init(Heap_Area *area, uintptr_t min_size);
#endif
void bsp_libc_init(void *heap_begin, uintptr_t heap_size, size_t sbrk_amount);
static inline void bsp_work_area_initialize_default(
void *area_begin,
uintptr_t area_size
)
{
Heap_Area area = {
.begin = area_begin,
.size = area_size
};
#if BSP_DIRTY_MEMORY == 1
memset(area.begin, 0xCF, area.size);
#endif
#ifdef CONFIGURE_MALLOC_BSP_SUPPORTS_SBRK
{
uintptr_t overhead = _Heap_Area_overhead(CPU_HEAP_ALIGNMENT);
uintptr_t work_space_size = rtems_configuration_get_work_space_size();
ptrdiff_t sbrk_amount = bsp_sbrk_init(
&area,
work_space_size
+ overhead
+ (rtems_configuration_get_unified_work_area() ? 0 : overhead)
);
rtems_heap_set_sbrk_amount(sbrk_amount);
}
#endif
/*
* The following may be helpful in debugging what goes wrong when
* you are allocating the Work Area in a new BSP.
*/
#ifdef BSP_GET_WORK_AREA_DEBUG
{
void *sp = __builtin_frame_address(0);
void *end = (char *) area.begin + area.size;
printk(
"work_area_start = 0x%p\n"
"work_area_size = %lu 0x%08lx\n"
"end = 0x%p\n"
"current stack pointer = 0x%p%s\n",
area.begin,
(unsigned long) area.size, /* decimal */
(unsigned long) area.size, /* hexadecimal */
end,
sp,
(uintptr_t) sp >= (uintptr_t) area.begin
&& (uintptr_t) sp <= (uintptr_t) end ?
" OVERLAPS!" : ""
);
}
#endif
_Workspace_Handler_initialization(&area, 1, NULL);
#ifdef BSP_GET_WORK_AREA_DEBUG
printk(
"heap_start = 0x%p\n"
"heap_size = %lu\n",
area.begin,
(unsigned long) area.size
);
#endif
RTEMS_Malloc_Initialize(&area, 1, NULL);
}
void bsp_work_area_initialize(void);
void bsp_libc_init(void);
/** @} */
#ifdef __cplusplus
}

View File

@@ -81,8 +81,8 @@ void bsp_spurious_initialize( void );
/* Allocate 8-byte aligned non-freeable pre-malloc() memory. The function
* can be called at any time. The work-area will shrink when called before
* bsp_get_work_area(). malloc() is called to get memory when this function
* is called after bsp_get_work_area().
* bsp_work_area_initialize(). malloc() is called to get memory when this function
* is called after bsp_work_area_initialize().
*/
void *bsp_early_malloc(int size);

View File

@@ -101,8 +101,8 @@ void bsp_spurious_initialize( void );
/* Allocate 8-byte aligned non-freeable pre-malloc() memory. The function
* can be called at any time. The work-area will shrink when called before
* bsp_get_work_area(). malloc() is called to get memory when this function
* is called after bsp_get_work_area().
* bsp_work_area_initialize(). malloc() is called to get memory when this function
* is called after bsp_work_area_initialize().
*/
void *bsp_early_malloc(int size);

View File

@@ -114,8 +114,8 @@ void bsp_spurious_initialize( void );
/* Allocate 8-byte aligned non-freeable pre-malloc() memory. The function
* can be called at any time. The work-area will shrink when called before
* bsp_get_work_area(). malloc() is called to get memory when this function
* is called after bsp_get_work_area().
* bsp_work_area_initialize(). malloc() is called to get memory when this function
* is called after bsp_work_area_initialize().
*/
void *bsp_early_malloc(int size);

View File

@@ -28,24 +28,17 @@ unsigned int early_mem = (unsigned int)&end;
* is to be allocated between the RTEMS Workspace and the C Program
* Heap.
*/
void bsp_get_work_area(
void **work_area_start,
uintptr_t *work_area_size,
void **heap_start,
uintptr_t *heap_size
)
void bsp_work_area_initialize(void)
{
/* must be identical to STACK_SIZE in start.S */
#define STACK_SIZE (16 * 1024)
/* Early dynamic memory allocator is placed just above _end */
*work_area_start = (void *)early_mem;
*work_area_size = (void *)rdb_start - (void *)early_mem - STACK_SIZE;
void *work_area_start = (void *)early_mem;
uintptr_t work_area_size =
(uintptr_t)rdb_start - (uintptr_t)early_mem - STACK_SIZE;
early_mem = ~0; /* Signal bsp_early_malloc not to be used anymore */
*heap_start = BSP_BOOTCARD_HEAP_USES_WORK_AREA;
*heap_size = BSP_BOOTCARD_HEAP_SIZE_DEFAULT;
/*
* The following may be helpful in debugging what goes wrong when
* you are allocating the Work Area in a new BSP.
@@ -58,19 +51,17 @@ void bsp_get_work_area(
"work_area_start = 0x%p\n"
"work_area_size = %d 0x%08x\n"
"end = 0x%p\n"
"heap_start = 0x%p\n"
"heap_size = %d\n"
"current stack pointer = 0x%p%s\n",
*work_area_start,
*work_area_size, /* decimal */
*work_area_size, /* hexadecimal */
work_area_start,
work_area_size, /* decimal */
work_area_size, /* hexadecimal */
end,
*heap_start,
*heap_size,
sp,
((sp >= *work_area_start && sp <= end) ? " OVERLAPS!" : "")
);
printk( "rdb_start = 0x%08x\n", rdb_start );
}
#endif
bsp_work_area_initialize_default(work_area_start, work_area_size);
}

View File

@@ -25,8 +25,8 @@ extern unsigned int early_mem;
/* Allocate 8-byte aligned non-freeable pre-malloc() memory. The function
* can be called at any time. The work-area will shrink when called before
* bsp_get_work_area(). malloc() is called to get memory when this function
* is called after bsp_get_work_area().
* bsp_work_area_initialize(). malloc() is called to get memory when this function
* is called after bsp_work_area_initialize().
*/
void *bsp_early_malloc(int size)
{

View File

@@ -42,7 +42,7 @@ startup_SOURCES = ../../shared/bspclean.c ../../shared/bsplibc.c \
../../shared/bsppredriverhook.c ../../shared/bsppretaskinghook.c \
../../shared/bsppost.c \
../../shared/bootcard.c ../../shared/sbrk.c \
../shared/startup/bspgetworkarea.c \
../../shared/bspgetworkarea.c \
../shared/startup/bspstart.c \
../shared/startup/setvec.c \
../../shared/gnatinstallhandler.c \

View File

@@ -1,91 +0,0 @@
/*
* This routine is an implementation of the bsp_get_work_area()
* that can be used by all BSPs following linkcmds conventions
* regarding heap, stack, and workspace allocation.
*
* COPYRIGHT (c) 1989-2008.
* 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.
*/
#include <bsp.h>
#include <bsp/bootcard.h>
#ifdef BSP_GET_WORK_AREA_DEBUG
#include <rtems/bspIo.h>
#endif
/*
* These are provided by the linkcmds for ALL of the BSPs which use this file.
*/
extern char WorkAreaBase[];
extern char HeapSize[];
extern char HeapBase[];
/*
* We may get the size information from U-Boot or the linker scripts.
*/
#ifdef HAS_UBOOT
extern bd_t bsp_uboot_board_info;
#else
extern char RamBase[];
extern char RamSize[];
#endif /* HAS_UBOOT */
/*
* This method returns the base address and size of the area which
* is to be allocated between the RTEMS Workspace and the C Program
* Heap.
*/
void bsp_get_work_area(
void **work_area_start,
uintptr_t *work_area_size,
void **heap_start,
uintptr_t *heap_size
)
{
uintptr_t ram_end;
#ifdef HAS_UBOOT
ram_end = (uintptr_t) bsp_uboot_board_info.bi_memstart +
bsp_uboot_board_info.bi_memsize;
#else
ram_end = (uintptr_t)RamBase + (uintptr_t)RamSize;
#endif
*work_area_start = WorkAreaBase;
*work_area_size = (uintptr_t) HeapSize;
*heap_start = (void*) HeapBase;
*heap_size = (uintptr_t) HeapSize;
/*
* The following may be helpful in debugging what goes wrong when
* you are allocating the Work Area in a new BSP.
*/
#ifdef BSP_GET_WORK_AREA_DEBUG
{
void *sp = __builtin_frame_address(0);
void *end = *work_area_start + *work_area_size;
printk(
"bsp_get_work_area\n\r"
"work_area_start = 0x%p\n\r"
"work_area_size = %d 0x%08x\n\r"
"end = 0x%p\n\r"
"heap_start = 0x%p\n\r"
"heap_size = %d\n\r"
"current stack pointer = 0x%p%s\n\r",
*work_area_start,
*work_area_size, /* decimal */
*work_area_size, /* hexadecimal */
end,
*heap_start,
*heap_size,
sp,
((sp >= *work_area_start && sp <= end) ? " OVERLAPS!" : "")
);
}
#endif
}

View File

@@ -88,7 +88,7 @@ startup_SOURCES = ../../shared/bspclean.c ../../shared/bsplibc.c \
../../shared/bspstart.c ../../shared/bsppretaskinghook.c \
../../shared/bsppost.c \
../../shared/bootcard.c ../../shared/sbrk.c \
../shared/startup/bspgetworkarea.c \
../../shared/bspgetworkarea.c \
../shared/startup/bsppredriverhook.c \
../shared/startup/setvec.c \
../../shared/gnatinstallhandler.c \

View File

@@ -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

View File

@@ -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);

View File

@@ -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;
extern rtems_malloc_sbrk_functions_t rtems_malloc_sbrk_helpers_table;
extern rtems_malloc_sbrk_functions_t *rtems_malloc_sbrk_helpers;
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 const rtems_heap_extend_handler rtems_malloc_extend_handler;
/*
* Malloc Plugin to Dirty Memory at Allocation Time

View File

@@ -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;

View File

@@ -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,33 +14,52 @@
*/
#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();
Heap_Control *heap = RTEMS_Malloc_Heap;
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;
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 ( space_available > 0 ) {
init_or_extend = extend;
}
}
if ( init_or_extend == _Heap_Initialize ) {
_Internal_error_Occurred(
INTERNAL_ERROR_CORE,
true,
INTERNAL_ERROR_NO_MEMORY_FOR_HEAP
);
}
}
/*
* If configured, initialize the statistics support
*/
@@ -48,59 +67,15 @@ void RTEMS_Malloc_Initialize(
(*rtems_malloc_statistics_helpers->initialize)();
}
/*
* 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 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.
*/
/*
* 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 ( separate_areas && rtems_configuration_get_do_zero_of_workspace() ) {
memset( heap_begin, 0, heap_size );
}
/*
* 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 ( 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 );
}
}
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

View File

@@ -22,11 +22,6 @@
#include <stdint.h>
#include <rtems/chain.h>
/*
* Basic management data
*/
extern Heap_Control *RTEMS_Malloc_Heap;
/*
* Malloc Statistics Structure
*/

View File

@@ -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
};

View File

@@ -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
*/

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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 */

View File

@@ -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() ? \

View File

@@ -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

View File

@@ -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>

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -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;
if ( rtems_configuration_get_do_zero_of_workspace() )
memset( starting_address, 0, size );
for (i = 0; i < area_count; ++i) {
Heap_Area *area = &areas [i];
memory_available = _Heap_Initialize(
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,
starting_address,
area->begin,
size,
CPU_HEAP_ALIGNMENT
page_size
);
if ( memory_available == 0 )
area->begin = (char *) area->begin + size;
area->size -= size;
if ( space_available < remaining ) {
remaining -= space_available;
} else {
remaining = 0;
}
init_or_extend = extend;
}
}
if ( remaining > 0 ) {
_Internal_error_Occurred(
INTERNAL_ERROR_CORE,
true,
INTERNAL_ERROR_TOO_LITTLE_WORKSPACE
);
}
}
/*

View File

@@ -147,34 +147,29 @@ The @code{boot_card()} routine performs the following functions:
@item It disables processor interrupts.
@item It sets the global program name and command line argument variables
@item It sets the command line argument variables
for later use by the application.
@item If the macro is BSP_BOOTCARD_HANDLES_RAM_ALLOCATION is defined, it
will invoke the BSP specific @code{bsp_get_work_area} function to obtain
information on the amount and location of BSP RAM that is available to
be allocated to the C Program Heap and RTEMS Workspace. If the amount
of memory available for the RTEMS Workspace is less than that required
by the application (e.g. @code{rtems_configuration_get_work_space_size()},
then a message is printed using @code{printk}, @code{bsp_cleanup} is
invoked, and -1 is return to the assembly language start code. BSPs which
use this memory allocation functionality in @code{bootcard.c}
must invoke the RTEMS specific autoconf macro
@code{RTEMS_BSP_BOOTCARD_HANDLES_RAM_ALLOCATION} in the BSP's
@code{configure.ac} file.
@item It invokes the BSP specific routine @code{bsp_start()} which is
written in C and thus able to perform more advanced initialization.
Often MMU and bus initialization occurs here.
@item It invokes the BSP specific routine @code{bsp_work_area_initialize()}
which is supposed to initialize the RTEMS Workspace and the C Program Heap.
Usually the default implementation in
@code{c/src/lib/libbsp/shared/bspgetworkarea.c} should be sufficient. Custom
implementations can use @code{bsp_work_area_initialize_default()} or
@code{bsp_work_area_initialize_with_table()} available as inline functions from
@code{#include <bsp/bootcard.h>}.
@item It invokes the RTEMS directive
@code{rtems_initialize_data_structures()} to initialize the RTEMS
executive to a state where objects can be created but tasking is not
enabled.
@item If the macro is BSP_BOOTCARD_HANDLES_RAM_ALLOCATION is defined,
it will calculate the memory available for the C Program Heap and invoke
the initialization routine for the C Library with this information.
@item It invokes the BSP specific routine @code{bsp_libc_init()} to initialize
the C Library. Usually the default implementation in
@code{c/src/lib/libbsp/shared/bsplibc.c} should be sufficient.
@item It invokes the BSP specific routine @code{bsp_pretasking_hook}. On
most BSPs which utilize the framework, this routine does nothing.
@@ -188,9 +183,7 @@ thread in a multiprocessor configuration and execute API specific
extensions.
@item It invokes the BSP specific routine @code{bsp_predriver_hook}. For
most BSPs, the implementation of this routine does nothing. However,
on some BSPs, required subsystems which utilize the C Library
(e.g. @code{malloc} in particular) may be initialized at this point.
most BSPs, the implementation of this routine does nothing.
@item It invokes the RTEMS directive
@code{rtems_initialize_device_drivers()} to initialize the statically
@@ -255,28 +248,13 @@ routine.
@subsection RTEMS Pretasking Callback
The method @code{bsp_pretasking_hook()} is the BSP specific routine
invoked once RTEMS API initialization is complete but before interrupts
and tasking are enabled. No tasks -- not even the IDLE task -- have
been created when this hook is invoked. The pretasking hook is optional
The method @code{bsp_pretasking_hook()} is the BSP specific routine invoked
once RTEMS API initialization is complete but before interrupts and tasking are
enabled. The idle thread exists at this time. The pretasking hook is optional
and the user may use the shared version.
The @code{bsp_pretasking_hook()} routine is the appropriate place to
initialize any support components which depend on the RTEMS APIs.
Older BSPs that do not take full advantage of @code{boot_card()}
may initialize the RTEMS C Library in their implementation of
@code{bsp_pretasking_hook()}. This initialization includes the
application heap used by the @code{malloc} family of routines as well
as the reentrancy support for the C Library.
The routine @code{bsp_libc_init} routine invoked from the
either @code{boot_card()} or (less preferable) the BSP specific
@code{bsp_pretasking_hook()} routine is passed the starting address,
length, and growth amount passed to @code{sbrk}. This "sbrk amount"
is only used if the heap runs out of memory. In this case, the RTEMS
malloc implementation will invoked @code{sbrk} to obtain more memory.
See @ref{Miscellaneous Support Files sbrk() Implementation} for more
details.
The @code{bsp_pretasking_hook()} routine is the appropriate place to initialize
any BSP specific support components which depend on the RTEMS APIs.
@subsection RTEMS Predriver Callback

View File

@@ -30,14 +30,20 @@
#include <rtems/confdefs.h>
/* end of configuration */
#ifndef CONFIGURE_MALLOC_BSP_SUPPORTS_SBRK
void *rtems_heap_null_extend(
Heap_Control *heap,
size_t alloc_size
)
{
return rtems_heap_extend_via_sbrk( heap, alloc_size );
}
#endif
char Malloc_Heap[ 128 ] CPU_STRUCTURE_ALIGNMENT;
int sbrk_count;
Heap_Control Heap_Holder;
Heap_Control TempHeap;
/* Heap variables we need to peek and poke at */
extern size_t RTEMS_Malloc_Sbrk_amount;
size_t offset;
void * sbrk(ptrdiff_t incr)
@@ -66,7 +72,8 @@ rtems_task Init(
rtems_task_argument argument
)
{
Heap_Control *TempHeap;
Heap_Control *real_heap;
Heap_Area area;
sbrk_count = 0;
offset = 0;
@@ -74,21 +81,26 @@ rtems_task Init(
puts( "\n\n*** TEST MALLOC 04 ***" );
/* Safe information on real heap */
TempHeap = malloc_get_heap_pointer();
Heap_Holder = *TempHeap;
rtems_malloc_sbrk_helpers = &rtems_malloc_sbrk_helpers_table;
real_heap = malloc_get_heap_pointer();
malloc_set_heap_pointer( &TempHeap );
rtems_heap_set_sbrk_amount( 64 );
puts( "Initialize heap with some memory" );
offset = 64;
sbrk_count = 0;
RTEMS_Malloc_Initialize( Malloc_Heap, 64, 64 );
area.begin = &Malloc_Heap [0];
area.size = 64;
RTEMS_Malloc_Initialize( &area, 1, NULL );
p1 = malloc(64);
p2 = malloc(64);
p3 = malloc(48);
p4 = malloc(48);
puts( "Initialize heap with some memory - return address out of heap" );
RTEMS_Malloc_Initialize( &Malloc_Heap[1], 64, 64 );
area.begin = &Malloc_Heap [1];
area.size = 64;
RTEMS_Malloc_Initialize( &area, 1, NULL );
offset = 64;
sbrk_count = -1;
p1 = malloc( 127 );
@@ -96,18 +108,21 @@ rtems_task Init(
rtems_test_assert( errno == ENOMEM );
RTEMS_Malloc_Initialize( Malloc_Heap, 64, 64 );
area.begin = &Malloc_Heap [0];
area.size = 64;
RTEMS_Malloc_Initialize( &area, 1, NULL );
puts( "Initialize heap with some unaligned memory" );
offset = 65;
sbrk_count = 0;
RTEMS_Malloc_Initialize( &Malloc_Heap[1], 64, 64 );
area.begin = &Malloc_Heap [1];
area.size = 64;
RTEMS_Malloc_Initialize( &area, 1, NULL );
p1 = malloc(64);
p2 = malloc(64);
p3 = malloc(48);
/* Restore information on real heap */
malloc_set_heap_pointer( TempHeap );
rtems_malloc_sbrk_helpers = NULL;
malloc_set_heap_pointer( real_heap );
puts( "*** END OF TEST MALLOC 04 ***" );

View File

@@ -87,13 +87,18 @@ char *Errors_Core[] = {
"INTERNAL_ERROR_BAD_ATTRIBUTES",
"INTERNAL_ERROR_IMPLEMENTATION_KEY_CREATE_INCONSISTENCY",
"INTERNAL_ERROR_IMPLEMENTATION_BLOCKING_OPERATION_CANCEL",
"INTERNAL_ERROR_MUTEX_OBTAIN_FROM_BAD_STATE"
"INTERNAL_ERROR_MUTEX_OBTAIN_FROM_BAD_STATE",
"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_NO_MEMORY_FOR_HEAP"
};
void Put_Error( uint32_t source, uint32_t error )
{
if ( source == INTERNAL_ERROR_CORE ) {
if ( error > INTERNAL_ERROR_MUTEX_OBTAIN_FROM_BAD_STATE )
if ( error > INTERNAL_ERROR_NO_MEMORY_FOR_HEAP )
printk("Unknown Internal Core Error (%d)", error);
else
printk( Errors_Core[ error ] );

View File

@@ -17,7 +17,7 @@ SUBDIRS = \
sperror01 sperror02 sperror03 \
spfatal01 spfatal02 spfatal03 spfatal04 spfatal05 spfatal06 spfatal07 \
spfatal08 spfatal09 spfatal10 spfatal11 spfatal12 spfatal13 spfatal14 \
spfatal15 spfatal16 spfatal17 spfatal18 spfatal19 spfatal20 spfatal21 \
spfatal15 spfatal16 spfatal17 spfatal18 spfatal19 spfatal20 \
spfatal22 spfatal23 spfatal24 spfatal25 \
spfifo01 spfifo02 spfifo03 spfifo04 spfifo05 \
spintrcritical01 spintrcritical02 spintrcritical03 spintrcritical04 \

View File

@@ -139,7 +139,6 @@ spfatal17/Makefile
spfatal18/Makefile
spfatal19/Makefile
spfatal20/Makefile
spfatal21/Makefile
spfatal22/Makefile
spfatal23/Makefile
spfatal24/Makefile

View File

@@ -38,6 +38,10 @@ rtems_initialization_tasks_table Initialization_tasks[] = {
void *New_stack_allocate_hook(size_t unused);
#define CONFIGURE_TASK_STACK_ALLOCATOR New_stack_allocate_hook
#define CONFIGURE_TASK_STACK_DEALLOCATOR NULL
void *New_stack_allocate_hook(size_t unused)
{
return NULL;
@@ -45,12 +49,5 @@ void *New_stack_allocate_hook(size_t unused)
void force_error()
{
if (Configuration.stack_free_hook != NULL)
Configuration.stack_allocate_hook = NULL;
else
Configuration.stack_allocate_hook = New_stack_allocate_hook;
rtems_initialize_data_structures();
/* we will not run this far */
}

View File

@@ -37,11 +37,15 @@ rtems_initialization_tasks_table Initialization_tasks[] = {
#define FATAL_ERROR_EXPECTED_ERROR \
INTERNAL_ERROR_INTERRUPT_STACK_TOO_SMALL
#if CPU_SIMPLE_VECTORED_INTERRUPTS == TRUE
#define CONFIGURE_MEMORY_OVERHEAD (sizeof(ISR_Handler_entry) * ISR_NUMBER_OF_VECTORS)
#endif
void force_error()
{
#if (CPU_ALLOCATE_INTERRUPT_STACK == TRUE)
Configuration.interrupt_stack_size = (STACK_MINIMUM_SIZE-1);
rtems_initialize_data_structures();
_ISR_Handler_initialization();
#else
printk(
"WARNING - Test not applicable on this target architecture.\n"

View File

@@ -9,6 +9,8 @@
* http://www.rtems.com/license/LICENSE.
*/
#include <rtems/score/wkspace.h>
/*
* Way too much stack space. Should generate a fatal error
* on the init task create.
@@ -39,10 +41,16 @@ char Workspace[ 256 ] CPU_STRUCTURE_ALIGNMENT;
void force_error()
{
rtems_configuration_set_work_space_start( Workspace );
rtems_configuration_set_work_space_size( sizeof(Workspace) );
Heap_Area area = {
.begin = Workspace,
.size = sizeof( Workspace )
};
rtems_configuration_set_work_space_size( 0 );
rtems_configuration_set_stack_space_size( 0 );
rtems_initialize_data_structures();;
_Workspace_Handler_initialization( &area, 1, NULL );
_Workspace_Allocate_or_fatal_error( 2 * sizeof( Workspace ) );
/* we will not run this far */
}

View File

@@ -14,15 +14,12 @@
#define FATAL_ERROR_TEST_NAME "9"
#define FATAL_ERROR_DESCRIPTION "Bad heap address to malloc"
#define FATAL_ERROR_EXPECTED_SOURCE INTERNAL_ERROR_RTEMS_API
#define FATAL_ERROR_EXPECTED_IS_INTERNAL FALSE
#define FATAL_ERROR_EXPECTED_ERROR RTEMS_NO_MEMORY
char Malloc_Heap[ 1 ] CPU_STRUCTURE_ALIGNMENT;
#define FATAL_ERROR_EXPECTED_SOURCE INTERNAL_ERROR_CORE
#define FATAL_ERROR_EXPECTED_IS_INTERNAL TRUE
#define FATAL_ERROR_EXPECTED_ERROR INTERNAL_ERROR_NO_MEMORY_FOR_HEAP
void force_error()
{
RTEMS_Malloc_Initialize( Malloc_Heap, sizeof(Malloc_Heap), 0 );
RTEMS_Malloc_Initialize( NULL, 0, NULL );
/* we will not run this far */
}

View File

@@ -17,9 +17,8 @@
void force_error()
{
rtems_configuration_set_work_space_size( sizeof(void *) );
rtems_configuration_set_stack_space_size( 0 );
rtems_initialize_data_structures();
Heap_Area area = { .begin = NULL, .size = 0 };
_Workspace_Handler_initialization( &area, 1, NULL );
/* we will not run this far */
}

View File

@@ -1,21 +0,0 @@
rtems_tests_PROGRAMS = spfatal21
spfatal21_SOURCES = ../spfatal_support/init.c \
../spfatal_support/system.h ../../support/src/test_support.c testcase.h
dist_rtems_tests_DATA = spfatal21.scn
dist_rtems_tests_DATA += spfatal21.doc
include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
include $(top_srcdir)/../automake/compile.am
include $(top_srcdir)/../automake/leaf.am
AM_CPPFLAGS += -I$(top_srcdir)/../support/include
LINK_OBJS = $(spfatal21_OBJECTS)
LINK_LIBS = $(spfatal21_LDLIBS)
spfatal21$(EXEEXT): $(spfatal21_OBJECTS) $(spfatal21_DEPENDENCIES)
@rm -f spfatal21$(EXEEXT)
$(make-exe)
include $(top_srcdir)/../automake/local.am

View File

@@ -1,19 +0,0 @@
# COPYRIGHT (c) 1989-2010.
# 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.
#
This file describes the directives and concepts tested by this test set.
test set name: spfatal21
directives:
malloc_sbrk_initialize
concepts:
+ exercise fatal error when sbrk fails to extend memory on the initial call.

View File

@@ -1,3 +0,0 @@
*** TEST FATAL FATAL 21 ***
Fatal error (sbrk during init fails) hit
*** END OF TEST FATAL 21 ***

View File

@@ -1,34 +0,0 @@
/*
* COPYRIGHT (c) 1989-2012.
* 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.
*/
#define FATAL_ERROR_TEST_NAME "FATAL 21"
#define FATAL_ERROR_DESCRIPTION "sbrk during init fails"
#define FATAL_ERROR_EXPECTED_SOURCE INTERNAL_ERROR_RTEMS_API
#define FATAL_ERROR_EXPECTED_IS_INTERNAL FALSE
#define FATAL_ERROR_EXPECTED_ERROR RTEMS_NO_MEMORY
#include <rtems/libcsupport.h>
#include <rtems/malloc.h>
#include <unistd.h>
/* Safe information on real heap */
extern rtems_malloc_sbrk_functions_t *rtems_malloc_sbrk_helpers;
extern rtems_malloc_sbrk_functions_t rtems_malloc_sbrk_helpers_table;
void * sbrk(ptrdiff_t incr)
{
return (void *) -1;
}
void force_error()
{
rtems_malloc_sbrk_helpers = &rtems_malloc_sbrk_helpers_table;
RTEMS_Malloc_Initialize( NULL, 0, 64 );
}

View File

@@ -88,13 +88,18 @@ char *Errors_Core[] = {
"INTERNAL_ERROR_BAD_ATTRIBUTES",
"INTERNAL_ERROR_IMPLEMENTATION_KEY_CREATE_INCONSISTENCY",
"INTERNAL_ERROR_IMPLEMENTATION_BLOCKING_OPERATION_CANCEL",
"INTERNAL_ERROR_MUTEX_OBTAIN_FROM_BAD_STATE"
"INTERNAL_ERROR_MUTEX_OBTAIN_FROM_BAD_STATE",
"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_NO_MEMORY_FOR_HEAP"
};
void Put_Error( uint32_t source, uint32_t error )
{
if ( source == INTERNAL_ERROR_CORE ) {
if ( error > INTERNAL_ERROR_MUTEX_OBTAIN_FROM_BAD_STATE )
if ( error > INTERNAL_ERROR_NO_MEMORY_FOR_HEAP )
printk("Unknown Internal Core Error (%d)", error);
else
printk( Errors_Core[ error ] );