summaryrefslogtreecommitdiffstats
path: root/cpukit/libcsupport
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>2007-12-18 20:36:40 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>2007-12-18 20:36:40 +0000
commit543fe820616f31350366ab61052050303d17dd25 (patch)
treea2e4702be2cd9988ed341586c1c8c976b8ba3bb8 /cpukit/libcsupport
parent2007-12-18 Joel Sherrill <joel.sherrill@OARcorp.com> (diff)
downloadrtems-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')
-rw-r--r--cpukit/libcsupport/Makefile.am12
-rw-r--r--cpukit/libcsupport/include/rtems/malloc.h101
-rw-r--r--cpukit/libcsupport/preinstall.am20
-rw-r--r--cpukit/libcsupport/src/_calloc_r.c30
-rw-r--r--cpukit/libcsupport/src/_free_r.c29
-rw-r--r--cpukit/libcsupport/src/_malloc_r.c29
-rw-r--r--cpukit/libcsupport/src/_realloc_r.c30
-rw-r--r--cpukit/libcsupport/src/calloc.c41
-rw-r--r--cpukit/libcsupport/src/free.c69
-rw-r--r--cpukit/libcsupport/src/malloc.c529
-rw-r--r--cpukit/libcsupport/src/malloc_boundary.c194
-rw-r--r--cpukit/libcsupport/src/malloc_get_statistics.c31
-rw-r--r--cpukit/libcsupport/src/malloc_initialize.c128
-rw-r--r--cpukit/libcsupport/src/malloc_p.h55
-rw-r--r--cpukit/libcsupport/src/malloc_report_statistics.c26
-rw-r--r--cpukit/libcsupport/src/malloc_report_statistics_plugin.c60
-rw-r--r--cpukit/libcsupport/src/malloc_statistics_helpers.c79
-rw-r--r--cpukit/libcsupport/src/malloc_walk.c29
-rw-r--r--cpukit/libcsupport/src/mallocinfo.c2
-rw-r--r--cpukit/libcsupport/src/realloc.c103
20 files changed, 1086 insertions, 511 deletions
diff --git a/cpukit/libcsupport/Makefile.am b/cpukit/libcsupport/Makefile.am
index 36aee4bc98..0f54c5c3f9 100644
--- a/cpukit/libcsupport/Makefile.am
+++ b/cpukit/libcsupport/Makefile.am
@@ -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
diff --git a/cpukit/libcsupport/include/rtems/malloc.h b/cpukit/libcsupport/include/rtems/malloc.h
new file mode 100644
index 0000000000..abf31f8406
--- /dev/null
+++ b/cpukit/libcsupport/include/rtems/malloc.h
@@ -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
diff --git a/cpukit/libcsupport/preinstall.am b/cpukit/libcsupport/preinstall.am
index 520d071de9..cccde53bc0 100644
--- a/cpukit/libcsupport/preinstall.am
+++ b/cpukit/libcsupport/preinstall.am
@@ -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
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