diff options
author | Eric Norum <WENorum@lbl.gov> | 2006-05-25 17:36:31 +0000 |
---|---|---|
committer | Eric Norum <WENorum@lbl.gov> | 2006-05-25 17:36:31 +0000 |
commit | be31de713feda36d1da3771df5decaa96088713a (patch) | |
tree | d0e0a94c3e92658edad482effc4b086674267069 /cpukit | |
parent | 2006-05-16 Ralf Corsépius <ralf.corsepius@rtems.org> (diff) | |
download | rtems-be31de713feda36d1da3771df5decaa96088713a.tar.bz2 |
Provide customisable mbuf allocation.
Patch from Steven Johnson <sjohnson@sakuraindustries.com>
Diffstat (limited to 'cpukit')
-rw-r--r-- | cpukit/ChangeLog | 9 | ||||
-rw-r--r-- | cpukit/libcsupport/src/malloc.c | 123 | ||||
-rw-r--r-- | cpukit/libnetworking/Makefile.am | 2 | ||||
-rw-r--r-- | cpukit/libnetworking/rtems/rtems_bsdnet.h | 16 | ||||
-rw-r--r-- | cpukit/libnetworking/rtems/rtems_glue.c | 6 | ||||
-rw-r--r-- | cpukit/libnetworking/rtems/rtems_malloc_mbuf.c | 33 |
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); +} + + |