forked from Imagelibrary/rtems
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:
@@ -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 );
|
||||
}
|
||||
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
@@ -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!" : "")
|
||||
);
|
||||
bsp_work_area_initialize_default((void *) work_area, work_size);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -61,14 +61,14 @@
|
||||
* 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;
|
||||
#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
|
||||
@@ -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 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;
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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 \
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
@@ -17,30 +17,49 @@
|
||||
#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;
|
||||
MSBUMP( space_available, _Protected_heap_Get_size( heap ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* 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) );
|
||||
#else
|
||||
void RTEMS_Malloc_Initialize(
|
||||
Heap_Area *areas,
|
||||
size_t area_count,
|
||||
Heap_Initialization_or_extend_handler extend
|
||||
)
|
||||
{
|
||||
/* FIXME: Dummy function */
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -22,11 +22,6 @@
|
||||
#include <stdint.h>
|
||||
#include <rtems/chain.h>
|
||||
|
||||
/*
|
||||
* Basic management data
|
||||
*/
|
||||
extern Heap_Control *RTEMS_Malloc_Heap;
|
||||
|
||||
/*
|
||||
* Malloc Statistics Structure
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
};
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
58
cpukit/libcsupport/src/rtems_heap_extend_via_sbrk.c
Normal file
58
cpukit/libcsupport/src/rtems_heap_extend_via_sbrk.c
Normal 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;
|
||||
}
|
||||
27
cpukit/libcsupport/src/rtems_heap_null_extend.c
Normal file
27
cpukit/libcsupport/src/rtems_heap_null_extend.c
Normal 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;
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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() ? \
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -28,29 +28,70 @@
|
||||
/*
|
||||
* _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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* _Workspace_Allocate
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 ***" );
|
||||
|
||||
|
||||
@@ -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 ] );
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -139,7 +139,6 @@ spfatal17/Makefile
|
||||
spfatal18/Makefile
|
||||
spfatal19/Makefile
|
||||
spfatal20/Makefile
|
||||
spfatal21/Makefile
|
||||
spfatal22/Makefile
|
||||
spfatal23/Makefile
|
||||
spfatal24/Makefile
|
||||
|
||||
@@ -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 */
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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 */
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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.
|
||||
@@ -1,3 +0,0 @@
|
||||
*** TEST FATAL FATAL 21 ***
|
||||
Fatal error (sbrk during init fails) hit
|
||||
*** END OF TEST FATAL 21 ***
|
||||
@@ -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 );
|
||||
}
|
||||
@@ -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 ] );
|
||||
|
||||
Reference in New Issue
Block a user