This is the mail archive of the newlib@sources.redhat.com mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

downwards-growing space-efficient malloc for xstormy16



For xstormy16, there's very limited RAM and the stack grows upwards,
so it really needed its own malloc().  The code is reasonably generic,
but at present really useful only on xstormy16, so I've put it down in
that directory.

OK to commit?

-- 
Geoff Keating <geoffk@redhat.com>

===File ~/patches/sanyo-tinymalloc-2.patch==================
Index: devo/libgloss/ChangeLog
2002-01-19  Geoffrey Keating  <geoffk@redhat.com>

	* xstormy16/Makefile.in (SIM_OBJS): Remove sbrk.o, add
	sim_malloc_start.o.
	* xstormy16/eva_app.ld: Add __malloc_start.
	* xstormy16/sbrk.c: Remove.
	* xstormy16/sim_malloc_start.s: New file.
	* xstormy16/sim_high.ld: Make the stack start immediately at the
	end of the program.

Index: devo/newlib/ChangeLog
2002-01-19  Geoffrey Keating  <geoffk@redhat.com>

	* configure.host (xstormy16): Don't use the generic malloc.
	* libc/machine/xstormy16/Makefile.am: Build tiny-malloc.
	* libc/machine/xstormy16/Makefile.in: Regenerate.
	* libc/machine/xstormy16/mallocr.c: New file.
	* libc/machine/xstormy16/tiny-malloc.c: New file.

Index: devo/libgloss/xstormy16/Makefile.in
===================================================================
RCS file: /cvs/cvsfiles/devo/libgloss/xstormy16/Makefile.in,v
retrieving revision 1.2.4.1
diff -p -u -p -r1.2.4.1 Makefile.in
--- Makefile.in	2002/01/15 13:35:25	1.2.4.1
+++ Makefile.in	2002/01/28 15:00:51
@@ -48,7 +48,7 @@ CRT		= crt0.o crti.o crtn.o
 SIM_SCRIPTS	= sim_high.ld
 SIM_LDFLAGS	=
 SIM_BSP		= libsim.a
-SIM_OBJS	= syscalls.o sbrk.o
+SIM_OBJS	= syscalls.o sim_malloc_start.o
 
 # Here is stuff for building apps for GDB on the EVA board
 EVA_APP_BSP     = libeva_app.a
Index: devo/libgloss/xstormy16/eva_app.ld
===================================================================
RCS file: /cvs/cvsfiles/devo/libgloss/xstormy16/eva_app.ld,v
retrieving revision 1.2.4.2
diff -p -u -p -r1.2.4.2 eva_app.ld
--- eva_app.ld	2001/11/19 08:35:47	1.2.4.2
+++ eva_app.ld	2002/01/28 15:00:51
@@ -13,6 +13,7 @@ MEMORY 
 SECTIONS
 {
   __stack = 2 ;
+  __malloc_start = 0x800;
   .data    :
   {
     *(.data)
Index: devo/libgloss/xstormy16/sbrk.c
===================================================================
RCS file: sbrk.c
diff -N sbrk.c
--- /tmp/cvsVBGP8D	Mon Jan 28 07:02:29 2002
+++ /dev/null	Thu Aug 24 02:00:32 2000
@@ -1,55 +0,0 @@
-/* sbrk.c -- allocate memory dynamically.
- * 
- * Copyright (c) 1995,1996 Cygnus Support
- *
- * The authors hereby grant permission to use, copy, modify, distribute,
- * and license this software and its documentation for any purpose, provided
- * that existing copyright notices are retained in all copies and that this
- * notice is included verbatim in any distributions. No written agreement,
- * license, or royalty fee is required for any of the authorized uses.
- * Modifications to this software may be copyrighted by their authors
- * and need not follow the licensing terms described here, provided that
- * the new terms are clearly indicated on the first page of each file where
- * they apply.
- */
-#include <errno.h>
-#include "glue.h"
-
-/* just in case, most boards have at least some memory */
-#ifndef RAMSIZE
-#  define RAMSIZE             (caddr_t)0x100000
-#endif
-
-char *heap_ptr;
-
-/*
- * sbrk -- changes heap size size. Get nbytes more
- *         RAM. We just increment a pointer in what's
- *         left of memory on the board.
- */
-char *
-_sbrk (nbytes)
-     int nbytes;
-{
-  char        *base;
-
-  if (!heap_ptr)
-    heap_ptr = (char *)&_end;
-  base = heap_ptr;
-  heap_ptr += nbytes;
-
-  return base;
-/* FIXME: We really want to make sure we don't run out of RAM, but this
- *       isn't very portable.
- */
-#if 0
-  if ((RAMSIZE - heap_ptr - nbytes) >= 0) {
-    base = heap_ptr;
-    heap_ptr += nbytes;
-    return (base);
-  } else {
-    errno = ENOMEM;
-    return ((char *)-1);
-  }
-#endif
-}
Index: devo/libgloss/xstormy16/sim_high.ld
===================================================================
RCS file: /cvs/cvsfiles/devo/libgloss/xstormy16/sim_high.ld,v
retrieving revision 1.1
diff -p -u -p -r1.1 sim_high.ld
--- sim_high.ld	2001/11/10 01:06:45	1.1
+++ sim_high.ld	2002/01/28 15:00:51
@@ -39,7 +39,6 @@ SECTIONS
   } > RAM
   . = ALIGN(2);
   __stack = .;
-  . = . + 4096;
   _end = .;
   PROVIDE (end = .);
   /* Read-only sections in ROM.  */
Index: devo/libgloss/xstormy16/sim_malloc_start.s
===================================================================
RCS file: sim_malloc_start.s
diff -N sim_malloc_start.s
--- /dev/null	Thu Aug 24 02:00:32 2000
+++ sim_malloc_start.s	Mon Jan 28 07:00:51 2002
@@ -0,0 +1,5 @@
+# This file just defines __malloc_start for newlib for the simulator.
+# The simulator has RAM up to the I/O area at 0x7F00.
+	.globl __malloc_start
+	.set __malloc_start,0x7F00
+	
Index: devo/newlib/configure.host
===================================================================
RCS file: /cvs/cvsfiles/devo/newlib/configure.host,v
retrieving revision 1.80.6.1
diff -p -u -p -r1.80.6.1 configure.host
--- configure.host	2001/11/13 22:06:02	1.80.6.1
+++ configure.host	2002/01/28 15:00:53
@@ -151,6 +151,7 @@ case "${host_cpu}" in
 	;;
   xstormy16)
 	machine_dir=xstormy16
+	newlib_cflags="${newlib_cflags} -DMALLOC_PROVIDED"
         ;;
   strongarm)
 	machine_dir=arm
Index: devo/newlib/libc/machine/xstormy16/Makefile.am
===================================================================
RCS file: /cvs/cvsfiles/devo/newlib/libc/machine/xstormy16/Makefile.am,v
retrieving revision 1.1
diff -p -u -p -r1.1 Makefile.am
--- Makefile.am	2001/11/09 09:14:43	1.1
+++ Makefile.am	2002/01/28 15:00:53
@@ -12,3 +12,58 @@ lib_a_SOURCES = setjmp.S
 
 ACLOCAL_AMFLAGS = -I ../../..
 CONFIG_STATUS_DEPENDENCIES = $(newlib_basedir)/configure.host
+
+lib_a_LIBADD = malloc.o free.o realloc.o calloc.o cfree.o malign.o \
+	valloc.o pvalloc.o mallinfo.o mallstats.o msize.o mallopt.o \
+	mallocr.o freer.o reallocr.o callocr.o
+
+MALLOC_COMPILE = $(COMPILE)
+
+malloc.o: tiny-malloc.c
+	$(MALLOC_COMPILE) -DDEFINE_MALLOC -c $(srcdir)/tiny-malloc.c -o $@
+
+free.o: tiny-malloc.c
+	$(MALLOC_COMPILE) -DDEFINE_FREE -c $(srcdir)/tiny-malloc.c -o $@
+
+realloc.o: tiny-malloc.c
+	$(MALLOC_COMPILE) -DDEFINE_REALLOC -c $(srcdir)/tiny-malloc.c -o $@
+
+calloc.o: tiny-malloc.c
+	$(MALLOC_COMPILE) -DDEFINE_CALLOC -c $(srcdir)/tiny-malloc.c -o $@
+
+cfree.o: tiny-malloc.c
+	$(MALLOC_COMPILE) -DDEFINE_CFREE -c $(srcdir)/tiny-malloc.c -o $@
+
+malign.o: tiny-malloc.c
+	$(MALLOC_COMPILE) -DDEFINE_MEMALIGN -c $(srcdir)/tiny-malloc.c -o $@
+
+valloc.o: tiny-malloc.c
+	$(MALLOC_COMPILE) -DDEFINE_VALLOC -c $(srcdir)/tiny-malloc.c -o $@
+
+pvalloc.o: tiny-malloc.c
+	$(MALLOC_COMPILE) -DDEFINE_PVALLOC -c $(srcdir)/tiny-malloc.c -o $@
+
+mallinfo.o: tiny-malloc.c
+	$(MALLOC_COMPILE) -DDEFINE_MALLINFO -c $(srcdir)/tiny-malloc.c -o $@
+
+mallstats.o: tiny-malloc.c
+	$(MALLOC_COMPILE) -DDEFINE_MALLOC_STATS -c $(srcdir)/tiny-malloc.c -o $@
+
+msize.o: tiny-malloc.c
+	$(MALLOC_COMPILE) -DDEFINE_MALLOC_USABLE_SIZE -c $(srcdir)/tiny-malloc.c -o $@
+
+mallopt.o: mallocr.c
+	$(MALLOC_COMPILE) -DDEFINE_MALLOPT -c $(srcdir)/mallocr.c -o $@
+
+mallocr.o: mallocr.c
+	$(MALLOC_COMPILE) -DDEFINE_MALLOC -c $(srcdir)/mallocr.c -o $@
+
+freer.o: mallocr.c
+	$(MALLOC_COMPILE) -DDEFINE_FREE -c $(srcdir)/mallocr.c -o $@
+
+reallocr.o: mallocr.c
+	$(MALLOC_COMPILE) -DDEFINE_REALLOC -c $(srcdir)/mallocr.c -o $@
+
+callocr.o: mallocr.c
+	$(MALLOC_COMPILE) -DDEFINE_CALLOC -c $(srcdir)/mallocr.c -o $@
+
Index: devo/newlib/libc/machine/xstormy16/Makefile.in
===================================================================
RCS file: /cvs/cvsfiles/devo/newlib/libc/machine/xstormy16/Makefile.in,v
retrieving revision 1.1
diff -p -u -p -r1.1 Makefile.in
--- Makefile.in	2001/11/09 09:14:43	1.1
+++ Makefile.in	2002/01/28 15:00:53
@@ -86,6 +86,11 @@ lib_a_SOURCES = setjmp.S
 
 ACLOCAL_AMFLAGS = -I ../../..
 CONFIG_STATUS_DEPENDENCIES = $(newlib_basedir)/configure.host
+
+lib_a_LIBADD = malloc.o free.o realloc.o calloc.o cfree.o malign.o 	valloc.o pvalloc.o mallinfo.o mallstats.o msize.o mallopt.o 	mallocr.o freer.o reallocr.o callocr.o
+
+
+MALLOC_COMPILE = $(COMPILE)
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 mkinstalldirs = $(SHELL) $(top_srcdir)/../../../../mkinstalldirs
 CONFIG_CLEAN_FILES = 
@@ -96,7 +101,9 @@ DEFS = @DEFS@ -I. -I$(srcdir) 
 CPPFLAGS = @CPPFLAGS@
 LDFLAGS = @LDFLAGS@
 LIBS = @LIBS@
-lib_a_LIBADD = 
+lib_a_DEPENDENCIES =  malloc.o free.o realloc.o calloc.o cfree.o \
+malign.o valloc.o pvalloc.o mallinfo.o mallstats.o msize.o mallopt.o \
+mallocr.o freer.o reallocr.o callocr.o
 lib_a_OBJECTS =  setjmp.o
 CFLAGS = @CFLAGS@
 COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
@@ -314,6 +321,54 @@ install uninstall-am uninstall all-redir
 mostlyclean-generic distclean-generic clean-generic \
 maintainer-clean-generic clean mostlyclean distclean maintainer-clean
 
+
+malloc.o: tiny-malloc.c
+	$(MALLOC_COMPILE) -DDEFINE_MALLOC -c $(srcdir)/tiny-malloc.c -o $@
+
+free.o: tiny-malloc.c
+	$(MALLOC_COMPILE) -DDEFINE_FREE -c $(srcdir)/tiny-malloc.c -o $@
+
+realloc.o: tiny-malloc.c
+	$(MALLOC_COMPILE) -DDEFINE_REALLOC -c $(srcdir)/tiny-malloc.c -o $@
+
+calloc.o: tiny-malloc.c
+	$(MALLOC_COMPILE) -DDEFINE_CALLOC -c $(srcdir)/tiny-malloc.c -o $@
+
+cfree.o: tiny-malloc.c
+	$(MALLOC_COMPILE) -DDEFINE_CFREE -c $(srcdir)/tiny-malloc.c -o $@
+
+malign.o: tiny-malloc.c
+	$(MALLOC_COMPILE) -DDEFINE_MEMALIGN -c $(srcdir)/tiny-malloc.c -o $@
+
+valloc.o: tiny-malloc.c
+	$(MALLOC_COMPILE) -DDEFINE_VALLOC -c $(srcdir)/tiny-malloc.c -o $@
+
+pvalloc.o: tiny-malloc.c
+	$(MALLOC_COMPILE) -DDEFINE_PVALLOC -c $(srcdir)/tiny-malloc.c -o $@
+
+mallinfo.o: tiny-malloc.c
+	$(MALLOC_COMPILE) -DDEFINE_MALLINFO -c $(srcdir)/tiny-malloc.c -o $@
+
+mallstats.o: tiny-malloc.c
+	$(MALLOC_COMPILE) -DDEFINE_MALLOC_STATS -c $(srcdir)/tiny-malloc.c -o $@
+
+msize.o: tiny-malloc.c
+	$(MALLOC_COMPILE) -DDEFINE_MALLOC_USABLE_SIZE -c $(srcdir)/tiny-malloc.c -o $@
+
+mallopt.o: mallocr.c
+	$(MALLOC_COMPILE) -DDEFINE_MALLOPT -c $(srcdir)/mallocr.c -o $@
+
+mallocr.o: mallocr.c
+	$(MALLOC_COMPILE) -DDEFINE_MALLOC -c $(srcdir)/mallocr.c -o $@
+
+freer.o: mallocr.c
+	$(MALLOC_COMPILE) -DDEFINE_FREE -c $(srcdir)/mallocr.c -o $@
+
+reallocr.o: mallocr.c
+	$(MALLOC_COMPILE) -DDEFINE_REALLOC -c $(srcdir)/mallocr.c -o $@
+
+callocr.o: mallocr.c
+	$(MALLOC_COMPILE) -DDEFINE_CALLOC -c $(srcdir)/mallocr.c -o $@
 
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.
Index: devo/newlib/libc/machine/xstormy16/mallocr.c
===================================================================
RCS file: mallocr.c
diff -N mallocr.c
--- /dev/null	Thu Aug 24 02:00:32 2000
+++ mallocr.c	Mon Jan 28 07:00:53 2002
@@ -0,0 +1,33 @@
+#include <malloc.h>
+
+#ifdef DEFINE_MALLOC
+_PTR 
+_malloc_r (struct _reent *r, size_t sz)
+{
+  return malloc (sz);
+}
+#endif
+
+#ifdef DEFINE_CALLOC
+_PTR 
+_calloc_r (struct _reent *r, size_t a, size_t b)
+{
+  return calloc (a, b);
+}
+#endif
+
+#ifdef DEFINE_FREE
+void
+_free_r (struct _reent *r, _PTR x)
+{
+  free (x);
+}
+#endif
+
+#ifdef DEFINE_REALLOC
+_PTR 
+_realloc_r (struct _reent *r, _PTR x, size_t sz)
+{
+  return realloc (x, sz);
+}
+#endif
Index: devo/newlib/libc/machine/xstormy16/tiny-malloc.c
===================================================================
RCS file: tiny-malloc.c
diff -N tiny-malloc.c
--- /dev/null	Thu Aug 24 02:00:32 2000
+++ tiny-malloc.c	Mon Jan 28 07:00:53 2002
@@ -0,0 +1,598 @@
+/* A replacement malloc with:
+   - Much reduced code size;
+   - Smaller RAM footprint;
+   - The ability to handle downward-growing heaps;
+   but
+   - Slower;
+   - Probably higher memory fragmentation;
+   - Doesn't support threads (but, if it did support threads,
+     it wouldn't need a global lock, only a compare-and-swap instruction);
+   - Assumes the maximum alignment required is the alignment of a pointer;
+   - Assumes that memory is already there and doesn't need to be allocated.
+
+* Synopsis of public routines
+
+  malloc(size_t n);
+     Return a pointer to a newly allocated chunk of at least n bytes, or null
+     if no space is available.
+  free(void* p);
+     Release the chunk of memory pointed to by p, or no effect if p is null.
+  realloc(void* p, size_t n);
+     Return a pointer to a chunk of size n that contains the same data
+     as does chunk p up to the minimum of (n, p's size) bytes, or null
+     if no space is available. The returned pointer may or may not be
+     the same as p. If p is null, equivalent to malloc.  Unless the
+     #define REALLOC_ZERO_BYTES_FREES below is set, realloc with a
+     size argument of zero (re)allocates a minimum-sized chunk.
+  memalign(size_t alignment, size_t n);
+     Return a pointer to a newly allocated chunk of n bytes, aligned
+     in accord with the alignment argument, which must be a power of
+     two.  Will fail if 'alignment' is too large.
+  calloc(size_t unit, size_t quantity);
+     Returns a pointer to quantity * unit bytes, with all locations
+     set to zero.
+  cfree(void* p);
+     Equivalent to free(p).
+  malloc_trim(size_t pad);
+     Release all but pad bytes of freed top-most memory back 
+     to the system. Return 1 if successful, else 0.
+  malloc_usable_size(void* p);
+     Report the number usable allocated bytes associated with allocated
+     chunk p. This may or may not report more bytes than were requested,
+     due to alignment and minimum size constraints.
+  malloc_stats();
+     Prints brief summary statistics on stderr.
+  mallinfo()
+     Returns (by copy) a struct containing various summary statistics.
+  mallopt(int parameter_number, int parameter_value)
+     Changes one of the tunable parameters described below. Returns
+     1 if successful in changing the parameter, else 0.  Actually, returns 0
+     always, as no parameter can be changed.
+*/
+
+#ifdef __xstormy16__
+#define MALLOC_DIRECTION -1
+#endif
+
+#ifndef MALLOC_DIRECTION
+#define MALLOC_DIRECTION 1
+#endif
+
+#include <stddef.h>
+
+void* malloc(size_t);
+void    free(void*);
+void* realloc(void*, size_t);
+void* memalign(size_t, size_t);
+void* valloc(size_t);
+void* pvalloc(size_t);
+void* calloc(size_t, size_t);
+void    cfree(void*);
+int     malloc_trim(size_t);
+size_t  malloc_usable_size(void*);
+void    malloc_stats(void);
+int     mallopt(int, int);
+struct mallinfo mallinfo(void);
+
+typedef struct freelist_entry {
+  size_t size;
+  struct freelist_entry *next;
+} *fle;
+
+extern void * __malloc_end;
+extern fle __malloc_freelist;
+
+/* Return the number of bytes that need to be added to X to make it
+   aligned to an ALIGN boundary.  ALIGN must be a power of 2.  */
+#define M_ALIGN(x, align) (-(size_t)(x) & ((align) - 1))
+
+/* Return the number of bytes that need to be subtracted from X to make it
+   aligned to an ALIGN boundary.  ALIGN must be a power of 2.  */
+#define M_ALIGN_SUB(x, align) ((size_t)(x) & ((align) - 1))
+
+extern void __malloc_start;
+
+/* This is the minimum gap allowed between __malloc_end and the top of
+   the stack.  This is only checked for when __malloc_end is
+   decreased; if instead the stack grows into the heap, silent data
+   corruption will result.  */
+#define MALLOC_MINIMUM_GAP 32
+
+#ifdef __xstormy16__
+register void * stack_pointer asm ("r15");
+#define MALLOC_LIMIT stack_pointer
+#else
+#define MALLOC_LIMIT __builtin_frame_address (0)
+#endif
+
+#if MALLOC_DIRECTION < 0
+#define CAN_ALLOC_P(required)				\
+  (((size_t) __malloc_end - (size_t)MALLOC_LIMIT	\
+    - MALLOC_MINIMUM_GAP) >= (required))
+#else
+#define CAN_ALLOC_P(required)				\
+  (((size_t)MALLOC_LIMIT - (size_t) __malloc_end	\
+    - MALLOC_MINIMUM_GAP) >= (required))
+#endif
+
+/* real_size is the size we actually have to allocate, allowing for
+   overhead and alignment.  */
+#define REAL_SIZE(sz)						\
+  ((sz) < sizeof (struct freelist_entry) - sizeof (size_t)	\
+   ? sizeof (struct freelist_entry)				\
+   : sz + sizeof (size_t) + M_ALIGN(sz, sizeof (size_t)))
+
+#ifdef DEFINE_MALLOC
+
+void * __malloc_end = &__malloc_start;
+fle __malloc_freelist;
+
+void *
+malloc (size_t sz)
+{
+  fle *nextfree;
+  fle block;
+
+  /* real_size is the size we actually have to allocate, allowing for
+     overhead and alignment.  */
+  size_t real_size = REAL_SIZE (sz);
+
+  /* Look for the first block on the freelist that is large enough.  */
+  for (nextfree = &__malloc_freelist; 
+       *nextfree; 
+       nextfree = &(*nextfree)->next)  
+    {
+      block = *nextfree;
+      
+      if (block->size >= real_size)
+	{
+	  /* If the block found is just the right size, remove it from
+	     the free list.  Otherwise, split it.  */
+	  if (block->size < real_size + sizeof (struct freelist_entry))
+	    {
+	      *nextfree = block->next;
+	      return (void *)&block->next;
+	    }
+	  else
+	    {
+	      size_t newsize = block->size - real_size;
+	      fle newnext = block->next;
+	      *nextfree = (fle)((size_t)block + real_size);
+	      (*nextfree)->size = newsize;
+	      (*nextfree)->next = newnext;
+	      goto done;
+	    }
+	}
+
+      /* If this is the last block on the freelist, and it was too small,
+	 enlarge it.  */
+      if (! block->next
+	  && __malloc_end == (void *)((size_t)block + block->size))
+	{
+	  size_t moresize = real_size - block->size;
+	  if (! CAN_ALLOC_P (moresize))
+	    return NULL;
+	  
+	  *nextfree = NULL;
+	  if (MALLOC_DIRECTION < 0)
+	    {
+	      block = __malloc_end = (void *)((size_t)block - moresize);
+	    }
+	  else
+	    {
+	      __malloc_end = (void *)((size_t)block + real_size);
+	    }
+
+	  goto done;
+	}
+    }
+
+  /* No free space at the end of the free list.  Allocate new space
+     and use that.  */
+
+  if (! CAN_ALLOC_P (real_size))
+    return NULL;
+
+  if (MALLOC_DIRECTION > 0)
+    {
+      block = __malloc_end;
+      __malloc_end = (void *)((size_t)__malloc_end + real_size);
+    }
+  else
+    {
+      block = __malloc_end = (void *)((size_t)__malloc_end - real_size);
+    }
+ done:
+  block->size = real_size;
+  return (void *)&block->next;
+}
+
+#endif
+
+#ifdef DEFINE_FREE
+
+void
+free (void *block_p)
+{
+  fle *nextfree;
+  fle block = (fle)((size_t) block_p - offsetof (struct freelist_entry, next));
+
+  if (block_p == NULL)
+    return;
+  
+  /* Look on the freelist to see if there's a free block just before
+     or just after this block.  */
+  for (nextfree = &__malloc_freelist; 
+       *nextfree; 
+       nextfree = &(*nextfree)->next)
+    {
+      fle thisblock = *nextfree;
+      if ((size_t)thisblock + thisblock->size == (size_t) block)
+	{
+	  thisblock->size += block->size;
+	  if (MALLOC_DIRECTION > 0
+	      && thisblock->next
+	      && (size_t) block + block->size == (size_t) thisblock->next)
+	    {
+	      thisblock->size += thisblock->next->size;
+	      thisblock->next = thisblock->next->next;
+	    }
+	  return;
+	}
+      else if ((size_t) thisblock == (size_t) block + block->size)
+	{
+	  if (MALLOC_DIRECTION < 0
+	      && thisblock->next
+	      && (size_t) block == ((size_t) thisblock->next 
+				    + thisblock->next->size))
+	    {
+	      *nextfree = thisblock->next;
+	      thisblock->next->size += block->size + thisblock->size;
+	    }
+	  else
+	    {
+	      block->size += thisblock->size;
+	      block->next = thisblock->next;
+	      *nextfree = block;
+	    }
+	  return;
+	}
+      else if ((MALLOC_DIRECTION > 0
+		&& (size_t) thisblock > (size_t) block)
+	       || (MALLOC_DIRECTION < 0
+		   && (size_t) thisblock < (size_t) block))
+	break;
+    }
+
+  block->next = *nextfree;
+  *nextfree = block;
+  return;
+}
+#endif
+
+#ifdef DEFINE_REALLOC
+void *
+realloc (void *block_p, size_t sz)
+{
+  fle block = (fle)((size_t) block_p - offsetof (struct freelist_entry, next));
+  size_t real_size = REAL_SIZE (sz);
+  size_t old_real_size;
+
+  if (block_p == NULL)
+    return malloc (sz);
+
+  old_real_size = block->size;
+
+  /* Perhaps we need to allocate more space.  */
+  if (old_real_size < real_size)
+    {
+      void *result;
+      size_t old_size = old_real_size - sizeof (size_t);
+      
+      /* Need to allocate, copy, and free.  */
+      result = malloc (sz);
+      if (result == NULL)
+	return NULL;
+      memcpy (result, block_p, old_size < sz ? old_size : sz);
+      free (block_p);
+      return result;
+    }
+  /* Perhaps we can free some space.  */
+  if (old_real_size - real_size >= sizeof (struct freelist_entry))
+    {
+      fle newblock = (fle)((size_t)block + real_size);
+      block->size = real_size;
+      newblock->size = old_real_size - real_size;
+      free (&newblock->next);
+    }
+  return block_p;
+}
+#endif
+
+#ifdef DEFINE_CALLOC
+void *
+calloc (size_t n, size_t elem_size)
+{
+  void *result;
+  size_t sz = n * elem_size;
+  result = malloc (sz);
+  if (result != NULL)
+    memset (result, 0, sz);
+  return result;
+}
+#endif
+
+#ifdef DEFINE_CFREE
+void
+cfree (void *p)
+{
+  free (p);
+}
+#endif
+
+#ifdef DEFINE_MEMALIGN
+void *
+memalign (size_t align, size_t sz)
+{
+  fle *nextfree;
+  fle block;
+
+  /* real_size is the size we actually have to allocate, allowing for
+     overhead and alignment.  */
+  size_t real_size = REAL_SIZE (sz);
+
+  /* Some sanity checking on 'align'. */
+  if ((align & (align - 1)) != 0
+      || align <= 0)
+    return NULL;
+
+  /* Look for the first block on the freelist that is large enough.  */
+  /* One tricky part is this: We want the result to be a valid pointer
+     to free.  That means that there has to be room for a size_t
+     before the block.  If there's additional space before the block,
+     it should go on the freelist, or it'll be lost---we could add it
+     to the size of the block before it in memory, but finding the
+     previous block is expensive.  */
+  for (nextfree = &__malloc_freelist; 
+       ; 
+       nextfree = &(*nextfree)->next)  
+    {
+      size_t before_size;
+      size_t old_size;
+
+      /* If we've run out of free blocks, allocate more space.  */
+      if (! *nextfree)
+	{
+	  old_size = real_size;
+	  if (MALLOC_DIRECTION < 0)
+	    {
+	      old_size += M_ALIGN_SUB (((size_t)__malloc_end 
+					- old_size + sizeof (size_t)),
+				       align);
+	      if (! CAN_ALLOC_P (old_size))
+		return NULL;
+	      block = __malloc_end = (void *)((size_t)__malloc_end - old_size);
+	    }
+	  else
+	    {
+	      block = __malloc_end;
+	      old_size += M_ALIGN ((size_t)__malloc_end + sizeof (size_t),
+				   align);
+	      if (! CAN_ALLOC_P (old_size))
+		return NULL;
+	      __malloc_end = (void *)((size_t)__malloc_end + old_size);
+	    }
+	  *nextfree = block;
+	  block->size = old_size;
+	  block->next = NULL;
+	}
+      else
+	{
+	  block = *nextfree;
+	  old_size = block->size;
+	}
+      
+
+      before_size = M_ALIGN (&block->next, align);
+      if (before_size != 0)
+	before_size = sizeof (*block) + M_ALIGN (&(block+1)->next, align);
+
+      /* If this is the last block on the freelist, and it is too small,
+	 enlarge it.  */
+      if (! block->next
+	  && old_size < real_size + before_size
+	  && __malloc_end == (void *)((size_t)block + block->size))
+	{
+	  if (MALLOC_DIRECTION < 0)
+	    {
+	      size_t moresize = real_size - block->size;
+	      moresize += M_ALIGN_SUB ((size_t)&block->next - moresize, align);
+	      if (! CAN_ALLOC_P (moresize))
+		return NULL;
+	      block = __malloc_end = (void *)((size_t)block - moresize);
+	      block->next = NULL;
+	      block->size = old_size = old_size + moresize;
+	      before_size = 0;
+	    }
+	  else
+	    {
+	      if (! CAN_ALLOC_P (before_size + real_size - block->size))
+		return NULL;
+	      __malloc_end = (void *)((size_t)block + before_size + real_size);
+	      block->size = old_size = before_size + real_size;
+	    }
+
+	  /* Two out of the four cases below will now be possible; which
+	     two depends on MALLOC_DIRECTION.  */
+	}
+
+      if (old_size >= real_size + before_size)
+	{
+	  /* This block will do.  If there needs to be space before it, 
+	     split the block.  */
+	  if (before_size != 0)
+	    {
+	      fle old_block = block;
+
+	      old_block->size = before_size;
+	      block = (fle)((size_t)block + before_size);
+	      
+	      /* If there's no space after the block, we're now nearly
+                 done; just make a note of the size required.  
+	         Otherwise, we need to create a new free space block.  */
+	      if (old_size - before_size 
+		  <= real_size + sizeof (struct freelist_entry))
+		{
+		  block->size = old_size - before_size;
+		  return (void *)&block->next;
+		}
+	      else 
+		{
+		  fle new_block;
+		  new_block = (fle)((size_t)block + real_size);
+		  new_block->size = old_size - before_size - real_size;
+		  if (MALLOC_DIRECTION > 0)
+		    {
+		      new_block->next = old_block->next;
+		      old_block->next = new_block;
+		    }
+		  else
+		    {
+		      new_block->next = old_block;
+		      *nextfree = new_block;
+		    }
+		  goto done;
+		}
+	    }
+	  else
+	    {
+	      /* If the block found is just the right size, remove it from
+		 the free list.  Otherwise, split it.  */
+	      if (old_size <= real_size + sizeof (struct freelist_entry))
+		{
+		  *nextfree = block->next;
+		  return (void *)&block->next;
+		}
+	      else
+		{
+		  size_t newsize = old_size - real_size;
+		  fle newnext = block->next;
+		  *nextfree = (fle)((size_t)block + real_size);
+		  (*nextfree)->size = newsize;
+		  (*nextfree)->next = newnext;
+		  goto done;
+		}
+	    }
+	}
+    }
+
+ done:
+  block->size = real_size;
+  return (void *)&block->next;
+}
+#endif
+
+#ifdef DEFINE_VALLOC
+void *
+valloc (size_t sz)
+{
+  return memalign (128, sz);
+}
+#endif
+#ifdef DEFINE_PVALLOC
+void *
+pvalloc (size_t sz)
+{
+  return memalign (128, sz + M_ALIGN (sz, 128));
+}
+#endif
+
+#ifdef DEFINE_MALLINFO
+#include "malloc.h"
+
+struct mallinfo 
+mallinfo (void)
+{
+  struct mallinfo r;
+  fle fr;
+  size_t free_size;
+  size_t total_size;
+  size_t free_blocks;
+
+  memset (&r, 0, sizeof (r));
+
+  free_size = 0;
+  free_blocks = 0;
+  for (fr = __malloc_freelist; fr; fr = fr->next)
+    {
+      free_size += fr->size;
+      free_blocks++;
+      if (! fr->next)
+	{
+	  int atend;
+	  if (MALLOC_DIRECTION > 0)
+	    atend = (void *)((size_t)fr + fr->size) == __malloc_end;
+	  else
+	    atend = (void *)fr == __malloc_end;
+	  if (atend)
+	    r.keepcost = fr->size;
+	}
+    }
+
+  if (MALLOC_DIRECTION > 0)
+    total_size = (char *)__malloc_end - (char *)&__malloc_start;
+  else
+    total_size = (char *)&__malloc_start - (char *)__malloc_end;
+  
+#ifdef DEBUG
+  /* Fixme: should walk through all the in-use blocks and see if
+     they're valid.  */
+#endif
+
+  r.arena = total_size;
+  r.fordblks = free_size;
+  r.uordblks = total_size - free_size;
+  r.ordblks = free_blocks;
+  return r;
+}
+#endif
+
+#ifdef DEFINE_MALLOC_STATS
+#include "malloc.h"
+#include <stdio.h>
+
+void 
+malloc_stats(void)
+{
+  struct mallinfo i;
+  FILE *fp;
+  
+  fp = stderr;
+  i = mallinfo();
+  fprintf (fp, "malloc has reserved %u bytes between %p and %p\n",
+	   i.arena, &__malloc_start, __malloc_end);
+  fprintf (fp, "there are %u bytes free in %u chunks\n",
+	   i.fordblks, i.ordblks);
+  fprintf (fp, "of which %u bytes are at the end of the reserved space\n",
+	   i.keepcost);
+  fprintf (fp, "and %u bytes are in use.\n", i.uordblks);
+}
+#endif
+
+#ifdef DEFINE_MALLOC_USABLE_SIZE
+size_t 
+malloc_usable_size (void *block_p)
+{
+  fle block = (fle)((size_t) block_p - offsetof (struct freelist_entry, next));
+  return block->size - sizeof (size_t);
+}
+#endif
+
+#ifdef DEFINE_MALLOPT
+int
+mallopt (int n, int v)
+{
+  (void)n; (void)v;
+  return 0;
+}
+#endif
============================================================


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]