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.
This commit is contained in:
Joel Sherrill
2007-12-18 20:36:40 +00:00
parent 02c54f5ee5
commit 543fe82061
25 changed files with 1178 additions and 524 deletions

View File

@@ -1,3 +1,28 @@
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.
2007-12-17 Joel Sherrill <joel.sherrill@oarcorp.com>
* libmisc/shell/main_alias.c, libmisc/shell/main_blksync.c,

View File

@@ -24,7 +24,7 @@ include_rtems_motorola_HEADERS = include/motorola/mc68230.h \
## rtems
include_rtems_HEADERS += include/rtems/assoc.h include/rtems/error.h \
include/rtems/libcsupport.h include/rtems/libio.h include/rtems/libio_.h \
include/rtems/termiostypes.h
include/rtems/malloc.h include/rtems/termiostypes.h
## zilog
@@ -78,8 +78,12 @@ ID_C_FILES = src/getegid.c src/geteuid.c src/getgid.c src/getgroups.c \
src/getlogin.c src/getpgrp.c src/getpid.c src/getppid.c src/getuid.c \
src/setpgid.c src/setsid.c
MALLOC_C_FILES = src/malloc.c src/mallocfreespace.c src/mallocinfo.c \
src/__brk.c src/__sbrk.c
MALLOC_C_FILES = src/malloc_initialize.c src/calloc.c src/malloc.c \
src/realloc.c src/_calloc_r.c src/free.c src/_free_r.c src/_malloc_r.c \
src/_realloc_r.c src/__brk.c src/__sbrk.c src/mallocfreespace.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/malloc_boundary.c
PASSWORD_GROUP_C_FILES = src/getpwent.c
@@ -104,7 +108,7 @@ libcsupport_a_SOURCES += $(LIBC_GLUE_C_FILES) $(PASSWORD_GROUP_C_FILES) \
$(TERMIOS_C_FILES) src/getpagesize.c
endif
EXTRA_DIST = src/TODO src/CASES src/README
EXTRA_DIST = src/TODO src/CASES src/README src/malloc_p.h
include $(srcdir)/preinstall.am
include $(top_srcdir)/automake/local.am

View File

@@ -0,0 +1,101 @@
/**
* @file rtems/malloc.h
*/
/*
* RTEMS Malloc Extensions
*
* COPYRIGHT (c) 1989-1997.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may in
* the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
*
* $ld:
*/
#ifndef _RTEMS_MALLOC_H
#define _RTEMS_MALLOC_H
#include <rtems.h>
#include <rtems/bspIo.h>
#include <stdint.h>
/*
* Malloc Statistics Structure
*/
typedef 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_statistics_t;
/*
* Malloc statistics plugin
*/
typedef struct {
void (*initialize)(void);
void (*at_malloc)(void *);
void (*at_free)(void *);
} rtems_malloc_statististics_functions_t;
extern rtems_malloc_statististics_functions_t
rtems_malloc_statistics_helpers_table;
extern rtems_malloc_statististics_functions_t *rtems_malloc_statistics_helpers;
/*
* Malloc boundary support plugin
*/
typedef struct {
void (*initialize)(void);
uint32_t (*overhead)(void);
void (*at_malloc)(void *, size_t);
void (*at_free)(void *);
void (*at_realloc)(void *, size_t);
} rtems_malloc_boundary_functions_t;
extern rtems_malloc_boundary_functions_t rtems_malloc_boundary_helpers_table;
extern rtems_malloc_boundary_functions_t *rtems_malloc_boundary_helpers;
/** @brief Print Malloc Statistic Usage Report
*
* This method fills in the called provided malloc statistics area.
*
* @return This method returns 0 if successful and -1 on error.
*/
int malloc_get_statistics(
rtems_malloc_statistics_t *stats
);
/** @brief Print Malloc Statistic Usage Report
*
* This method prints a malloc statistics report.
*
* @note It uses printk to print the report.
*/
void malloc_report_statistics(void);
/** @brief Print Malloc Statistic Usage Report
*
* This method prints a malloc statistics report.
*
* @param[in] context is the context to pass to the print handler
* @param[in] print is the print handler
*
* @note It uses the CALLER's routine to print the report.
*/
void malloc_report_statistics_with_plugin(
void *context,
rtems_printk_plugin_t print
);
#endif

View File

@@ -8,10 +8,24 @@ endif
PREINSTALL_DIRS =
DISTCLEANFILES = $(PREINSTALL_DIRS)
all-local: $(TMPINSTALL_FILES)
TMPINSTALL_FILES =
CLEANFILES = $(TMPINSTALL_FILES)
all-am: $(PREINSTALL_FILES)
PREINSTALL_FILES =
CLEANFILES = $(PREINSTALL_FILES)
CLEANFILES += $(PREINSTALL_FILES)
$(PROJECT_LIB)/$(dirstamp):
@$(MKDIR_P) $(PROJECT_LIB)
@: > $(PROJECT_LIB)/$(dirstamp)
PREINSTALL_DIRS += $(PROJECT_LIB)/$(dirstamp)
$(PROJECT_LIB)/libcsupport.a: libcsupport.a $(PROJECT_LIB)/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_LIB)/libcsupport.a
TMPINSTALL_FILES += $(PROJECT_LIB)/libcsupport.a
$(PROJECT_INCLUDE)/rtems/$(dirstamp):
@$(MKDIR_P) $(PROJECT_INCLUDE)/rtems
@@ -87,6 +101,10 @@ $(PROJECT_INCLUDE)/rtems/libio_.h: include/rtems/libio_.h $(PROJECT_INCLUDE)/rte
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/libio_.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/libio_.h
$(PROJECT_INCLUDE)/rtems/malloc.h: include/rtems/malloc.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/malloc.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/malloc.h
$(PROJECT_INCLUDE)/rtems/termiostypes.h: include/rtems/termiostypes.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/termiostypes.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/termiostypes.h

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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 "malloc_p.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);
}
#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 the user wants us to dirty the allocated memory, then do it.
*/
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 ( !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;
}
}
#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
#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 );
}
void _free_r(
struct _reent *ignored,
void *ptr
)
{
free( ptr );
return return_this;
}
#endif

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -31,8 +31,6 @@ int malloc_info(
Heap_Information_block *the_info
)
{
Heap_Information info;
if ( !the_info )
return -1;

View File

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

View File

@@ -77,12 +77,12 @@ libshell_a_SOURCES = shell/cat_file.c shell/cmds.c shell/internal.h \
shell/main_mdump.c shell/main_medit.c shell/main_mfill.c \
shell/main_mkdir.c shell/main_mount.c $(shell_mount_fs) \
shell/main_mount_msdos.c shell/main_mmove.c shell/main_msdosfmt.c \
shell/main_mwdump.c shell/main_pwd.c shell/main_rm.c shell/main_rmdir.c \
shell/main_stackuse.c shell/main_tty.c shell/main_umask.c \
shell/main_unmount.c shell/main_blksync.c shell/main_whoami.c \
shell/shell.c shell/shell_cmdset.c shell/shellconfig.c \
shell/shellconfig.h shell/shell.h shell/shell_makeargs.c \
shell/str2int.c shell/write_file.c
shell/main_mwdump.c shell/main_perioduse.c shell/main_pwd.c \
shell/main_rm.c shell/main_rmdir.c shell/main_stackuse.c \
shell/main_tty.c shell/main_umask.c shell/main_unmount.c \
shell/main_blksync.c shell/main_whoami.c shell/shell.c \
shell/shell_cmdset.c shell/shellconfig.c shell/shellconfig.h \
shell/shell.h shell/shell_makeargs.c shell/str2int.c shell/write_file.c
endif
EXTRA_DIST += shell/README

View File

@@ -18,6 +18,7 @@
#include <inttypes.h>
#include <rtems.h>
#include <rtems/malloc.h>
#include <rtems/shell.h>
#include "internal.h"
@@ -39,8 +40,8 @@ static void printit(
}
int rtems_shell_main_malloc_info(
int argc,
char * argv[]
int argc,
char *argv[]
)
{
if ( argc == 2 ) {
@@ -51,19 +52,21 @@ int rtems_shell_main_malloc_info(
printit( "free", &info.Free );
printit( "used", &info.Used );
return 0;
} else if ( !strcmp( argv[1], "dump" ) ) {
extern void malloc_dump();
malloc_dump();
} else if ( !strcmp( argv[1], "stats" ) ) {
malloc_report_statistics_with_plugin(
stdout,
(rtems_printk_plugin_t) fprintf
);
return 0;
}
}
fprintf( stderr, "subcommands info or dump\n" );
fprintf( stderr, "subcommands info or stats\n" );
return -1;
}
rtems_shell_cmd_t rtems_shell_MALLOC_INFO_Command = {
"malloc", /* name */
"[info|dump]", /* usage */
"[info|stats]", /* usage */
"mem", /* topic */
rtems_shell_main_malloc_info, /* command */
NULL, /* alias */

View File

@@ -0,0 +1,45 @@
/*
* perioduse Command 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$
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <rtems.h>
#include <rtems/shell.h>
#include "internal.h"
int rtems_shell_main_perioduse(int argc,char *argv[])
{
if ( argc >= 1 && !strcmp( argv[1], "-r" ) ) {
printf( "Resetting Period Usage information\n" );
rtems_rate_monotonic_reset_all_statistics();
} else {
rtems_rate_monotonic_report_statistics_with_plugin(
stdout,
(rtems_printk_plugin_t)fprintf
);
}
return 0;
}
rtems_shell_cmd_t rtems_shell_PERIODUSE_Command = {
"perioduse", /* name */
"[-r] print or reset per period usage", /* usage */
"rtems", /* topic */
rtems_shell_main_perioduse, /* command */
NULL, /* alias */
NULL /* next */
};

View File

@@ -51,6 +51,7 @@ extern rtems_shell_cmd_t rtems_shell_BLKSYNC_Command;
extern rtems_shell_cmd_t rtems_shell_CPUUSE_Command;
extern rtems_shell_cmd_t rtems_shell_STACKUSE_Command;
extern rtems_shell_cmd_t rtems_shell_PERIODUSE_Command;
extern rtems_shell_cmd_t rtems_shell_MALLOC_INFO_Command;
extern rtems_shell_cmd_t *rtems_shell_Initial_commands[];
@@ -275,6 +276,11 @@ extern rtems_shell_filesystems_t *rtems_shell_Mount_filesystems[];
defined(CONFIGURE_SHELL_COMMAND_STACKUSE)
&rtems_shell_STACKUSE_Command,
#endif
#if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \
!defined(CONFIGURE_SHELL_NO_COMMAND_PERIODUSE)) || \
defined(CONFIGURE_SHELL_COMMAND_PERIODUSE)
&rtems_shell_PERIODUSE_Command,
#endif
/*
* Malloc family commands