In ld/ChangeLog:
* scripttempl/xstormy16.sc: Don't allocate extra space for the stack. In libgloss/ChangeLog: * 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. In newlib/ChangeLog: * 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.
This commit is contained in:
parent
2c8d73598c
commit
9c2e764253
|
@ -1,3 +1,13 @@
|
||||||
|
2002-02-01 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.
|
||||||
|
|
||||||
2002-02-01 Michael Meissner <meissner@redhat.com>
|
2002-02-01 Michael Meissner <meissner@redhat.com>
|
||||||
|
|
||||||
* mips/cma101.c (__sizemem_default): Allow user to specify the
|
* mips/cma101.c (__sizemem_default): Allow user to specify the
|
||||||
|
|
|
@ -48,7 +48,7 @@ CRT = crt0.o crti.o crtn.o
|
||||||
SIM_SCRIPTS = sim_high.ld
|
SIM_SCRIPTS = sim_high.ld
|
||||||
SIM_LDFLAGS =
|
SIM_LDFLAGS =
|
||||||
SIM_BSP = libsim.a
|
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
|
# Here is stuff for building apps for GDB on the EVA board
|
||||||
EVA_APP_BSP = libeva_app.a
|
EVA_APP_BSP = libeva_app.a
|
||||||
|
|
|
@ -13,6 +13,7 @@ MEMORY
|
||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
__stack = 2 ;
|
__stack = 2 ;
|
||||||
|
__malloc_start = 0x800;
|
||||||
.data :
|
.data :
|
||||||
{
|
{
|
||||||
*(.data)
|
*(.data)
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -39,7 +39,6 @@ SECTIONS
|
||||||
} > RAM
|
} > RAM
|
||||||
. = ALIGN(2);
|
. = ALIGN(2);
|
||||||
__stack = .;
|
__stack = .;
|
||||||
. = . + 4096;
|
|
||||||
_end = .;
|
_end = .;
|
||||||
PROVIDE (end = .);
|
PROVIDE (end = .);
|
||||||
/* Read-only sections in ROM. */
|
/* Read-only sections in ROM. */
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
2002-02-01 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.
|
||||||
|
|
||||||
2002-01-28 Thomas Fitzsimmons <fitzsim@redhat.com>
|
2002-01-28 Thomas Fitzsimmons <fitzsim@redhat.com>
|
||||||
|
|
||||||
* libc/include/sys/signal.h [__CYGWIN__]: Issue error message
|
* libc/include/sys/signal.h [__CYGWIN__]: Issue error message
|
||||||
|
|
|
@ -191,6 +191,7 @@ case "${host_cpu}" in
|
||||||
;;
|
;;
|
||||||
xstormy16)
|
xstormy16)
|
||||||
machine_dir=xstormy16
|
machine_dir=xstormy16
|
||||||
|
newlib_cflags="${newlib_cflags} -DMALLOC_PROVIDED"
|
||||||
;;
|
;;
|
||||||
z8k)
|
z8k)
|
||||||
machine_dir=z8k
|
machine_dir=z8k
|
||||||
|
|
|
@ -12,3 +12,58 @@ lib_a_SOURCES = setjmp.S
|
||||||
|
|
||||||
ACLOCAL_AMFLAGS = -I ../../..
|
ACLOCAL_AMFLAGS = -I ../../..
|
||||||
CONFIG_STATUS_DEPENDENCIES = $(newlib_basedir)/configure.host
|
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 $@
|
||||||
|
|
||||||
|
|
|
@ -86,6 +86,11 @@ lib_a_SOURCES = setjmp.S
|
||||||
|
|
||||||
ACLOCAL_AMFLAGS = -I ../../..
|
ACLOCAL_AMFLAGS = -I ../../..
|
||||||
CONFIG_STATUS_DEPENDENCIES = $(newlib_basedir)/configure.host
|
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
|
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||||
mkinstalldirs = $(SHELL) $(top_srcdir)/../../../../mkinstalldirs
|
mkinstalldirs = $(SHELL) $(top_srcdir)/../../../../mkinstalldirs
|
||||||
CONFIG_CLEAN_FILES =
|
CONFIG_CLEAN_FILES =
|
||||||
|
@ -96,7 +101,9 @@ DEFS = @DEFS@ -I. -I$(srcdir)
|
||||||
CPPFLAGS = @CPPFLAGS@
|
CPPFLAGS = @CPPFLAGS@
|
||||||
LDFLAGS = @LDFLAGS@
|
LDFLAGS = @LDFLAGS@
|
||||||
LIBS = @LIBS@
|
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
|
lib_a_OBJECTS = setjmp.o
|
||||||
CFLAGS = @CFLAGS@
|
CFLAGS = @CFLAGS@
|
||||||
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||||
|
@ -315,6 +322,54 @@ mostlyclean-generic distclean-generic clean-generic \
|
||||||
maintainer-clean-generic clean mostlyclean distclean maintainer-clean
|
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.
|
# 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.
|
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||||
.NOEXPORT:
|
.NOEXPORT:
|
||||||
|
|
|
@ -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
|
|
@ -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
|
Loading…
Reference in New Issue