summaryrefslogtreecommitdiffstats
path: root/cpukit
diff options
context:
space:
mode:
authorEric Norum <WENorum@lbl.gov>2006-05-25 17:36:31 +0000
committerEric Norum <WENorum@lbl.gov>2006-05-25 17:36:31 +0000
commitbe31de713feda36d1da3771df5decaa96088713a (patch)
treed0e0a94c3e92658edad482effc4b086674267069 /cpukit
parent2006-05-16 Ralf Corsépius <ralf.corsepius@rtems.org> (diff)
downloadrtems-be31de713feda36d1da3771df5decaa96088713a.tar.bz2
Provide customisable mbuf allocation.
Patch from Steven Johnson <sjohnson@sakuraindustries.com>
Diffstat (limited to 'cpukit')
-rw-r--r--cpukit/ChangeLog9
-rw-r--r--cpukit/libcsupport/src/malloc.c123
-rw-r--r--cpukit/libnetworking/Makefile.am2
-rw-r--r--cpukit/libnetworking/rtems/rtems_bsdnet.h16
-rw-r--r--cpukit/libnetworking/rtems/rtems_glue.c6
-rw-r--r--cpukit/libnetworking/rtems/rtems_malloc_mbuf.c33
6 files changed, 185 insertions, 4 deletions
diff --git a/cpukit/ChangeLog b/cpukit/ChangeLog
index a4f24efa12..619e2dd952 100644
--- a/cpukit/ChangeLog
+++ b/cpukit/ChangeLog
@@ -1,3 +1,12 @@
+2006-05-25 Eric Norum <norume@aps.anl.gov>
+
+ * libnetworking/Makefile.am,
+ libnetworking/Makefile.in,
+ libnetworking/rtems/rtems_bsdnet.h,
+ libnetworking/rtems/rtems_glue.c,
+ libnetworking/rtems/rtems_malloc_mbuf.c: Provide customisable mbuf
+ allocation. Patch from Steven Johnson <sjohnson@sakuraindustries.com>
+
2006-05-16 Ralf Corsépius <ralf.corsepius@rtems.org>
* aclocal/rtems-ampolish.m4: New.
diff --git a/cpukit/libcsupport/src/malloc.c b/cpukit/libcsupport/src/malloc.c
index 91acf92c44..8f961cf8f3 100644
--- a/cpukit/libcsupport/src/malloc.c
+++ b/cpukit/libcsupport/src/malloc.c
@@ -35,6 +35,46 @@
#include <rtems/chain.h>
+#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
+
Chain_Control RTEMS_Malloc_GC_list;
rtems_id RTEMS_Malloc_Heap;
@@ -190,6 +230,9 @@ void *malloc(
* If this fails then return a NULL pointer.
*/
+#ifdef MALLOC_ARENA_CHECK
+ size += sizeof(struct mallocNode) + SENTINELSIZE;
+#endif
status = rtems_region_get_segment(
RTEMS_Malloc_Heap,
size,
@@ -261,6 +304,32 @@ void *malloc(
(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;
}
@@ -318,6 +387,16 @@ void *realloc(
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
status =
rtems_region_resize_segment( RTEMS_Malloc_Heap, ptr, size, &old_size );
@@ -378,6 +457,30 @@ void free(
}
}
+#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;
@@ -394,6 +497,26 @@ void free(
assert( 0 );
}
}
+
+#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
diff --git a/cpukit/libnetworking/Makefile.am b/cpukit/libnetworking/Makefile.am
index a4b72bd8ba..d475f0de6f 100644
--- a/cpukit/libnetworking/Makefile.am
+++ b/cpukit/libnetworking/Makefile.am
@@ -118,7 +118,7 @@ include_rtems_HEADERS = rtems/rtems_bsdnet.h rtems/rtems_bsdnet_internal.h \
include_rtems_HEADERS += rtems/rtems_mii_ioctl.h
libnetworking_a_SOURCES += rtems/sghostname.c rtems/issetugid.c \
- rtems/rtems_glue.c rtems/rtems_syscall.c \
+ rtems/rtems_glue.c rtems/rtems_malloc_mbuf.c rtems/rtems_syscall.c \
rtems/rtems_bootp.c rtems/rtems_dhcp.c \
rtems/rtems_showmbuf.c rtems/rtems_showroute.c rtems/rtems_showifstat.c \
rtems/rtems_showipstat.c rtems/rtems_showicmpstat.c \
diff --git a/cpukit/libnetworking/rtems/rtems_bsdnet.h b/cpukit/libnetworking/rtems/rtems_bsdnet.h
index 7c7c2c8df4..3112779078 100644
--- a/cpukit/libnetworking/rtems/rtems_bsdnet.h
+++ b/cpukit/libnetworking/rtems/rtems_bsdnet.h
@@ -260,4 +260,20 @@ int rtems_bsdnet_synchronize_ntp (int interval, rtems_task_priority priority);
*/
void rtems_bsdnet_malloc_starvation(void);
+/*
+ * mbuf malloc interface to enable custom allocation of mbuf's
+ *
+ * May be declared in user code. If not, then the default is to
+ * malloc.
+ */
+void* rtems_bsdnet_malloc_mbuf(size_t size, int type);
+
+/*
+ * Possible values of the type parameter to rtems_bsdnet_malloc_mbuf to assist
+ * in allocation of the structure.
+ */
+#define MBUF_MALLOC_NMBCLUSTERS (0)
+#define MBUF_MALLOC_MCLREFCNT (1)
+#define MBUF_MALLOC_MBUF (2)
+
#endif /* _RTEMS_BSDNET_H */
diff --git a/cpukit/libnetworking/rtems/rtems_glue.c b/cpukit/libnetworking/rtems/rtems_glue.c
index dc9fa4bd68..657a2f862e 100644
--- a/cpukit/libnetworking/rtems/rtems_glue.c
+++ b/cpukit/libnetworking/rtems/rtems_glue.c
@@ -149,7 +149,7 @@ bsd_init (void)
/*
* Set up mbuf cluster data strutures
*/
- p = malloc ((nmbclusters*MCLBYTES)+MCLBYTES-1);
+ p = rtems_bsdnet_malloc_mbuf ((nmbclusters*MCLBYTES)+MCLBYTES-1, MBUF_MALLOC_NMBCLUSTERS);
if (p == NULL) {
printf ("Can't get network cluster memory.\n");
return -1;
@@ -163,7 +163,7 @@ bsd_init (void)
mbstat.m_clfree++;
}
mbstat.m_clusters = nmbclusters;
- mclrefcnt = malloc (nmbclusters);
+ mclrefcnt = rtems_bsdnet_malloc_mbuf (nmbclusters, MBUF_MALLOC_MCLREFCNT);
if (mclrefcnt == NULL) {
printf ("Can't get mbuf cluster reference counts memory.\n");
return -1;
@@ -174,7 +174,7 @@ bsd_init (void)
* Set up mbuf data structures
*/
- p = malloc(nmbuf * MSIZE + MSIZE - 1);
+ p = rtems_bsdnet_malloc_mbuf(nmbuf * MSIZE + MSIZE - 1,MBUF_MALLOC_MBUF);
p = (char *)(((unsigned int)p + MSIZE - 1) & ~(MSIZE - 1));
if (p == NULL) {
printf ("Can't get network memory.\n");
diff --git a/cpukit/libnetworking/rtems/rtems_malloc_mbuf.c b/cpukit/libnetworking/rtems/rtems_malloc_mbuf.c
new file mode 100644
index 0000000000..d5654c8297
--- /dev/null
+++ b/cpukit/libnetworking/rtems/rtems_malloc_mbuf.c
@@ -0,0 +1,33 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define RTEMS_FAST_MUTEX
+
+#ifdef RTEMS_FAST_MUTEX
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__ 1
+#endif
+
+#include <string.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/rtems_bsdnet.h>
+
+/*
+ * Default allocator for mbuf data. Over-ride in user code to change
+ * the way mbuf's are allocated.
+ */
+
+void* rtems_bsdnet_malloc_mbuf(size_t size, int type)
+{
+ return malloc(size);
+}
+
+