diff options
author | Joel Sherrill <joel.sherrill@OARcorp.com> | 2007-12-18 20:36:40 +0000 |
---|---|---|
committer | Joel Sherrill <joel.sherrill@OARcorp.com> | 2007-12-18 20:36:40 +0000 |
commit | 543fe820616f31350366ab61052050303d17dd25 (patch) | |
tree | a2e4702be2cd9988ed341586c1c8c976b8ba3bb8 /cpukit/libcsupport/src | |
parent | 2007-12-18 Joel Sherrill <joel.sherrill@OARcorp.com> (diff) | |
download | rtems-543fe820616f31350366ab61052050303d17dd25.tar.bz2 |
2007-12-18 Joel Sherrill <joel.sherrill@oarcorp.com>
* libcsupport/Makefile.am, libcsupport/preinstall.am,
libcsupport/src/malloc.c, libcsupport/src/mallocinfo.c,
libmisc/Makefile.am, libmisc/shell/main_mallocinfo.c,
libmisc/shell/shellconfig.h: Split malloc.c into multiple files with
one function per file. Also split out statistics into a separate file
which can be plugged in dynamically. Right now, it is always in. I
suspect that splitting the file removed more code than leaving
statistics in. I tinkered with malloc information command in the
shell. I resurrected the malloc arena code as malloc boundary. This
code is now compiled all the time even though it does not appear to
work.
* libcsupport/include/rtems/malloc.h, libcsupport/src/_calloc_r.c,
libcsupport/src/_free_r.c, libcsupport/src/_malloc_r.c,
libcsupport/src/_realloc_r.c, libcsupport/src/calloc.c,
libcsupport/src/free.c, libcsupport/src/malloc_boundary.c,
libcsupport/src/malloc_get_statistics.c,
libcsupport/src/malloc_initialize.c, libcsupport/src/malloc_p.h,
libcsupport/src/malloc_report_statistics.c,
libcsupport/src/malloc_report_statistics_plugin.c,
libcsupport/src/malloc_statistics_helpers.c,
libcsupport/src/malloc_walk.c, libcsupport/src/realloc.c,
libmisc/shell/main_perioduse.c: New files.
Diffstat (limited to 'cpukit/libcsupport/src')
-rw-r--r-- | cpukit/libcsupport/src/_calloc_r.c | 30 | ||||
-rw-r--r-- | cpukit/libcsupport/src/_free_r.c | 29 | ||||
-rw-r--r-- | cpukit/libcsupport/src/_malloc_r.c | 29 | ||||
-rw-r--r-- | cpukit/libcsupport/src/_realloc_r.c | 30 | ||||
-rw-r--r-- | cpukit/libcsupport/src/calloc.c | 41 | ||||
-rw-r--r-- | cpukit/libcsupport/src/free.c | 69 | ||||
-rw-r--r-- | cpukit/libcsupport/src/malloc.c | 529 | ||||
-rw-r--r-- | cpukit/libcsupport/src/malloc_boundary.c | 194 | ||||
-rw-r--r-- | cpukit/libcsupport/src/malloc_get_statistics.c | 31 | ||||
-rw-r--r-- | cpukit/libcsupport/src/malloc_initialize.c | 128 | ||||
-rw-r--r-- | cpukit/libcsupport/src/malloc_p.h | 55 | ||||
-rw-r--r-- | cpukit/libcsupport/src/malloc_report_statistics.c | 26 | ||||
-rw-r--r-- | cpukit/libcsupport/src/malloc_report_statistics_plugin.c | 60 | ||||
-rw-r--r-- | cpukit/libcsupport/src/malloc_statistics_helpers.c | 79 | ||||
-rw-r--r-- | cpukit/libcsupport/src/malloc_walk.c | 29 | ||||
-rw-r--r-- | cpukit/libcsupport/src/mallocinfo.c | 2 | ||||
-rw-r--r-- | cpukit/libcsupport/src/realloc.c | 103 |
17 files changed, 958 insertions, 506 deletions
diff --git a/cpukit/libcsupport/src/_calloc_r.c b/cpukit/libcsupport/src/_calloc_r.c new file mode 100644 index 0000000000..98753f347f --- /dev/null +++ b/cpukit/libcsupport/src/_calloc_r.c @@ -0,0 +1,30 @@ +/* + * _calloc_r Implementation + * + * 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. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef RTEMS_NEWLIB +#include <sys/reent.h> +#include <stdlib.h> + +void *_calloc_r( + struct _reent *ignored, + size_t elements, + size_t size +) +{ + return calloc( elements, size ); +} +#endif diff --git a/cpukit/libcsupport/src/_free_r.c b/cpukit/libcsupport/src/_free_r.c new file mode 100644 index 0000000000..8cc4a5f811 --- /dev/null +++ b/cpukit/libcsupport/src/_free_r.c @@ -0,0 +1,29 @@ +/* + * _free_r Implementation + * + * 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. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef RTEMS_NEWLIB +#include <sys/reent.h> +#include <stdlib.h> + +void _free_r( + struct _reent *ignored, + void *ptr +) +{ + free( ptr ); +} +#endif diff --git a/cpukit/libcsupport/src/_malloc_r.c b/cpukit/libcsupport/src/_malloc_r.c new file mode 100644 index 0000000000..7b0f4eb93c --- /dev/null +++ b/cpukit/libcsupport/src/_malloc_r.c @@ -0,0 +1,29 @@ +/* + * _malloc_r Implementation + * + * 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. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef RTEMS_NEWLIB +#include <sys/reent.h> +#include <stdlib.h> + +void *_malloc_r( + struct _reent *ignored, + size_t size +) +{ + return malloc( size ); +} +#endif diff --git a/cpukit/libcsupport/src/_realloc_r.c b/cpukit/libcsupport/src/_realloc_r.c new file mode 100644 index 0000000000..16dce667f2 --- /dev/null +++ b/cpukit/libcsupport/src/_realloc_r.c @@ -0,0 +1,30 @@ +/* + * _realloc_r Implementation + * + * 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. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef RTEMS_NEWLIB +#include <sys/reent.h> +#include <stdlib.h> + +void *_realloc_r( + struct _reent *ignored, + void *ptr, + size_t size +) +{ + return realloc( ptr, size ); +} +#endif diff --git a/cpukit/libcsupport/src/calloc.c b/cpukit/libcsupport/src/calloc.c new file mode 100644 index 0000000000..2a43736d71 --- /dev/null +++ b/cpukit/libcsupport/src/calloc.c @@ -0,0 +1,41 @@ +/* + * calloc() + * + * 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. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef RTEMS_NEWLIB +#include "malloc_p.h" +#include <stdlib.h> + +void *calloc( + size_t nelem, + size_t elsize +) +{ + register char *cptr; + int length; + + MSBUMP(calloc_calls, 1); + + length = nelem * elsize; + cptr = malloc( length ); + if ( cptr ) + memset( cptr, '\0', length ); + + MSBUMP(malloc_calls, -1); /* subtract off the malloc */ + + return cptr; +} +#endif diff --git a/cpukit/libcsupport/src/free.c b/cpukit/libcsupport/src/free.c new file mode 100644 index 0000000000..160e560bba --- /dev/null +++ b/cpukit/libcsupport/src/free.c @@ -0,0 +1,69 @@ +/* + * calloc() + * + * 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. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef RTEMS_NEWLIB +#include "malloc_p.h" +#include <stdlib.h> + +void free( + void *ptr +) +{ + MSBUMP(free_calls, 1); + + if ( !ptr ) + return; + + #if defined(RTEMS_HEAP_DEBUG) + _Protected_heap_Walk( &RTEMS_Malloc_Heap, 0, FALSE ); + #endif + + /* + * Do not attempt to free memory if in a critical section or ISR. + */ + + if (_System_state_Is_up(_System_state_Get())) { + if ((_Thread_Dispatch_disable_level > 0) || (_ISR_Nest_level > 0)) { + Chain_Append(&RTEMS_Malloc_GC_list, (Chain_Node *)ptr); + return; + } + } + + #if defined(RTEMS_MALLOC_BOUNDARY_HELPERS) + /* + * If configured, check the boundary area + */ + if ( rtems_malloc_boundary_helpers ) + (*rtems_malloc_boundary_helpers->at_free)(ptr); + #endif + + /* + * If configured, update the statistics + */ + if ( rtems_malloc_statistics_helpers ) + (*rtems_malloc_statistics_helpers->at_free)(ptr); + + if ( !_Protected_heap_Free( &RTEMS_Malloc_Heap, ptr ) ) { + printk( "Program heap: free of bad pointer %p -- range %p - %p \n", + ptr, + RTEMS_Malloc_Heap.start, + RTEMS_Malloc_Heap.end + ); + } + +} +#endif diff --git a/cpukit/libcsupport/src/malloc.c b/cpukit/libcsupport/src/malloc.c index 6a8f584a98..d1b3bb3504 100644 --- a/cpukit/libcsupport/src/malloc.c +++ b/cpukit/libcsupport/src/malloc.c @@ -2,7 +2,7 @@ * RTEMS Malloc Family Implementation * * - * COPYRIGHT (c) 1989-1999. + * COPYRIGHT (c) 1989-2007. * On-Line Applications Research Corporation (OAR). * * The license and distribution terms for this file may be @@ -16,201 +16,12 @@ #include "config.h" #endif -#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__ -#include <rtems.h> -#include <rtems/libcsupport.h> -#include <rtems/score/protectedheap.h> #ifdef RTEMS_NEWLIB -#include <sys/reent.h> -#endif - -#include <stdio.h> #include <stdlib.h> -#include <sys/types.h> #include <errno.h> -#include <string.h> - -#include <unistd.h> /* sbrk(2) */ -#include <inttypes.h> - -#include <rtems/chain.h> - -#ifndef HAVE_UINTMAX_T -/* Fall back to unsigned long if uintmax_t is not available */ -#define unsigned long uintmax_t - -#ifndef PRIuMAX -#define PRIuMAX "lu" -#endif -#endif - -#ifdef MALLOC_ARENA_CHECK -#define SENTINELSIZE 12 -#define SENTINEL "\xD1\xAC\xB2\xF1" "BITE ME" -#define CALLCHAINSIZE 5 -struct mallocNode { - struct mallocNode *back; - struct mallocNode *forw; - int callChain[CALLCHAINSIZE]; - size_t size; - void *memory; -}; -static struct mallocNode mallocNodeHead = { &mallocNodeHead, &mallocNodeHead }; -void reportMallocError(const char *msg, struct mallocNode *mp) -{ - unsigned char *sp = (unsigned char *)mp->memory + mp->size; - int i, ind = 0; - static char cbuf[500]; - ind += sprintf(cbuf+ind, "Malloc Error: %s\n", msg); - if ((mp->forw->back != mp) || (mp->back->forw != mp)) - ind += sprintf(cbuf+ind, - "mp:0x%x mp->forw:0x%x mp->forw->back:0x%x " - "mp->back:0x%x mp->back->forw:0x%x\n", - mp, mp->forw, mp->forw->back, mp->back, mp->back->forw); - if (mp->memory != (mp + 1)) - ind += sprintf(cbuf+ind, "mp+1:0x%x ", mp + 1); - ind += sprintf(cbuf+ind, "mp->memory:0x%x mp->size:%d\n", mp->memory, mp->size); - if (memcmp((char *)mp->memory + mp->size, SENTINEL, SENTINELSIZE) != 0) { - ind += sprintf(cbuf+ind, "mp->sentinel: "); - for (i = 0 ; i < SENTINELSIZE ; i++) - ind += sprintf(cbuf+ind, " 0x%x", sp[i]); - ind += sprintf(cbuf+ind, "\n"); - } - ind += sprintf(cbuf+ind, "Call chain:"); - for (i = 0 ; i < CALLCHAINSIZE ; i++) { - if (mp->callChain[i] == 0) - break; - ind += sprintf(cbuf+ind, " 0x%x", mp->callChain[i]); - } - printk("\n\n%s\n\n", cbuf); -} -#endif - -Heap_Control RTEMS_Malloc_Heap; -Chain_Control RTEMS_Malloc_GC_list; - -/* rtems_id RTEMS_Malloc_Heap; */ -size_t RTEMS_Malloc_Sbrk_amount; - -#ifdef RTEMS_DEBUG -#define MALLOC_STATS -#define MALLOC_DIRTY -/*#define MALLOC_ARENA_CHECK -void checkMallocArena(void); */ -#endif - -#ifdef MALLOC_STATS -#define MSBUMP(f,n) rtems_malloc_stats.f += (n) - -struct { - uint32_t space_available; /* current size of malloc area */ - uint32_t malloc_calls; /* # calls to malloc */ - uint32_t free_calls; - uint32_t realloc_calls; - uint32_t calloc_calls; - uint32_t max_depth; /* most ever malloc'd at 1 time */ - uintmax_t lifetime_allocated; - uintmax_t lifetime_freed; -} rtems_malloc_stats; - -#else /* No rtems_malloc_stats */ -#define MSBUMP(f,n) -#endif - -void RTEMS_Malloc_Initialize( - void *start, - size_t length, - size_t sbrk_amount -) -{ - uint32_t status; - void *starting_address; - uintptr_t old_address; - uintptr_t uaddress; - - /* - * Initialize the garbage collection list to start with nothing on it. - */ - Chain_Initialize_empty(&RTEMS_Malloc_GC_list); - - /* - * 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. - */ - - starting_address = start; - RTEMS_Malloc_Sbrk_amount = sbrk_amount; - - 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; - } - - /* - * 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 ( rtems_configuration_get_do_zero_of_workspace() ) - memset( starting_address, 0, length ); - - /* - * 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. - */ - - status = _Protected_heap_Initialize( - &RTEMS_Malloc_Heap, - starting_address, - length, - CPU_HEAP_ALIGNMENT - ); - if ( !status ) - rtems_fatal_error_occurred( status ); - - #if defined(RTEMS_HEAP_DEBUG) - if ( _Protected_heap_Walk( &RTEMS_Malloc_Heap, 0, FALSE ) ) { - printk( "Malloc heap not initialized correctly\n" ); - rtems_print_buffer( start, 32 ); - printk( "\n" ); - rtems_print_buffer( (start + length) - 48, 48 ); - rtems_fatal_error_occurred( RTEMS_NO_MEMORY ); - } - #endif -#ifdef MALLOC_STATS - /* zero all the stats */ - (void) memset( &rtems_malloc_stats, 0, sizeof(rtems_malloc_stats) ); -#endif - MSBUMP(space_available, length); -} +#include "malloc_p.h" -#ifdef RTEMS_NEWLIB void *malloc( size_t size ) @@ -248,15 +59,21 @@ void *malloc( while ((to_be_freed = Chain_Get(&RTEMS_Malloc_GC_list)) != NULL) free(to_be_freed); + #if defined(RTEMS_MALLOC_BOUNDARY_HELPERS) + /* + * If the support for a boundary area at the end of the heap + * block allocated is turned on, then adjust the size. + */ + if (rtems_malloc_boundary_helpers) + size += (*rtems_malloc_boundary_helpers->overhead)(); + #endif + /* * Try to give a segment in the current heap if there is not * enough space then try to grow the heap. * If this fails then return a NULL pointer. */ -#ifdef MALLOC_ARENA_CHECK - size += sizeof(struct mallocNode) + SENTINELSIZE; -#endif return_this = _Protected_heap_Allocate( &RTEMS_Malloc_Heap, size ); if ( !return_this ) { @@ -293,324 +110,28 @@ void *malloc( } } -#ifdef MALLOC_STATS - if (return_this) - { - size_t actual_size = 0; - uint32_t current_depth; - void *ptr = return_this; - _Protected_heap_Get_block_size(&RTEMS_Malloc_Heap, ptr, &actual_size); - MSBUMP(lifetime_allocated, actual_size); - current_depth = rtems_malloc_stats.lifetime_allocated - - rtems_malloc_stats.lifetime_freed; - if (current_depth > rtems_malloc_stats.max_depth) - rtems_malloc_stats.max_depth = current_depth; - } -#endif - -#ifdef MALLOC_DIRTY - (void) memset(return_this, 0xCF, size); -#endif - -#ifdef MALLOC_ARENA_CHECK - { - struct mallocNode *mp = (struct mallocNode *)return_this; - int key, *fp, *nfp, i; - rtems_interrupt_disable(key); - mp->memory = mp + 1; - return_this = mp->memory; - mp->size = size - (sizeof(struct mallocNode) + SENTINELSIZE); - fp = (int *)&size - 2; - for (i = 0 ; i < CALLCHAINSIZE ; i++) { - mp->callChain[i] = fp[1]; - nfp = (int *)(fp[0]); - if((nfp <= fp) || (nfp > (int *)(1 << 24))) - break; - fp = nfp; - } - while (i < CALLCHAINSIZE) - mp->callChain[i++] = 0; - memcpy((char *)mp->memory + mp->size, SENTINEL, SENTINELSIZE); - mp->forw = mallocNodeHead.forw; - mp->back = &mallocNodeHead; - mallocNodeHead.forw->back = mp; - mallocNodeHead.forw = mp; - rtems_interrupt_enable(key); - } -#endif - return return_this; -} - -void *calloc( - size_t nelem, - size_t elsize -) -{ - register char *cptr; - int length; - - MSBUMP(calloc_calls, 1); - - length = nelem * elsize; - cptr = malloc( length ); - if ( cptr ) - memset( cptr, '\0', length ); - - MSBUMP(malloc_calls, -1); /* subtract off the malloc */ - - return cptr; -} - -void *realloc( - void *ptr, - size_t size -) -{ - size_t old_size; - char *new_area; - - MSBUMP(realloc_calls, 1); - - /* - * Do not attempt to allocate memory if in a critical section or ISR. - */ - - if (_System_state_Is_up(_System_state_Get())) { - if (_Thread_Dispatch_disable_level > 0) - return (void *) 0; - - if (_ISR_Nest_level > 0) - return (void *) 0; - } - - /* - * Continue with realloc(). - */ - if ( !ptr ) - return malloc( size ); - - if ( !size ) { - free( ptr ); - return (void *) 0; - } - -#ifdef MALLOC_ARENA_CHECK - { - void *np; - np = malloc(size); - if (!np) return np; - memcpy(np,ptr,size); - free(ptr); - return np; - } -#endif - if ( _Protected_heap_Resize_block( &RTEMS_Malloc_Heap, ptr, size ) ) { - return ptr; - } - - new_area = malloc( size ); - - MSBUMP(malloc_calls, -1); /* subtract off the malloc */ - /* - * There used to be a free on this error case but it is wrong to - * free the memory per OpenGroup Single UNIX Specification V2 - * and the C Standard. + * If the user wants us to dirty the allocated memory, then do it. */ - - if ( !new_area ) { - return (void *) 0; - } - - if ( !_Protected_heap_Get_block_size(&RTEMS_Malloc_Heap, ptr, &old_size) ) { - errno = EINVAL; - return (void *) 0; - } - - memcpy( new_area, ptr, (size < old_size) ? size : old_size ); - free( ptr ); - - return new_area; - -} - -void free( - void *ptr -) -{ - MSBUMP(free_calls, 1); - - if ( !ptr ) - return; - - #if defined(RTEMS_HEAP_DEBUG) - _Protected_heap_Walk( &RTEMS_Malloc_Heap, 0, FALSE ); + #ifdef MALLOC_DIRTY + (void) memset(return_this, 0xCF, size); #endif /* - * Do not attempt to free memory if in a critical section or ISR. + * If configured, update the statistics */ + if ( rtems_malloc_statistics_helpers ) + (*rtems_malloc_statistics_helpers->at_malloc)(return_this); - if (_System_state_Is_up(_System_state_Get())) { - if ((_Thread_Dispatch_disable_level > 0) || (_ISR_Nest_level > 0)) { - Chain_Append(&RTEMS_Malloc_GC_list, (Chain_Node *)ptr); - return; - } - } - -#ifdef MALLOC_ARENA_CHECK - { - struct mallocNode *mp = (struct mallocNode *)ptr - 1; - struct mallocNode *mp1; - int key; - rtems_interrupt_disable(key); - if ((mp->memory != (mp + 1)) - || (memcmp((char *)mp->memory + mp->size, SENTINEL, SENTINELSIZE) != 0)) - reportMallocError("Freeing with inconsistent pointer/sentinel", mp); - mp1 = mallocNodeHead.forw; - while (mp1 != &mallocNodeHead) { - if (mp1 == mp) - break; - mp1 = mp1->forw; - } - if (mp1 != mp) - reportMallocError("Freeing, but not on allocated list", mp); - mp->forw->back = mp->back; - mp->back->forw = mp->forw; - mp->back = mp->forw = NULL; - ptr = mp; - rtems_interrupt_enable(key); - } -#endif -#ifdef MALLOC_STATS - { - size_t size; - if (_Protected_heap_Get_block_size(&RTEMS_Malloc_Heap, ptr, &size) ) { - MSBUMP(lifetime_freed, size); - } - } -#endif - - if ( !_Protected_heap_Free( &RTEMS_Malloc_Heap, ptr ) ) { - printk( "Program heap: free of bad pointer %p -- range %p - %p \n", - ptr, - RTEMS_Malloc_Heap.start, - RTEMS_Malloc_Heap.end - ); - } -} - -#ifdef MALLOC_ARENA_CHECK -void checkMallocArena(void) -{ - struct mallocNode *mp = mallocNodeHead.forw; - int key; - rtems_interrupt_disable(key); - while (mp != &mallocNodeHead) { - if ((mp->forw->back != mp) - || (mp->back->forw != mp)) - reportMallocError("Pointers mangled", mp); - if((mp->memory != (mp + 1)) - || (memcmp((char *)mp->memory + mp->size, SENTINEL, SENTINELSIZE) != 0)) - reportMallocError("Inconsistent pointer/sentinel", mp); - mp = mp->forw; - } - rtems_interrupt_enable(key); -} -#endif - -/* end if RTEMS_NEWLIB */ -#endif - -#ifdef MALLOC_STATS -/* - * Dump the malloc statistics - * May be called via atexit() (installable by our bsp) or - * at any time by user - */ - -void malloc_dump(void) -{ - uint32_t allocated = rtems_malloc_stats.lifetime_allocated - - rtems_malloc_stats.lifetime_freed; - - printf("Malloc stats\n"); - printf(" avail:%"PRIu32"k allocated:%"PRIu32"k (%"PRId32"%%) " - "max:%"PRIu32"k (%"PRIu32"%%)" - " lifetime:%"PRIuMAX"k freed:%"PRIuMAX"k\n", - rtems_malloc_stats.space_available / 1024, - allocated / 1024, - /* avoid float! */ - (allocated * 100) / rtems_malloc_stats.space_available, - rtems_malloc_stats.max_depth / 1024, - (rtems_malloc_stats.max_depth * 100) / rtems_malloc_stats.space_available, - rtems_malloc_stats.lifetime_allocated / 1024, - rtems_malloc_stats.lifetime_freed / 1024 - ); - printf(" Call counts: malloc:%"PRIu32" free:%"PRIu32" realloc:%"PRIu32" calloc:%"PRIu32"\n", - rtems_malloc_stats.malloc_calls, - rtems_malloc_stats.free_calls, - rtems_malloc_stats.realloc_calls, - rtems_malloc_stats.calloc_calls); -} - - -void malloc_walk(size_t source, size_t printf_enabled) -{ - _Protected_heap_Walk( &RTEMS_Malloc_Heap, source, printf_enabled ); -} - -#else - -void malloc_dump(void) -{ - return; -} - -void malloc_walk(size_t source, size_t printf_enabled) -{ - return; -} - -#endif - -/* - * "Reentrant" versions of the above routines implemented above. - */ - -#ifdef RTEMS_NEWLIB -void *_malloc_r( - struct _reent *ignored, - size_t size -) -{ - return malloc( size ); -} - -void *_calloc_r( - struct _reent *ignored, - size_t nelem, - size_t elsize -) -{ - return calloc( nelem, elsize ); -} - -void *_realloc_r( - struct _reent *ignored, - void *ptr, - size_t size -) -{ - return realloc( ptr, size ); -} + #if defined(RTEMS_MALLOC_BOUNDARY_HELPERS) + /* + * If configured, set the boundary area + */ + if (rtems_malloc_boundary_helpers) + (*rtems_malloc_boundary_helpers->at_malloc)(return_this, size); + #endif -void _free_r( - struct _reent *ignored, - void *ptr -) -{ - free( ptr ); + return return_this; } #endif diff --git a/cpukit/libcsupport/src/malloc_boundary.c b/cpukit/libcsupport/src/malloc_boundary.c new file mode 100644 index 0000000000..706e224294 --- /dev/null +++ b/cpukit/libcsupport/src/malloc_boundary.c @@ -0,0 +1,194 @@ +/* + * RTEMS Malloc Block Boundary Integrity Checker + * + * WARNING!!! WARNING!!! WARNING!!! WARNING!!! + * WARNING!!! WARNING!!! WARNING!!! WARNING!!! + * + * This file is built but never called. It is a first + * step in reintegrating this functionality. + * This code was disabled for a LONG time in malloc.c. + * This is a restructured and slightly modified version + * that should be able to be configured as a plugin BUT + * it has not been tested recently. When it has been + * tested again, please remove this comment. + * + * JOEL: I have not analyzed this code in terms of + * the heap changes post 4.6. It is possible + * that that way the boundary area is carved + * off breaks the alignment. + * + * WARNING!!! WARNING!!! WARNING!!! WARNING!!! + * WARNING!!! WARNING!!! WARNING!!! WARNING!!! + * + * 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. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include "malloc_p.h" + +#include <stdio.h> + +#ifdef RTEMS_NEWLIB + +#define SENTINELSIZE 12 +#define SENTINEL "\xD1\xAC\xB2\xF1" "BITE ME" +#define CALLCHAINSIZE 5 + +struct mallocNode { + struct mallocNode *back; + struct mallocNode *forw; + int callChain[CALLCHAINSIZE]; + size_t size; + void *memory; +}; + +struct mallocNode mallocNodeHead; + +void rtems_malloc_boundary_initialize(void) +{ + mallocNodeHead.back = &mallocNodeHead; + mallocNodeHead.forw = &mallocNodeHead; +} + +uint32_t rtems_malloc_boundary_overhead(void) +{ + return sizeof(struct mallocNode) + SENTINELSIZE; +} + +void rtems_malloc_boundary_at_malloc( + void *pointer, + size_t size +) +{ + void *return_this; + struct mallocNode *mp = (struct mallocNode *)pointer; + int *fp, *nfp, i; + + _RTEMS_Lock_allocator(); + mp->memory = mp + 1; + return_this = mp->memory; + mp->size = size - (sizeof(struct mallocNode) + SENTINELSIZE); + fp = (int *)&size - 2; + for (i = 0 ; i < CALLCHAINSIZE ; i++) { + mp->callChain[i] = fp[1]; + nfp = (int *)(fp[0]); + if((nfp <= fp) || (nfp > (int *)(1 << 24))) + break; + fp = nfp; + } + while (i < CALLCHAINSIZE) + mp->callChain[i++] = 0; + memcpy((char *)mp->memory + mp->size, SENTINEL, SENTINELSIZE); + mp->forw = mallocNodeHead.forw; + mp->back = &mallocNodeHead; + mallocNodeHead.forw->back = mp; + mallocNodeHead.forw = mp; + _RTEMS_Unlock_allocator(); +} + +void reportMallocError(const char *msg, struct mallocNode *mp); + +void rtems_malloc_boundary_at_free( + void *pointer +) +{ + struct mallocNode *mp = (struct mallocNode *)pointer - 1; + struct mallocNode *mp1; + + _RTEMS_Lock_allocator(); + if ((mp->memory != (mp + 1)) || + (memcmp((char *)mp->memory + mp->size, SENTINEL, SENTINELSIZE) != 0)) + reportMallocError("Freeing with inconsistent pointer/sentinel", mp); + mp1 = mallocNodeHead.forw; + while (mp1 != &mallocNodeHead) { + if (mp1 == mp) + break; + mp1 = mp1->forw; + } + if (mp1 != mp) + reportMallocError("Freeing, but not on allocated list", mp); + mp->forw->back = mp->back; + mp->back->forw = mp->forw; + mp->back = mp->forw = NULL; + pointer = mp; + _RTEMS_Unlock_allocator(); +} + +void rtems_malloc_boundary_at_realloc( + void *pointer, + size_t size +) +{ + /* this needs to be implemented */ +} + +/* + * Malloc boundary support plugin + */ +rtems_malloc_boundary_functions_t rtems_malloc_boundary_functions_table = { + rtems_malloc_boundary_initialize, + rtems_malloc_boundary_overhead, + rtems_malloc_boundary_at_malloc, + rtems_malloc_boundary_at_free, + rtems_malloc_boundary_at_realloc, +}; + +rtems_malloc_boundary_functions_t *rtems_malloc_boundary_helpers = NULL; +/* &rtems_malloc_boundary_functions_table; */ + +void reportMallocError(const char *msg, struct mallocNode *mp) +{ + unsigned char *sp = (unsigned char *)mp->memory + mp->size; + int i, ind = 0; + static char cbuf[500]; + ind += sprintf(cbuf+ind, "Malloc Error: %s\n", msg); + if ((mp->forw->back != mp) || (mp->back->forw != mp)) + ind += sprintf(cbuf+ind, + "mp:%p mp->forw:%p mp->forw->back:%p " + "mp->back:%p mp->back->forw:%p\n", + mp, mp->forw, mp->forw->back, mp->back, mp->back->forw); + if (mp->memory != (mp + 1)) + ind += sprintf(cbuf+ind, "mp+1:%p ", mp + 1); + ind += sprintf(cbuf+ind, "mp->memory:%p mp->size:%d\n", mp->memory, mp->size); + if (memcmp((char *)mp->memory + mp->size, SENTINEL, SENTINELSIZE) != 0) { + ind += sprintf(cbuf+ind, "mp->sentinel: "); + for (i = 0 ; i < SENTINELSIZE ; i++) + ind += sprintf(cbuf+ind, " 0x%x", sp[i]); + ind += sprintf(cbuf+ind, "\n"); + } + ind += sprintf(cbuf+ind, "Call chain:"); + for (i = 0 ; i < CALLCHAINSIZE ; i++) { + if (mp->callChain[i] == 0) + break; + ind += sprintf(cbuf+ind, " 0x%x", mp->callChain[i]); + } + printk("\n\n%s\n\n", cbuf); +} + +void checkMallocArena(void) +{ + struct mallocNode *mp; + + _RTEMS_Lock_allocator(); + for ( mp = mallocNodeHead.forw; mp != &mallocNodeHead ; mp = mp->forw ) { + if ((mp->forw->back != mp) || (mp->back->forw != mp)) + reportMallocError("Pointers mangled", mp); + if ((mp->memory != (mp + 1)) || + (memcmp((char *)mp->memory + mp->size, SENTINEL, SENTINELSIZE) != 0)) + reportMallocError("Inconsistent pointer/sentinel", mp); + } + _RTEMS_Unlock_allocator(); +} + +#endif + diff --git a/cpukit/libcsupport/src/malloc_get_statistics.c b/cpukit/libcsupport/src/malloc_get_statistics.c new file mode 100644 index 0000000000..57cc8c600f --- /dev/null +++ b/cpukit/libcsupport/src/malloc_get_statistics.c @@ -0,0 +1,31 @@ +/* + * malloc_get_statistics Implementation + * + * 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. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef RTEMS_NEWLIB +#include "malloc_p.h" + +int malloc_get_statistics( + rtems_malloc_statistics_t *stats +) +{ + if ( !stats ) + return -1; + *stats = rtems_malloc_statistics; + return 0; +} + +#endif diff --git a/cpukit/libcsupport/src/malloc_initialize.c b/cpukit/libcsupport/src/malloc_initialize.c new file mode 100644 index 0000000000..08fc351f7f --- /dev/null +++ b/cpukit/libcsupport/src/malloc_initialize.c @@ -0,0 +1,128 @@ +/* + * RTEMS Malloc Family Implementation --Initialization + * + * + * 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. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems.h> +#include <rtems/malloc.h> +#include "malloc_p.h" + +Heap_Control RTEMS_Malloc_Heap; +Chain_Control RTEMS_Malloc_GC_list; +size_t RTEMS_Malloc_Sbrk_amount; +rtems_malloc_statistics_t rtems_malloc_statistics; + +void RTEMS_Malloc_Initialize( + void *start, + size_t length, + size_t sbrk_amount +) +{ + uint32_t status; + void *starting_address; + uintptr_t old_address; + uintptr_t uaddress; + + #if defined(RTEMS_MALLOC_BOUNDARY_HELPERS) + /* + * If configured, initialize the boundary support + */ + if (rtems_malloc_boundary_helpers) + (*rtems_malloc_boundary_helpers->initialize)(); + #endif + + /* + * If configured, initialize the statistics support + */ + if ( rtems_malloc_statistics_helpers ) + (*rtems_malloc_statistics_helpers->initialize)(); + + /* + * Initialize the garbage collection list to start with nothing on it. + */ + Chain_Initialize_empty(&RTEMS_Malloc_GC_list); + + /* + * 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. + */ + + starting_address = start; + RTEMS_Malloc_Sbrk_amount = sbrk_amount; + + 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; + } + + /* + * 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 ( rtems_configuration_get_do_zero_of_workspace() ) + memset( starting_address, 0, length ); + + /* + * 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. + */ + + status = _Protected_heap_Initialize( + &RTEMS_Malloc_Heap, + starting_address, + length, + CPU_HEAP_ALIGNMENT + ); + if ( !status ) + rtems_fatal_error_occurred( status ); + + #if defined(RTEMS_HEAP_DEBUG) + if ( _Protected_heap_Walk( &RTEMS_Malloc_Heap, 0, FALSE ) ) { + printk( "Malloc heap not initialized correctly\n" ); + rtems_print_buffer( start, 32 ); + printk( "\n" ); + rtems_print_buffer( (start + length) - 48, 48 ); + rtems_fatal_error_occurred( RTEMS_NO_MEMORY ); + } + #endif + + MSBUMP(space_available, length); +} diff --git a/cpukit/libcsupport/src/malloc_p.h b/cpukit/libcsupport/src/malloc_p.h new file mode 100644 index 0000000000..95f73d72b1 --- /dev/null +++ b/cpukit/libcsupport/src/malloc_p.h @@ -0,0 +1,55 @@ +/* + * RTEMS Malloc Family Internal Header + * + * 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. + * + * $Id$ + */ + +#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__ +#include <rtems.h> +#include <rtems/libcsupport.h> +#include <rtems/score/protectedheap.h> +#include <rtems/malloc.h> + +#ifdef RTEMS_NEWLIB +#include <sys/reent.h> +#endif + +#include <stdint.h> +#include <inttypes.h> +#include <rtems/chain.h> + +#ifndef HAVE_UINTMAX_T + /* Fall back to unsigned long if uintmax_t is not available */ + #define unsigned long uintmax_t + + #ifndef PRIuMAX + #define PRIuMAX "lu" + #endif +#endif + +/* + * Basic management data + */ +extern Heap_Control RTEMS_Malloc_Heap; +extern Chain_Control RTEMS_Malloc_GC_list; +extern size_t RTEMS_Malloc_Sbrk_amount; + +/* + * Malloc Statistics Structure + */ +extern rtems_malloc_statistics_t rtems_malloc_statistics; + +#define MSBUMP(_f,_n) rtems_malloc_statistics._f += (_n) + +/* + * Dirty memory plugin + */ +#define MALLOC_DIRTY + diff --git a/cpukit/libcsupport/src/malloc_report_statistics.c b/cpukit/libcsupport/src/malloc_report_statistics.c new file mode 100644 index 0000000000..24f5505429 --- /dev/null +++ b/cpukit/libcsupport/src/malloc_report_statistics.c @@ -0,0 +1,26 @@ +/* + * malloc_report_statistics Implementation + * + * 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. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef RTEMS_NEWLIB +#include "malloc_p.h" + +void malloc_report_statistics(void) +{ + malloc_report_statistics_with_plugin( NULL, printk_plugin ); +} + +#endif diff --git a/cpukit/libcsupport/src/malloc_report_statistics_plugin.c b/cpukit/libcsupport/src/malloc_report_statistics_plugin.c new file mode 100644 index 0000000000..2f00477d44 --- /dev/null +++ b/cpukit/libcsupport/src/malloc_report_statistics_plugin.c @@ -0,0 +1,60 @@ +/* + * malloc_report_statistics with plugin Implementation + * + * 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. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef RTEMS_NEWLIB +#include "malloc_p.h" +#include "inttypes.h" + +void malloc_report_statistics_with_plugin( + void *context, + rtems_printk_plugin_t print +) +{ + rtems_malloc_statistics_t *s; + uint32_t allocated; + + s = &rtems_malloc_statistics; + + allocated = s->lifetime_allocated - s->lifetime_freed; + + (*print)( + context, + "Malloc statistics\n" + " avail:%"PRIu32"k allocated:%"PRIu32"k (%"PRId32"%%) " + "max:%"PRIu32"k (%"PRIu32"%%)" + " lifetime:%"PRIuMAX"k freed:%"PRIuMAX"k\n", + s->space_available / 1024, + allocated / 1024, + /* avoid float! */ + (allocated * 100) / s->space_available, + s->max_depth / 1024, + (s->max_depth * 100) / s->space_available, + s->lifetime_allocated / 1024, + s->lifetime_freed / 1024 + ); + (*print)( + context, + " Call counts: malloc:%"PRIu32" free:%"PRIu32 + " realloc:%"PRIu32" calloc:%"PRIu32"\n", + s->malloc_calls, + s->free_calls, + s->realloc_calls, + s->calloc_calls + ); +} + +#endif diff --git a/cpukit/libcsupport/src/malloc_statistics_helpers.c b/cpukit/libcsupport/src/malloc_statistics_helpers.c new file mode 100644 index 0000000000..9e744a4c40 --- /dev/null +++ b/cpukit/libcsupport/src/malloc_statistics_helpers.c @@ -0,0 +1,79 @@ + +/* + * _calloc_r Implementation + * + * 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. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef RTEMS_NEWLIB +#include "malloc_p.h" + +#include <sys/reent.h> +#include <stdlib.h> + + +void rtems_malloc_statistics_initialize() +{ + /* + * Zero all the statistics + */ + (void) memset(&rtems_malloc_statistics, 0, sizeof(rtems_malloc_statistics)); +} + +void rtems_malloc_statistics_at_malloc( + void *pointer +) +{ + size_t actual_size = 0; + uint32_t current_depth; + rtems_malloc_statistics_t *s = &rtems_malloc_statistics; + + if ( !pointer ) + return; + + _Protected_heap_Get_block_size(&RTEMS_Malloc_Heap, pointer, &actual_size); + + MSBUMP(lifetime_allocated, actual_size); + + current_depth = s->lifetime_allocated - s->lifetime_freed; + if (current_depth > s->max_depth) + s->max_depth = current_depth; +} + +/* + * If the pointer is not in the heap, then we won't be able to get its + * size and thus we skip updating the statistics. + */ +void rtems_malloc_statistics_at_free( + void *pointer +) +{ + size_t size; + + if (_Protected_heap_Get_block_size(&RTEMS_Malloc_Heap, pointer, &size) ) { + MSBUMP(lifetime_freed, size); + } +} + +rtems_malloc_statististics_functions_t rtems_malloc_statistics_helpers_table = { + rtems_malloc_statistics_initialize, + rtems_malloc_statistics_at_malloc, + rtems_malloc_statistics_at_free, +}; + +rtems_malloc_statististics_functions_t *rtems_malloc_statistics_helpers = + &rtems_malloc_statistics_helpers_table; + +#endif + diff --git a/cpukit/libcsupport/src/malloc_walk.c b/cpukit/libcsupport/src/malloc_walk.c new file mode 100644 index 0000000000..a376282077 --- /dev/null +++ b/cpukit/libcsupport/src/malloc_walk.c @@ -0,0 +1,29 @@ +/* + * malloc_walk Implementation + * + * 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. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef RTEMS_NEWLIB +#include <sys/reent.h> +#include <stdlib.h> + +void malloc_walk(size_t source, size_t printf_enabled) +{ + #if defined(RTEMS_DEBUG) + _Protected_heap_Walk( &RTEMS_Malloc_Heap, source, printf_enabled ); + #endif +} + +#endif diff --git a/cpukit/libcsupport/src/mallocinfo.c b/cpukit/libcsupport/src/mallocinfo.c index 2868ff819e..d5ecd03db3 100644 --- a/cpukit/libcsupport/src/mallocinfo.c +++ b/cpukit/libcsupport/src/mallocinfo.c @@ -31,8 +31,6 @@ int malloc_info( Heap_Information_block *the_info ) { - Heap_Information info; - if ( !the_info ) return -1; diff --git a/cpukit/libcsupport/src/realloc.c b/cpukit/libcsupport/src/realloc.c new file mode 100644 index 0000000000..cba244cc37 --- /dev/null +++ b/cpukit/libcsupport/src/realloc.c @@ -0,0 +1,103 @@ +/* + * calloc() + * + * 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. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef RTEMS_NEWLIB +#include "malloc_p.h" +#include <stdlib.h> +#include <errno.h> + +void *realloc( + void *ptr, + size_t size +) +{ + size_t old_size; + char *new_area; + size_t resize; + + MSBUMP(realloc_calls, 1); + + /* + * Do not attempt to allocate memory if in a critical section or ISR. + */ + + if (_System_state_Is_up(_System_state_Get())) { + if (_Thread_Dispatch_disable_level > 0) + return (void *) 0; + + if (_ISR_Nest_level > 0) + return (void *) 0; + } + + /* + * Continue with realloc(). + */ + if ( !ptr ) + return malloc( size ); + + if ( !size ) { + free( ptr ); + return (void *) 0; + } + + /* + * If block boundary integrity checking is enabled, then + * we need to account for the boundary memory again. + */ + resize = size; + #if defined(RTEMS_MALLOC_BOUNDARY_HELPERS) + if (rtems_malloc_boundary_helpers) + resize += (*rtems_malloc_boundary_helpers->overhead)(); + #endif + + if ( _Protected_heap_Resize_block( &RTEMS_Malloc_Heap, ptr, resize ) ) { + #if defined(RTEMS_MALLOC_BOUNDARY_HELPERS) + /* + * Successful resize. Update the boundary on the same block. + */ + if (rtems_malloc_boundary_helpers) + (*rtems_malloc_boundary_helpers->at_realloc)(ptr, resize); + #endif + return ptr; + } + + /* + * There used to be a free on this error case but it is wrong to + * free the memory per OpenGroup Single UNIX Specification V2 + * and the C Standard. + */ + + new_area = malloc( size ); + + MSBUMP(malloc_calls, -1); /* subtract off the malloc */ + + if ( !new_area ) { + return (void *) 0; + } + + if ( !_Protected_heap_Get_block_size(&RTEMS_Malloc_Heap, ptr, &old_size) ) { + errno = EINVAL; + return (void *) 0; + } + + memcpy( new_area, ptr, (size < old_size) ? size : old_size ); + free( ptr ); + + return new_area; + +} +#endif |