From a83263b981a6b222d6305023682e57e4a0f387c4 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Wed, 29 May 2013 12:37:59 +0000 Subject: [PATCH] * configure.in (--enable-newlib-nano-malloc): New option. * configure: Regenerated. * libc/configure.in (--enable-newlib-nano-malloc): New option. * libc/configure: Regenerated. * libc/stdlib/Makefile.am (NEWLIB_NANO_MALLOC): Use. * libc/stdlib/Makefile.in: Regenerated. * libc/stdlib/nano-mallocr.c: New file, implementing nano version malloc family functions. --- newlib/ChangeLog | 12 + newlib/configure | 22 ++ newlib/configure.in | 23 +- newlib/libc/configure | 32 ++ newlib/libc/configure.in | 10 + newlib/libc/stdlib/Makefile.am | 98 +++-- newlib/libc/stdlib/Makefile.in | 94 +++-- newlib/libc/stdlib/nano-mallocr.c | 581 ++++++++++++++++++++++++++++++ 8 files changed, 799 insertions(+), 73 deletions(-) create mode 100644 newlib/libc/stdlib/nano-mallocr.c diff --git a/newlib/ChangeLog b/newlib/ChangeLog index 6008381f7..114f4cd0b 100644 --- a/newlib/ChangeLog +++ b/newlib/ChangeLog @@ -1,3 +1,15 @@ +2013-05-13 Joey Ye + Bin Cheng + + * configure.in (--enable-newlib-nano-malloc): New option. + * configure: Regenerated. + * libc/configure.in (--enable-newlib-nano-malloc): New option. + * libc/configure: Regenerated. + * libc/stdlib/Makefile.am (NEWLIB_NANO_MALLOC): Use. + * libc/stdlib/Makefile.in: Regenerated. + * libc/stdlib/nano-mallocr.c: New file, implementing nano + version malloc family functions. + 2013-05-28 Richard Earnshaw * libc/macine/arm/strcpy.S: Explicitly set build attributes when diff --git a/newlib/configure b/newlib/configure index a91700c21..fe55eb115 100755 --- a/newlib/configure +++ b/newlib/configure @@ -792,6 +792,7 @@ enable_newlib_reent_small enable_newlib_fvwrite_in_streamio enable_newlib_fseek_optimization enable_newlib_wide_orient +enable_newlib_nano_malloc enable_multilib enable_target_optspace enable_malloc_debugging @@ -1458,6 +1459,7 @@ Optional Features: --disable-newlib-fvwrite-in-streamio disable iov in streamio --disable-newlib-fseek-optimization disable fseek optimization --disable-newlib-wide-orient Turn off wide orientation in streamio + --enable-newlib-nano-malloc use small-footprint nano-malloc implementation --enable-multilib build many library versions (default) --enable-target-optspace optimize for space --enable-malloc-debugging indicate malloc debugging requested @@ -2395,6 +2397,19 @@ else fi +# Check whether --enable-newlib-nano-malloc was given. +if test "${enable_newlib_nano_malloc+set}" = set; then : + enableval=$enable_newlib_nano_malloc; if test "${newlib_nano_malloc+set}" != set; then + case "${enableval}" in + yes) newlib_nano_malloc=yes ;; + no) newlib_nano_malloc=no ;; + *) as_fn_error $? "bad value ${enableval} for newlib-nano-malloc option" "$LINENO" 5 ;; + esac + fi +else + newlib_nano_malloc=no +fi + # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || @@ -12297,6 +12312,13 @@ _ACEOF fi +if test "${newlib_nano_malloc}" = "yes"; then +cat >>confdefs.h <<_ACEOF +#define NEWLIB_NANO_MALLOC 1 +_ACEOF + +fi + if test "x${iconv_encodings}" != "x" \ || test "x${iconv_to_encodings}" != "x" \ diff --git a/newlib/configure.in b/newlib/configure.in index 95025fe88..5646d64d0 100644 --- a/newlib/configure.in +++ b/newlib/configure.in @@ -157,6 +157,19 @@ AC_ARG_ENABLE(newlib_wide_orient, *) AC_MSG_ERROR(bad value ${enableval} for newlib-wide-orient) ;; esac],[newlib_wide_orient=yes]) +dnl Support --enable-newlib-nano-malloc +dnl This option is also read in libc/configure.in. It is repeated +dnl here so that it shows up in the help text. +AC_ARG_ENABLE(newlib-nano-malloc, +[ --enable-newlib-nano-malloc use small-footprint nano-malloc implementation], +[if test "${newlib_nano_malloc+set}" != set; then + case "${enableval}" in + yes) newlib_nano_malloc=yes ;; + no) newlib_nano_malloc=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for newlib-nano-malloc option) ;; + esac + fi], [newlib_nano_malloc=no])dnl + NEWLIB_CONFIGURE(.) dnl We have to enable libtool after NEWLIB_CONFIGURE because if we try and @@ -345,19 +358,23 @@ fi if test "${newlib_atexit_dynamic_alloc}" = "yes"; then AC_DEFINE_UNQUOTED(_ATEXIT_DYNAMIC_ALLOC) fi - + if test "${newlib_fvwrite_in_streamio}" = "yes"; then AC_DEFINE_UNQUOTED(_FVWRITE_IN_STREAMIO) fi - + if test "${newlib_fseek_optimization}" = "yes"; then AC_DEFINE_UNQUOTED(_FSEEK_OPTIMIZATION) fi - + if test "${newlib_wide_orient}" = "yes"; then AC_DEFINE_UNQUOTED(_WIDE_ORIENT) fi +if test "${newlib_nano_malloc}" = "yes"; then +AC_DEFINE_UNQUOTED(_NANO_MALLOC) +fi + dnl dnl Parse --enable-newlib-iconv-encodings option argument dnl diff --git a/newlib/libc/configure b/newlib/libc/configure index 4a1ab6b99..e2782a5f5 100755 --- a/newlib/libc/configure +++ b/newlib/libc/configure @@ -749,6 +749,8 @@ build newlib_basedir MAY_SUPPLY_SYSCALLS_FALSE MAY_SUPPLY_SYSCALLS_TRUE +NEWLIB_NANO_MALLOC_FALSE +NEWLIB_NANO_MALLOC_TRUE NEWLIB_WIDE_ORIENT_FALSE NEWLIB_WIDE_ORIENT_TRUE target_alias @@ -794,6 +796,7 @@ ac_user_opts=' enable_option_checking enable_newlib_io_pos_args enable_newlib_wide_orient +enable_newlib_nano_malloc enable_multilib enable_target_optspace enable_malloc_debugging @@ -1444,6 +1447,7 @@ Optional Features: --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-newlib-io-pos-args enable printf-family positional arg support --disable-newlib-wide-orient Turn off wide char orient in streamio + --enable-newlib-nano-malloc Use small-footprint nano-malloc implementation --enable-multilib build many library versions (default) --enable-target-optspace optimize for space --enable-malloc-debugging indicate malloc debugging requested @@ -2236,6 +2240,26 @@ else fi +# Check whether --enable-newlib_nano_malloc was given. +if test "${enable_newlib_nano_malloc+set}" = set; then : + enableval=$enable_newlib_nano_malloc; case "${enableval}" in + yes) newlib_nano_malloc=yes ;; + no) newlib_nano_malloc=no ;; + *) as_fn_error $? "bad value ${enableval} for newlib-nano-malloc" "$LINENO" 5 ;; + esac +else + newlib_nano_malloc=no +fi + + if test x$newlib_nano_malloc = xyes; then + NEWLIB_NANO_MALLOC_TRUE= + NEWLIB_NANO_MALLOC_FALSE='#' +else + NEWLIB_NANO_MALLOC_TRUE='#' + NEWLIB_NANO_MALLOC_FALSE= +fi + + # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || @@ -12213,6 +12237,14 @@ LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs +if test -z "${NEWLIB_WIDE_ORIENT_TRUE}" && test -z "${NEWLIB_WIDE_ORIENT_FALSE}"; then + as_fn_error $? "conditional \"NEWLIB_WIDE_ORIENT\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${NEWLIB_NANO_MALLOC_TRUE}" && test -z "${NEWLIB_NANO_MALLOC_FALSE}"; then + as_fn_error $? "conditional \"NEWLIB_NANO_MALLOC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${MAY_SUPPLY_SYSCALLS_TRUE}" && test -z "${MAY_SUPPLY_SYSCALLS_FALSE}"; then as_fn_error $? "conditional \"MAY_SUPPLY_SYSCALLS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 diff --git a/newlib/libc/configure.in b/newlib/libc/configure.in index f262d7d45..d9df7c5f7 100644 --- a/newlib/libc/configure.in +++ b/newlib/libc/configure.in @@ -27,6 +27,16 @@ AC_ARG_ENABLE(newlib_wide_orient, esac],[newlib_wide_orient=yes]) AM_CONDITIONAL(NEWLIB_WIDE_ORIENT, test x$newlib_wide_orient = xyes) +dnl Support --enable-newlib-nano-malloc used by libc/stdlib +AC_ARG_ENABLE(newlib_nano_malloc, +[ --enable-newlib-nano-malloc Use small-footprint nano-malloc implementation], +[case "${enableval}" in + yes) newlib_nano_malloc=yes ;; + no) newlib_nano_malloc=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for newlib-nano-malloc) ;; + esac],[newlib_nano_malloc=no]) +AM_CONDITIONAL(NEWLIB_NANO_MALLOC, test x$newlib_nano_malloc = xyes) + NEWLIB_CONFIGURE(..) dnl We have to enable libtool after NEWLIB_CONFIGURE because if we try and diff --git a/newlib/libc/stdlib/Makefile.am b/newlib/libc/stdlib/Makefile.am index 38120e6e2..22fedcc84 100644 --- a/newlib/libc/stdlib/Makefile.am +++ b/newlib/libc/stdlib/Makefile.am @@ -66,12 +66,40 @@ GENERAL_SOURCES += \ wcstold.c endif # HAVE_LONG_DOUBLE +if NEWLIB_NANO_MALLOC +MALIGNR=nano-malignr +MALLOPTR=nano-malloptr +PVALLOCR=nano-pvallocr +VALLOCR=nano-vallocr +FREER=nano-freer +REALLOCR=nano-reallocr +CALLOCR=nano-callocr +CFREER=nano-cfreer +MALLINFOR=nano-mallinfor +MALLSTATSR=nano-mallstatsr +MSIZER=nano-msizer +MALLOCR=nano-mallocr +else +MALIGNR=malignr +MALLOPTR=malloptr +PVALLOCR=pvallocr +VALLOCR=vallocr +FREER=freer +REALLOCR=reallocr +CALLOCR=callocr +CFREER=cfreer +MALLINFOR=mallinfor +MALLSTATSR=mallstatsr +MSIZER=msizer +MALLOCR=mallocr +endif + EXTENDED_SOURCES = \ cxa_atexit.c \ cxa_finalize.c \ drand48.c \ - ecvtbuf.c \ - efgcvt.c \ + ecvtbuf.c \ + efgcvt.c \ erand48.c \ jrand48.c \ lcong48.c \ @@ -115,10 +143,10 @@ ELIX_2_SOURCES = \ wctob.c ELIX_2_OBJS = \ - $(lpfx)malignr.$(oext) \ - $(lpfx)malloptr.$(oext) \ - $(lpfx)pvallocr.$(oext) \ - $(lpfx)vallocr.$(oext) + $(lpfx)$(MALIGNR).$(oext) \ + $(lpfx)$(MALLOPTR).$(oext) \ + $(lpfx)$(PVALLOCR).$(oext) \ + $(lpfx)$(VALLOCR).$(oext) ELIX_3_SOURCES = \ putenv.c \ @@ -148,10 +176,10 @@ endif endif # Because of how libtool moves objects around, mallocr must be built last. -LIBADD_OBJS = $(lpfx)freer.$(oext) $(lpfx)reallocr.$(oext) \ - $(lpfx)callocr.$(oext) $(lpfx)cfreer.$(oext) \ - $(lpfx)mallinfor.$(oext) $(lpfx)mallstatsr.$(oext) \ - $(lpfx)msizer.$(oext) $(lpfx)mallocr.$(oext) +LIBADD_OBJS = $(lpfx)$(FREER).$(oext) $(lpfx)$(REALLOCR).$(oext) \ + $(lpfx)$(CALLOCR).$(oext) $(lpfx)$(CFREER).$(oext) \ + $(lpfx)$(MALLINFOR).$(oext) $(lpfx)$(MALLSTATSR).$(oext) \ + $(lpfx)$(MSIZER).$(oext) $(lpfx)$(MALLOCR).$(oext) libstdlib_la_LDFLAGS = -Xcompiler -nostdlib @@ -176,41 +204,41 @@ include $(srcdir)/../../Makefile.shared MALLOC_COMPILE = $(LIB_COMPILE) -DINTERNAL_NEWLIB -$(lpfx)mallocr.$(oext): mallocr.c - $(MALLOC_COMPILE) -DDEFINE_MALLOC -c $(srcdir)/mallocr.c -o $@ +$(lpfx)$(MALLOCR).$(oext): $(MALLOCR).c + $(MALLOC_COMPILE) -DDEFINE_MALLOC -c $(srcdir)/$(MALLOCR).c -o $@ -$(lpfx)freer.$(oext): mallocr.c - $(MALLOC_COMPILE) -DDEFINE_FREE -c $(srcdir)/mallocr.c -o $@ +$(lpfx)$(FREER).$(oext): $(MALLOCR).c + $(MALLOC_COMPILE) -DDEFINE_FREE -c $(srcdir)/$(MALLOCR).c -o $@ -$(lpfx)reallocr.$(oext): mallocr.c - $(MALLOC_COMPILE) -DDEFINE_REALLOC -c $(srcdir)/mallocr.c -o $@ +$(lpfx)$(REALLOCR).$(oext): $(MALLOCR).c + $(MALLOC_COMPILE) -DDEFINE_REALLOC -c $(srcdir)/$(MALLOCR).c -o $@ -$(lpfx)callocr.$(oext): mallocr.c - $(MALLOC_COMPILE) -DDEFINE_CALLOC -c $(srcdir)/mallocr.c -o $@ +$(lpfx)$(CALLOCR).$(oext): $(MALLOCR).c + $(MALLOC_COMPILE) -DDEFINE_CALLOC -c $(srcdir)/$(MALLOCR).c -o $@ -$(lpfx)cfreer.$(oext): mallocr.c - $(MALLOC_COMPILE) -DDEFINE_CFREE -c $(srcdir)/mallocr.c -o $@ +$(lpfx)$(CFREER).$(oext): $(MALLOCR).c + $(MALLOC_COMPILE) -DDEFINE_CFREE -c $(srcdir)/$(MALLOCR).c -o $@ -$(lpfx)malignr.$(oext): mallocr.c - $(MALLOC_COMPILE) -DDEFINE_MEMALIGN -c $(srcdir)/mallocr.c -o $@ +$(lpfx)$(MALIGNR).$(oext): $(MALLOCR).c + $(MALLOC_COMPILE) -DDEFINE_MEMALIGN -c $(srcdir)/$(MALLOCR).c -o $@ -$(lpfx)vallocr.$(oext): mallocr.c - $(MALLOC_COMPILE) -DDEFINE_VALLOC -c $(srcdir)/mallocr.c -o $@ +$(lpfx)$(VALLOCR).$(oext): $(MALLOCR).c + $(MALLOC_COMPILE) -DDEFINE_VALLOC -c $(srcdir)/$(MALLOCR).c -o $@ -$(lpfx)pvallocr.$(oext): mallocr.c - $(MALLOC_COMPILE) -DDEFINE_PVALLOC -c $(srcdir)/mallocr.c -o $@ +$(lpfx)$(PVALLOCR).$(oext): $(MALLOCR).c + $(MALLOC_COMPILE) -DDEFINE_PVALLOC -c $(srcdir)/$(MALLOCR).c -o $@ -$(lpfx)mallinfor.$(oext): mallocr.c - $(MALLOC_COMPILE) -DDEFINE_MALLINFO -c $(srcdir)/mallocr.c -o $@ +$(lpfx)$(MALLINFOR).$(oext): $(MALLOCR).c + $(MALLOC_COMPILE) -DDEFINE_MALLINFO -c $(srcdir)/$(MALLOCR).c -o $@ -$(lpfx)mallstatsr.$(oext): mallocr.c - $(MALLOC_COMPILE) -DDEFINE_MALLOC_STATS -c $(srcdir)/mallocr.c -o $@ +$(lpfx)$(MALLSTATSR).$(oext): $(MALLOCR).c + $(MALLOC_COMPILE) -DDEFINE_MALLOC_STATS -c $(srcdir)/$(MALLOCR).c -o $@ -$(lpfx)msizer.$(oext): mallocr.c - $(MALLOC_COMPILE) -DDEFINE_MALLOC_USABLE_SIZE -c $(srcdir)/mallocr.c -o $@ +$(lpfx)$(MSIZER).$(oext): $(MALLOCR).c + $(MALLOC_COMPILE) -DDEFINE_MALLOC_USABLE_SIZE -c $(srcdir)/$(MALLOCR).c -o $@ -$(lpfx)malloptr.$(oext): mallocr.c - $(MALLOC_COMPILE) -DDEFINE_MALLOPT -c $(srcdir)/mallocr.c -o $@ +$(lpfx)$(MALLOPTR).$(oext): $(MALLOCR).c + $(MALLOC_COMPILE) -DDEFINE_MALLOPT -c $(srcdir)/$(MALLOCR).c -o $@ CHEWOUT_FILES= \ _Exit.def \ @@ -234,7 +262,7 @@ CHEWOUT_FILES= \ llabs.def \ lldiv.def \ malloc.def \ - mallocr.def \ + $(MALLOCR).def \ mblen.def \ mbsnrtowcs.def \ mbstowcs.def \ diff --git a/newlib/libc/stdlib/Makefile.in b/newlib/libc/stdlib/Makefile.in index 33e5f260d..319079dd5 100644 --- a/newlib/libc/stdlib/Makefile.in +++ b/newlib/libc/stdlib/Makefile.in @@ -361,12 +361,36 @@ GENERAL_SOURCES = __adjust.c __atexit.c __call_atexit.c __exp10.c \ reallocf.c sb_charsets.c strtod.c strtol.c strtoul.c wcstod.c \ wcstol.c wcstoul.c wcstombs.c wcstombs_r.c wctomb.c wctomb_r.c \ $(am__append_1) +@NEWLIB_NANO_MALLOC_FALSE@MALIGNR = malignr +@NEWLIB_NANO_MALLOC_TRUE@MALIGNR = nano-malignr +@NEWLIB_NANO_MALLOC_FALSE@MALLOPTR = malloptr +@NEWLIB_NANO_MALLOC_TRUE@MALLOPTR = nano-malloptr +@NEWLIB_NANO_MALLOC_FALSE@PVALLOCR = pvallocr +@NEWLIB_NANO_MALLOC_TRUE@PVALLOCR = nano-pvallocr +@NEWLIB_NANO_MALLOC_FALSE@VALLOCR = vallocr +@NEWLIB_NANO_MALLOC_TRUE@VALLOCR = nano-vallocr +@NEWLIB_NANO_MALLOC_FALSE@FREER = freer +@NEWLIB_NANO_MALLOC_TRUE@FREER = nano-freer +@NEWLIB_NANO_MALLOC_FALSE@REALLOCR = reallocr +@NEWLIB_NANO_MALLOC_TRUE@REALLOCR = nano-reallocr +@NEWLIB_NANO_MALLOC_FALSE@CALLOCR = callocr +@NEWLIB_NANO_MALLOC_TRUE@CALLOCR = nano-callocr +@NEWLIB_NANO_MALLOC_FALSE@CFREER = cfreer +@NEWLIB_NANO_MALLOC_TRUE@CFREER = nano-cfreer +@NEWLIB_NANO_MALLOC_FALSE@MALLINFOR = mallinfor +@NEWLIB_NANO_MALLOC_TRUE@MALLINFOR = nano-mallinfor +@NEWLIB_NANO_MALLOC_FALSE@MALLSTATSR = mallstatsr +@NEWLIB_NANO_MALLOC_TRUE@MALLSTATSR = nano-mallstatsr +@NEWLIB_NANO_MALLOC_FALSE@MSIZER = msizer +@NEWLIB_NANO_MALLOC_TRUE@MSIZER = nano-msizer +@NEWLIB_NANO_MALLOC_FALSE@MALLOCR = mallocr +@NEWLIB_NANO_MALLOC_TRUE@MALLOCR = nano-mallocr EXTENDED_SOURCES = \ cxa_atexit.c \ cxa_finalize.c \ drand48.c \ - ecvtbuf.c \ - efgcvt.c \ + ecvtbuf.c \ + efgcvt.c \ erand48.c \ jrand48.c \ lcong48.c \ @@ -410,10 +434,10 @@ ELIX_2_SOURCES = \ wctob.c ELIX_2_OBJS = \ - $(lpfx)malignr.$(oext) \ - $(lpfx)malloptr.$(oext) \ - $(lpfx)pvallocr.$(oext) \ - $(lpfx)vallocr.$(oext) + $(lpfx)$(MALIGNR).$(oext) \ + $(lpfx)$(MALLOPTR).$(oext) \ + $(lpfx)$(PVALLOCR).$(oext) \ + $(lpfx)$(VALLOCR).$(oext) ELIX_3_SOURCES = \ putenv.c \ @@ -434,10 +458,10 @@ ELIX_4_SOURCES = \ @ELIX_LEVEL_1_TRUE@ELIX_OBJS = # Because of how libtool moves objects around, mallocr must be built last. -LIBADD_OBJS = $(lpfx)freer.$(oext) $(lpfx)reallocr.$(oext) \ - $(lpfx)callocr.$(oext) $(lpfx)cfreer.$(oext) \ - $(lpfx)mallinfor.$(oext) $(lpfx)mallstatsr.$(oext) \ - $(lpfx)msizer.$(oext) $(lpfx)mallocr.$(oext) +LIBADD_OBJS = $(lpfx)$(FREER).$(oext) $(lpfx)$(REALLOCR).$(oext) \ + $(lpfx)$(CALLOCR).$(oext) $(lpfx)$(CFREER).$(oext) \ + $(lpfx)$(MALLINFOR).$(oext) $(lpfx)$(MALLSTATSR).$(oext) \ + $(lpfx)$(MSIZER).$(oext) $(lpfx)$(MALLOCR).$(oext) libstdlib_la_LDFLAGS = -Xcompiler -nostdlib @USE_LIBTOOL_TRUE@noinst_LTLIBRARIES = libstdlib.la @@ -476,7 +500,7 @@ CHEWOUT_FILES = \ llabs.def \ lldiv.def \ malloc.def \ - mallocr.def \ + $(MALLOCR).def \ mblen.def \ mbsnrtowcs.def \ mbstowcs.def \ @@ -1388,41 +1412,41 @@ objectlist.awk.in: $(noinst_LTLIBRARIES) echo $$i `pwd`/$$i >> objectlist.awk.in ; \ done -$(lpfx)mallocr.$(oext): mallocr.c - $(MALLOC_COMPILE) -DDEFINE_MALLOC -c $(srcdir)/mallocr.c -o $@ +$(lpfx)$(MALLOCR).$(oext): $(MALLOCR).c + $(MALLOC_COMPILE) -DDEFINE_MALLOC -c $(srcdir)/$(MALLOCR).c -o $@ -$(lpfx)freer.$(oext): mallocr.c - $(MALLOC_COMPILE) -DDEFINE_FREE -c $(srcdir)/mallocr.c -o $@ +$(lpfx)$(FREER).$(oext): $(MALLOCR).c + $(MALLOC_COMPILE) -DDEFINE_FREE -c $(srcdir)/$(MALLOCR).c -o $@ -$(lpfx)reallocr.$(oext): mallocr.c - $(MALLOC_COMPILE) -DDEFINE_REALLOC -c $(srcdir)/mallocr.c -o $@ +$(lpfx)$(REALLOCR).$(oext): $(MALLOCR).c + $(MALLOC_COMPILE) -DDEFINE_REALLOC -c $(srcdir)/$(MALLOCR).c -o $@ -$(lpfx)callocr.$(oext): mallocr.c - $(MALLOC_COMPILE) -DDEFINE_CALLOC -c $(srcdir)/mallocr.c -o $@ +$(lpfx)$(CALLOCR).$(oext): $(MALLOCR).c + $(MALLOC_COMPILE) -DDEFINE_CALLOC -c $(srcdir)/$(MALLOCR).c -o $@ -$(lpfx)cfreer.$(oext): mallocr.c - $(MALLOC_COMPILE) -DDEFINE_CFREE -c $(srcdir)/mallocr.c -o $@ +$(lpfx)$(CFREER).$(oext): $(MALLOCR).c + $(MALLOC_COMPILE) -DDEFINE_CFREE -c $(srcdir)/$(MALLOCR).c -o $@ -$(lpfx)malignr.$(oext): mallocr.c - $(MALLOC_COMPILE) -DDEFINE_MEMALIGN -c $(srcdir)/mallocr.c -o $@ +$(lpfx)$(MALIGNR).$(oext): $(MALLOCR).c + $(MALLOC_COMPILE) -DDEFINE_MEMALIGN -c $(srcdir)/$(MALLOCR).c -o $@ -$(lpfx)vallocr.$(oext): mallocr.c - $(MALLOC_COMPILE) -DDEFINE_VALLOC -c $(srcdir)/mallocr.c -o $@ +$(lpfx)$(VALLOCR).$(oext): $(MALLOCR).c + $(MALLOC_COMPILE) -DDEFINE_VALLOC -c $(srcdir)/$(MALLOCR).c -o $@ -$(lpfx)pvallocr.$(oext): mallocr.c - $(MALLOC_COMPILE) -DDEFINE_PVALLOC -c $(srcdir)/mallocr.c -o $@ +$(lpfx)$(PVALLOCR).$(oext): $(MALLOCR).c + $(MALLOC_COMPILE) -DDEFINE_PVALLOC -c $(srcdir)/$(MALLOCR).c -o $@ -$(lpfx)mallinfor.$(oext): mallocr.c - $(MALLOC_COMPILE) -DDEFINE_MALLINFO -c $(srcdir)/mallocr.c -o $@ +$(lpfx)$(MALLINFOR).$(oext): $(MALLOCR).c + $(MALLOC_COMPILE) -DDEFINE_MALLINFO -c $(srcdir)/$(MALLOCR).c -o $@ -$(lpfx)mallstatsr.$(oext): mallocr.c - $(MALLOC_COMPILE) -DDEFINE_MALLOC_STATS -c $(srcdir)/mallocr.c -o $@ +$(lpfx)$(MALLSTATSR).$(oext): $(MALLOCR).c + $(MALLOC_COMPILE) -DDEFINE_MALLOC_STATS -c $(srcdir)/$(MALLOCR).c -o $@ -$(lpfx)msizer.$(oext): mallocr.c - $(MALLOC_COMPILE) -DDEFINE_MALLOC_USABLE_SIZE -c $(srcdir)/mallocr.c -o $@ +$(lpfx)$(MSIZER).$(oext): $(MALLOCR).c + $(MALLOC_COMPILE) -DDEFINE_MALLOC_USABLE_SIZE -c $(srcdir)/$(MALLOCR).c -o $@ -$(lpfx)malloptr.$(oext): mallocr.c - $(MALLOC_COMPILE) -DDEFINE_MALLOPT -c $(srcdir)/mallocr.c -o $@ +$(lpfx)$(MALLOPTR).$(oext): $(MALLOCR).c + $(MALLOC_COMPILE) -DDEFINE_MALLOPT -c $(srcdir)/$(MALLOCR).c -o $@ .c.def: $(CHEW) < $< > $*.def 2> $*.ref diff --git a/newlib/libc/stdlib/nano-mallocr.c b/newlib/libc/stdlib/nano-mallocr.c new file mode 100644 index 000000000..e0a919590 --- /dev/null +++ b/newlib/libc/stdlib/nano-mallocr.c @@ -0,0 +1,581 @@ +/* + * Copyright (c) 2012, 2013 ARM Ltd + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the company may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Implementation of <> <> <> <>, optional + * as to be reenterable. + * + * Interface documentation refer to malloc.c. + */ + +#include +#include +#include + +#if DEBUG +#include +#else +#define assert(x) ((void)0) +#endif + +#ifndef MAX +#define MAX(a,b) ((a) >= (b) ? (a) : (b)) +#endif + +#ifdef INTERNAL_NEWLIB + +#include +#include + +#define RARG struct _reent *reent_ptr, +#define RONEARG struct _reent *reent_ptr +#define RCALL reent_ptr, + +/* Disable MALLOC_LOCK so far. So it won't be thread safe */ +#define MALLOC_LOCK /*__malloc_lock(reent_ptr) */ +#define MALLOC_UNLOCK /*__malloc_unlock(reent_ptr) */ + +#define RERRNO reent_ptr->_errno + +#define nano_malloc _malloc_r +#define nano_free _free_r +#define nano_realloc _realloc_r +#define nano_memalign _memalign_r +#define nano_valloc _valloc_r +#define nano_pvalloc _pvalloc_r +#define nano_calloc _calloc_r +#define nano_cfree _cfree_r +#define nano_malloc_usable_size _malloc_usable_size_r +#define nano_malloc_stats _malloc_stats_r +#define nano_mallinfo _mallinfo_r +#define nano_allopt _mallopt_r + +#else /* ! INTERNAL_NEWLIB */ + +#define RARG +#define RONEARG +#define RCALL +#define MALLOC_LOCK +#define MALLOC_UNLOCK +#define RERRNO errno + +#define nano_malloc malloc +#define nano_free free +#define nano_realloc realloc +#define nano_memalign memalign +#define nano_valloc valloc +#define nano_pvalloc pvalloc +#define nano_calloc calloc +#define nano_cfree cfree +#define nano_malloc_usable_size malloc_usable_size +#define nano_malloc_stats malloc_stats +#define nano_mallinfo mallinfo +#define nano_allopt mallopt +#endif /* ! INTERNAL_NEWLIB */ + +/* Define free_list as internal name to avoid conflict with user names */ +#define free_list __malloc_free_list + +#define ALIGN_TO(size, align) \ + (((size) + (align) -1) & ~((align) -1)) + +/* Alignment of allocated block */ +#define MALLOC_ALIGN (8U) +#define CHUNK_ALIGN (sizeof(void*)) +#define MALLOC_PADDING ((MAX(MALLOC_ALIGN, CHUNK_ALIGN)) - CHUNK_ALIGN) + +/* as well as the minimal allocation size + * to hold a free pointer */ +#define MALLOC_MINSIZE (sizeof(void *)) +#define MALLOC_PAGE_ALIGN (0x1000) +#define MAX_ALLOC_SIZE (0x80000000U) + +typedef size_t malloc_size_t; + +typedef struct malloc_chunk +{ + /* ------------------ + * chunk->| size (4 bytes) | + * ------------------ + * | Padding for | + * | alignment | + * | holding neg | + * | offset to size | + * ------------------ + * mem_ptr->| point to next | + * | free when freed| + * | or data load | + * | when allocated | + * ------------------ + */ + /* size of the allocated payload area, including size before + CHUNK_OFFSET */ + int size; + + /* since here, the memory is either the next free block, or data load */ + struct malloc_chunk * next; +}chunk; + +#define CHUNK_OFFSET ((malloc_size_t)(&(((struct malloc_chunk *)0)->next))) + +/* size of smallest possible chunk. A memory piece smaller than this size + * won't be able to create a chunk */ +#define MALLOC_MINCHUNK (CHUNK_OFFSET + MALLOC_PADDING + MALLOC_MINSIZE) + +static chunk * get_chunk_from_ptr(void * ptr) +{ + chunk * c = (chunk *)((char *)ptr - CHUNK_OFFSET); + /* Skip the padding area */ + if (c->size < 0) c = (chunk *)((char *)c + c->size); + return c; +} + +#ifdef DEFINE_MALLOC +chunk * free_list = NULL; + +/** Function sbrk_aligned + * Algorithm: + * Use sbrk() to obtain more memory and ensure it is CHUNK_ALIGN aligned + * Optimise for the case that it is already aligned - only ask for extra + * padding after we know we need it + */ +static void* sbrk_aligned(RARG malloc_size_t s) +{ + char *p, *align_p; + + p = _sbrk_r(RCALL s); + + /* sbrk returns -1 if fail to allocate */ + if (p == (void *)-1) + return p; + + align_p = (char*)ALIGN_TO((unsigned long)p, CHUNK_ALIGN); + if (align_p != p) + { + /* p is not aligned, ask for a few more bytes so that we have s + * bytes reserved from align_p. */ + p = _sbrk_r(RCALL align_p - p); + if (p == (void *)-1) + return p; + } + return align_p; +} + +/** Function nano_malloc + * Algorithm: + * Walk through the free list to find the first match. If fails to find + * one, call sbrk to allocate a new chunk. + */ +void * nano_malloc(RARG malloc_size_t s) +{ + chunk *p, *r; + char * ptr, * align_ptr; + int offset; + + malloc_size_t alloc_size; + + alloc_size = ALIGN_TO(s, CHUNK_ALIGN); /* size of aligned data load */ + alloc_size += MALLOC_PADDING; /* padding */ + alloc_size += CHUNK_OFFSET; /* size of chunk head */ + alloc_size = MAX(alloc_size, MALLOC_MINCHUNK); + + if (alloc_size >= MAX_ALLOC_SIZE || alloc_size < s) + { + RERRNO = ENOMEM; + return NULL; + } + + MALLOC_LOCK; + + p = free_list; + r = p; + + while (r) + { + int rem = r->size - alloc_size; + if (rem >= 0) + { + if (rem >= MALLOC_MINCHUNK) + { + /* Find a chunk that much larger than required size, break + * it into two chunks and return the second one */ + r->size = rem; + r = (chunk *)((char *)r + rem); + r->size = alloc_size; + } + /* Find a chunk that is exactly the size or slightly bigger + * than requested size, just return this chunk */ + else if (p == r) + { + /* Now it implies p==r==free_list. Move the free_list + * to next chunk */ + free_list = r->next; + } + else + { + /* Normal case. Remove it from free_list */ + p->next = r->next; + } + break; + } + p=r; + r=r->next; + } + + /* Failed to find a appropriate chunk. Ask for more memory */ + if (r == NULL) + { + r = sbrk_aligned(RCALL alloc_size); + + /* sbrk returns -1 if fail to allocate */ + if (r == (void *)-1) + { + RERRNO = ENOMEM; + MALLOC_UNLOCK; + return NULL; + } + r->size = alloc_size; + } + MALLOC_UNLOCK; + + ptr = (char *)r + CHUNK_OFFSET; + + align_ptr = (char *)ALIGN_TO((unsigned long)ptr, MALLOC_ALIGN); + offset = align_ptr - ptr; + + if (offset) + { + *(int *)((char *)r + offset) = -offset; + } + + assert(align_ptr + size <= (char *)r + alloc_size); + return align_ptr; +} +#endif /* DEFINE_MALLOC */ + +#ifdef DEFINE_FREE +#define MALLOC_CHECK_DOUBLE_FREE + +extern chunk * free_list; +/** Function nano_free + * Implementation of libc free. + * Algorithm: + * Maintain a global free chunk single link list, headed by global + * variable free_list. + * When free, insert the to-be-freed chunk into free list. The place to + * insert should make sure all chunks are sorted by address from low to + * high. Then merge with neighbor chunks if adjacent. + */ +void nano_free (RARG void * free_p) +{ + chunk * p_to_free; + chunk * p, * q; + + if (free_p == NULL) return; + + p_to_free = get_chunk_from_ptr(free_p); + + MALLOC_LOCK; + if (free_list == NULL) + { + /* Set first free list element */ + p_to_free->next = free_list; + free_list = p_to_free; + MALLOC_UNLOCK; + return; + } + + if (p_to_free < free_list) + { + if ((char *)p_to_free + p_to_free->size == (char *)free_list) + { + /* Chunk to free is just before the first element of + * free list */ + p_to_free->size += free_list->size; + p_to_free->next = free_list->next; + } + else + { + /* Insert before current free_list */ + p_to_free->next = free_list; + } + free_list = p_to_free; + MALLOC_UNLOCK; + return; + } + + q = free_list; + /* Walk through the free list to find the place for insert. */ + do + { + p = q; + q = q->next; + } while (q && q <= p_to_free); + + /* Now p <= p_to_free and either q == NULL or q > p_to_free + * Try to merge with chunks immediately before/after it. */ + + if ((char *)p + p->size == (char *)p_to_free) + { + /* Chunk to be freed is adjacent + * to a free chunk before it */ + p->size += p_to_free->size; + /* If the merged chunk is also adjacent + * to the chunk after it, merge again */ + if ((char *)p + p->size == (char *) q) + { + p->size += q->size; + p->next = q->next; + } + } +#ifdef MALLOC_CHECK_DOUBLE_FREE + else if ((char *)p + p->size > (char *)p_to_free) + { + /* Report double free fault */ + RERRNO = ENOMEM; + MALLOC_UNLOCK; + return; + } +#endif + else if ((char *)p_to_free + p_to_free->size == (char *) q) + { + /* Chunk to be freed is adjacent + * to a free chunk after it */ + p_to_free->size += q->size; + p_to_free->next = q->next; + p->next = p_to_free; + } + else + { + /* Not adjacent to any chunk. Just insert it. Resulting + * a fragment. */ + p_to_free->next = q; + p->next = p_to_free; + } + MALLOC_UNLOCK; +} +#endif /* DEFINE_FREE */ + +#ifdef DEFINE_CFREE +void nano_free (RARG void * free_p); + +void nano_cfree(RARG void * ptr) +{ + nano_free(RCALL ptr); +} +#endif /* DEFINE_CFREE */ + +#ifdef DEFINE_CALLOC +void * nano_malloc(RARG malloc_size_t s); + +/* Function nano_calloc + * Implement calloc simply by calling malloc and set zero */ +void * nano_calloc(RARG malloc_size_t n, malloc_size_t elem) +{ + void * mem = nano_malloc(RCALL n * elem); + if (mem != NULL) memset(mem, 0, n * elem); + return mem; +} +#endif /* DEFINE_CALLOC */ + +#ifdef DEFINE_REALLOC +void * nano_malloc(RARG malloc_size_t s); +void nano_free (RARG void * free_p); +malloc_size_t nano_malloc_usable_size(RARG void * ptr); + +/* Function nano_realloc + * Implement realloc by malloc + memcpy */ +void * nano_realloc(RARG void * ptr, malloc_size_t size) +{ + void * mem; + chunk * p_to_realloc; + + if (ptr == NULL) return nano_malloc(RCALL size); + + if (size == 0) + { + nano_free(RCALL ptr); + return NULL; + } + + /* TODO: There is chance to shrink the chunk if newly requested + * size is much small */ + if (nano_malloc_usable_size(RCALL ptr) >= size) + return ptr; + + mem = nano_malloc(RCALL size); + if (mem != NULL) + { + memcpy(mem, ptr, size); + nano_free(RCALL ptr); + } + return mem; +} +#endif /* DEFINE_REALLOC */ + +#ifdef DEFINE_MALLINFO +struct mallinfo +{ + int arena; /* total space allocated from system */ + int ordblks; /* number of non-inuse chunks */ + int smblks; /* unused -- always zero */ + int hblks; /* number of mmapped regions */ + int hblkhd; /* total space in mmapped regions */ + int usmblks; /* unused -- always zero */ + int fsmblks; /* unused -- always zero */ + int uordblks; /* total allocated space */ + int fordblks; /* total non-inuse space */ + int keepcost; /* top-most, releasable (via malloc_trim) space */ +}; + +static struct mallinfo current_mallinfo={0,0,0,0,0,0,0,0,0,0}; + +struct mallinfo nano_mallinfo(RONEARG) +{ + return current_mallinfo; +} + +#endif /* DEFINE_MALLINFO */ + +#ifdef DEFINE_MALLOC_STATS +void nano_malloc_stats(RONEARG) +{ +} +#endif /* DEFINE_MALLOC_STATS */ + +#ifdef DEFINE_MALLOC_USABLE_SIZE +malloc_size_t nano_malloc_usable_size(RARG void * ptr) +{ + chunk * c = (chunk *)((char *)ptr - CHUNK_OFFSET); + int size_or_offset = c->size; + + if (size_or_offset < 0) + { + /* Padding is used. Excluding the padding size */ + c = (chunk *)((char *)c + c->size); + return c->size - CHUNK_OFFSET + size_or_offset; + } + return c->size - CHUNK_OFFSET; +} +#endif /* DEFINE_MALLOC_USABLE_SIZE */ + +#ifdef DEFINE_MEMALIGN +void * nano_malloc(RARG malloc_size_t s); + +/* Function nano_memalign + * Allocate memory block aligned at specific boundary. + * align: required alignment. Must be power of 2. Return NULL + * if not power of 2. Undefined behavior is bigger than + * pointer value range. + * s: required size. + * Return: allocated memory pointer aligned to align + * Algorithm: Malloc a big enough block, padding pointer to aligned + * address, then truncate and free the tail if too big. + * Record the offset of align pointer and original pointer + * in the padding area. + */ +void * nano_memalign(RARG size_t align, size_t s) +{ + chunk * chunk_p; + malloc_size_t size_allocated, offset, ma_size, size_with_padding; + char * allocated, * aligned_p; + + /* Return NULL if align isn't power of 2 */ + if ((align & (align-1)) != 0) return NULL; + + align = MAX(align, MALLOC_ALIGN); + ma_size = ALIGN_TO(MAX(s, MALLOC_MINSIZE), CHUNK_ALIGN); + size_with_padding = ma_size + align - MALLOC_ALIGN; + + allocated = nano_malloc(RCALL size_with_padding); + if (allocated == NULL) return NULL; + + chunk_p = get_chunk_from_ptr(allocated); + aligned_p = (char *)ALIGN_TO( + (unsigned long)((char *)chunk_p + CHUNK_OFFSET), + (unsigned long)align); + offset = aligned_p - ((char *)chunk_p + CHUNK_OFFSET); + + if (offset) + { + if (offset >= MALLOC_MINCHUNK) + { + /* Padding is too large, free it */ + chunk * front_chunk = chunk_p; + chunk_p = (chunk *)((char *)chunk_p + offset); + chunk_p->size = front_chunk->size - offset; + front_chunk->size = offset; + nano_free(RCALL (char *)front_chunk + CHUNK_OFFSET); + } + else + { + /* Padding is used. Need to set a jump offset for aligned pointer + * to get back to chunk head */ + assert(offset >= sizeof(int)); + *(int *)((char *)chunk_p + offset) = -offset; + } + } + + size_allocated = chunk_p->size; + if ((char *)chunk_p + size_allocated > + (aligned_p + ma_size + MALLOC_MINCHUNK)) + { + /* allocated much more than what's required for padding, free + * tail part */ + chunk * tail_chunk = (chunk *)(aligned_p + ma_size); + chunk_p->size = aligned_p + ma_size - (char *)chunk_p; + tail_chunk->size = size_allocated - chunk_p->size; + nano_free(RCALL (char *)tail_chunk + CHUNK_OFFSET); + } + return aligned_p; +} +#endif /* DEFINE_MEMALIGN */ + +#ifdef DEFINE_MALLOPT +int nano_mallopt(RARG int parameter_number, int parameter_value) +{ + return 0; +} +#endif /* DEFINE_MALLOPT */ + +#ifdef DEFINE_VALLOC +void * nano_memalign(RARG size_t align, size_t s); + +void * nano_valloc(RARG size_t s) +{ + return nano_memalign(RCALL MALLOC_PAGE_ALIGN, s); +} +#endif /* DEFINE_VALLOC */ + +#ifdef DEFINE_PVALLOC +void * nano_valloc(RARG size_t s); + +void * nano_pvalloc(RARG size_t s) +{ + return nano_valloc(RCALL ALIGN_TO(s, MALLOC_PAGE_ALIGN)); +} +#endif /* DEFINE_PVALLOC */ -- 2.43.5