From 200f5f1d94809ad782dd59086b8ad3fc9786b9ef Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Mon, 2 Nov 2020 09:54:12 +0000 Subject: [PATCH] added the xma memory manager --- hawk/bin/main.c | 23 +- hawk/lib/Makefile.am | 6 +- hawk/lib/Makefile.in | 61 ++-- hawk/lib/hawk-std.h | 6 + hawk/lib/hawk-xma.h | 243 ++++++++++++++ hawk/lib/mod-hawk.c | 2 + hawk/lib/run.c | 20 +- hawk/lib/std.c | 14 +- hawk/lib/xma.c | 779 +++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 1100 insertions(+), 54 deletions(-) create mode 100644 hawk/lib/hawk-xma.h create mode 100644 hawk/lib/xma.c diff --git a/hawk/bin/main.c b/hawk/bin/main.c index 4ea9ad58..7235f4fb 100644 --- a/hawk/bin/main.c +++ b/hawk/bin/main.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -1026,15 +1027,14 @@ static void print_hawk_rtx_error (hawk_rtx_t* rtx) ); } -#if 0 static void* xma_alloc (hawk_mmgr_t* mmgr, hawk_oow_t size) { - return hawk_xma_alloc (mmgr->ctx, size); + return hawk_xma_alloc(mmgr->ctx, size); } static void* xma_realloc (hawk_mmgr_t* mmgr, void* ptr, hawk_oow_t size) { - return hawk_xma_realloc (mmgr->ctx, ptr, size); + return hawk_xma_realloc(mmgr->ctx, ptr, size); } static void xma_free (hawk_mmgr_t* mmgr, void* ptr) @@ -1050,7 +1050,6 @@ static hawk_mmgr_t xma_mmgr = HAWK_NULL }; - #if defined(HAWK_BUILD_DEBUG) static hawk_uintptr_t debug_mmgr_count = 0; static hawk_uintptr_t debug_mmgr_alloc_count = 0; @@ -1098,8 +1097,6 @@ static hawk_mmgr_t debug_mmgr = }; #endif -#endif - static HAWK_INLINE int execute_hawk (int argc, hawk_bch_t* argv[]) { hawk_t* hawk = HAWK_NULL; @@ -1120,9 +1117,7 @@ static HAWK_INLINE int execute_hawk (int argc, hawk_bch_t* argv[]) /* TODO: change it to support multiple source files */ hawk_parsestd_t psout; -#if 0 - hawk_mmgr_t* mmgr = HAWK_MMGR_GETDFL(); -#endif + hawk_mmgr_t* mmgr = hawk_get_sys_mmgr(); i = process_argv(argc, argv, &arg); if (i <= 0) @@ -1140,7 +1135,6 @@ static HAWK_INLINE int execute_hawk (int argc, hawk_bch_t* argv[]) psout.u.fileb.cmgr = arg.script_cmgr; } -#if 0 #if defined(HAWK_BUILD_DEBUG) if (arg.failmalloc > 0) { @@ -1151,7 +1145,7 @@ static HAWK_INLINE int execute_hawk (int argc, hawk_bch_t* argv[]) #endif if (arg.memlimit > 0) { - xma_mmgr.ctx = hawk_xma_open(HAWK_MMGR_GETDFL(), 0, arg.memlimit); + xma_mmgr.ctx = hawk_xma_open(hawk_get_sys_mmgr(), 0, HAWK_NULL, arg.memlimit); if (xma_mmgr.ctx == HAWK_NULL) { print_error ("cannot open memory heap\n"); @@ -1159,9 +1153,8 @@ static HAWK_INLINE int execute_hawk (int argc, hawk_bch_t* argv[]) } mmgr = &xma_mmgr; } -#endif - hawk = hawk_openstd(0, HAWK_NULL); + hawk = hawk_openstdwithmmgr(mmgr, 0, hawk_get_cmgr_by_id(HAWK_CMGR_UTF8), HAWK_NULL); if (HAWK_UNLIKELY(!hawk)) { print_error ("cannot open hawk\n"); @@ -1252,7 +1245,7 @@ static HAWK_INLINE int execute_hawk (int argc, hawk_bch_t* argv[]) if (apply_fs_and_gvs_to_rtx(rtx, &arg) <= -1) { - print_hawk_error (hawk); + print_hawk_rtx_error (hawk); goto oops; } @@ -1300,9 +1293,7 @@ oops: if (rtx) hawk_rtx_close (rtx); if (hawk) hawk_close (hawk); -#if 0 if (xma_mmgr.ctx) hawk_xma_close (xma_mmgr.ctx); -#endif freearg (&arg); #if defined(HAWK_BUILD_DEBUG) diff --git a/hawk/lib/Makefile.am b/hawk/lib/Makefile.am index 71aeecdb..67c58cd2 100644 --- a/hawk/lib/Makefile.am +++ b/hawk/lib/Makefile.am @@ -50,7 +50,8 @@ pkginclude_HEADERS = \ hawk-utl.h \ hawk-std.h \ hawk-tre.h \ - hawk-unpack.h + hawk-unpack.h \ + hawk-xma.h ################################################## @@ -121,7 +122,8 @@ libhawk_la_SOURCES = \ utl-sys.c \ utl.c \ val-prv.h \ - val.c + val.c \ + xma.c libhawk_la_SOURCES += \ hawk-cli.h \ diff --git a/hawk/lib/Makefile.in b/hawk/lib/Makefile.in index f3d5f09f..03896d18 100644 --- a/hawk/lib/Makefile.in +++ b/hawk/lib/Makefile.in @@ -216,21 +216,22 @@ libhawk_sys_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ am__libhawk_la_SOURCES_DIST = hawk.h hawk-arr.h hawk-chr.h hawk-cmn.h \ hawk-dir.h hawk-ecs.h hawk-fmt.h hawk-gem.h hawk-htb.h \ hawk-map.h hawk-rbt.h hawk-pack1.h hawk-utl.h hawk-std.h \ - hawk-tre.h hawk-unpack.h Hawk.hpp HawkStd.hpp arr.c chr.c \ - dir.c ecs-imp.h ecs.c err-prv.h err.c err-sys.c fmt-imp.h \ - fmt.c fnc-prv.h fnc.c htb.c gem.c gem-skad.c gem-nwif.c \ - gem-nwif2.c hawk-prv.h hawk.c idmap-imp.h mb8.c misc-prv.h \ - misc.c parse-prv.h parse.c rbt.c rec.c rio-prv.h rio.c \ - run-prv.h run.c tre-prv.h tre-ast.c tre-ast.h tre-compile.c \ - tre-compile.h tre-match-bt.c tre-match-pa.c tre-match-ut.h \ - tre-mem.c tre-mem.h tre-parse.c tre-parse.h tre-stack.h \ - tre-stack.c tre.c tree-prv.h tree.c uch-prop.h uch-case.h \ - utf16.c utf8.c utl-ass.c utl-skad.c utl-skad.h utl-sort.c \ - utl-str.c utl-sys.c utl.c val-prv.h val.c hawk-cli.h \ - hawk-fio.h hawk-mtx.h hawk-pio.h hawk-sio.h hawk-tio.h \ - cli-imp.h cli.c fio.c mtx.c pio.c sio.c syscall.h tio.c \ - std-prv.h std.c Hawk.cpp HawkStd.cpp mod-hawk.c mod-hawk.h \ - mod-math.c mod-math.h mod-str.c mod-str.h mod-sys.c mod-sys.h + hawk-tre.h hawk-unpack.h hawk-xma.h Hawk.hpp HawkStd.hpp arr.c \ + chr.c dir.c ecs-imp.h ecs.c err-prv.h err.c err-sys.c \ + fmt-imp.h fmt.c fnc-prv.h fnc.c htb.c gem.c gem-skad.c \ + gem-nwif.c gem-nwif2.c hawk-prv.h hawk.c idmap-imp.h mb8.c \ + misc-prv.h misc.c parse-prv.h parse.c rbt.c rec.c rio-prv.h \ + rio.c run-prv.h run.c tre-prv.h tre-ast.c tre-ast.h \ + tre-compile.c tre-compile.h tre-match-bt.c tre-match-pa.c \ + tre-match-ut.h tre-mem.c tre-mem.h tre-parse.c tre-parse.h \ + tre-stack.h tre-stack.c tre.c tree-prv.h tree.c uch-prop.h \ + uch-case.h utf16.c utf8.c utl-ass.c utl-skad.c utl-skad.h \ + utl-sort.c utl-str.c utl-sys.c utl.c val-prv.h val.c xma.c \ + hawk-cli.h hawk-fio.h hawk-mtx.h hawk-pio.h hawk-sio.h \ + hawk-tio.h cli-imp.h cli.c fio.c mtx.c pio.c sio.c syscall.h \ + tio.c std-prv.h std.c Hawk.cpp HawkStd.cpp mod-hawk.c \ + mod-hawk.h mod-math.c mod-math.h mod-str.c mod-str.h mod-sys.c \ + mod-sys.h am__objects_1 = am__objects_2 = $(am__objects_1) @ENABLE_CXX_TRUE@am__objects_3 = libhawk_la-Hawk.lo \ @@ -254,10 +255,10 @@ am_libhawk_la_OBJECTS = $(am__objects_2) libhawk_la-arr.lo \ libhawk_la-utf16.lo libhawk_la-utf8.lo libhawk_la-utl-ass.lo \ libhawk_la-utl-skad.lo libhawk_la-utl-sort.lo \ libhawk_la-utl-str.lo libhawk_la-utl-sys.lo libhawk_la-utl.lo \ - libhawk_la-val.lo libhawk_la-cli.lo libhawk_la-fio.lo \ - libhawk_la-mtx.lo libhawk_la-pio.lo libhawk_la-sio.lo \ - libhawk_la-tio.lo libhawk_la-std.lo $(am__objects_3) \ - $(am__objects_4) + libhawk_la-val.lo libhawk_la-xma.lo libhawk_la-cli.lo \ + libhawk_la-fio.lo libhawk_la-mtx.lo libhawk_la-pio.lo \ + libhawk_la-sio.lo libhawk_la-tio.lo libhawk_la-std.lo \ + $(am__objects_3) $(am__objects_4) libhawk_la_OBJECTS = $(am_libhawk_la_OBJECTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) @@ -315,6 +316,7 @@ am__depfiles_remade = ./$(DEPDIR)/libhawk_hawk_la-mod-hawk.Plo \ ./$(DEPDIR)/libhawk_la-utl-str.Plo \ ./$(DEPDIR)/libhawk_la-utl-sys.Plo \ ./$(DEPDIR)/libhawk_la-utl.Plo ./$(DEPDIR)/libhawk_la-val.Plo \ + ./$(DEPDIR)/libhawk_la-xma.Plo \ ./$(DEPDIR)/libhawk_math_la-mod-math.Plo \ ./$(DEPDIR)/libhawk_str_la-mod-str.Plo \ ./$(DEPDIR)/libhawk_sys_la-mod-sys.Plo @@ -371,7 +373,7 @@ am__can_run_installinfo = \ am__pkginclude_HEADERS_DIST = hawk.h hawk-arr.h hawk-chr.h hawk-cmn.h \ hawk-dir.h hawk-ecs.h hawk-fmt.h hawk-gem.h hawk-htb.h \ hawk-map.h hawk-rbt.h hawk-pack1.h hawk-utl.h hawk-std.h \ - hawk-tre.h hawk-unpack.h Hawk.hpp HawkStd.hpp + hawk-tre.h hawk-unpack.h hawk-xma.h Hawk.hpp HawkStd.hpp HEADERS = $(pkginclude_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ $(LISP)hawk-cfg.h.in @@ -579,7 +581,7 @@ CPPFLAGS_ALL_COMMON = \ pkginclude_HEADERS = hawk.h hawk-arr.h hawk-chr.h hawk-cmn.h \ hawk-dir.h hawk-ecs.h hawk-fmt.h hawk-gem.h hawk-htb.h \ hawk-map.h hawk-rbt.h hawk-pack1.h hawk-utl.h hawk-std.h \ - hawk-tre.h hawk-unpack.h $(am__append_7) + hawk-tre.h hawk-unpack.h hawk-xma.h $(am__append_7) pkglib_LTLIBRARIES = libhawk.la $(am__append_15) libhawk_la_SOURCES = $(pkginclude_HEADERS) arr.c chr.c dir.c ecs-imp.h \ ecs.c err-prv.h err.c err-sys.c fmt-imp.h fmt.c fnc-prv.h \ @@ -591,9 +593,10 @@ libhawk_la_SOURCES = $(pkginclude_HEADERS) arr.c chr.c dir.c ecs-imp.h \ tre-parse.h tre-stack.h tre-stack.c tre.c tree-prv.h tree.c \ uch-prop.h uch-case.h utf16.c utf8.c utl-ass.c utl-skad.c \ utl-skad.h utl-sort.c utl-str.c utl-sys.c utl.c val-prv.h \ - val.c hawk-cli.h hawk-fio.h hawk-mtx.h hawk-pio.h hawk-sio.h \ - hawk-tio.h cli-imp.h cli.c fio.c mtx.c pio.c sio.c syscall.h \ - tio.c std-prv.h std.c $(am__append_8) $(am__append_9) + val.c xma.c hawk-cli.h hawk-fio.h hawk-mtx.h hawk-pio.h \ + hawk-sio.h hawk-tio.h cli-imp.h cli.c fio.c mtx.c pio.c sio.c \ + syscall.h tio.c std-prv.h std.c $(am__append_8) \ + $(am__append_9) libhawk_la_CPPFLAGS = $(CPPFLAGS_ALL_COMMON) $(CPPFLAGS_PFMOD) \ $(am__append_3) libhawk_la_LDFLAGS = $(LDFLAGS_ALL_COMMON) -version-info 1:0:0 -no-undefined @@ -798,6 +801,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhawk_la-utl-sys.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhawk_la-utl.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhawk_la-val.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhawk_la-xma.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhawk_math_la-mod-math.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhawk_str_la-mod-str.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhawk_sys_la-mod-sys.Plo@am__quote@ # am--include-marker @@ -1133,6 +1137,13 @@ libhawk_la-val.lo: val.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhawk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhawk_la-val.lo `test -f 'val.c' || echo '$(srcdir)/'`val.c +libhawk_la-xma.lo: xma.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhawk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libhawk_la-xma.lo -MD -MP -MF $(DEPDIR)/libhawk_la-xma.Tpo -c -o libhawk_la-xma.lo `test -f 'xma.c' || echo '$(srcdir)/'`xma.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libhawk_la-xma.Tpo $(DEPDIR)/libhawk_la-xma.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xma.c' object='libhawk_la-xma.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhawk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhawk_la-xma.lo `test -f 'xma.c' || echo '$(srcdir)/'`xma.c + libhawk_la-cli.lo: cli.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhawk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libhawk_la-cli.lo -MD -MP -MF $(DEPDIR)/libhawk_la-cli.Tpo -c -o libhawk_la-cli.lo `test -f 'cli.c' || echo '$(srcdir)/'`cli.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libhawk_la-cli.Tpo $(DEPDIR)/libhawk_la-cli.Plo @@ -1456,6 +1467,7 @@ distclean: distclean-am -rm -f ./$(DEPDIR)/libhawk_la-utl-sys.Plo -rm -f ./$(DEPDIR)/libhawk_la-utl.Plo -rm -f ./$(DEPDIR)/libhawk_la-val.Plo + -rm -f ./$(DEPDIR)/libhawk_la-xma.Plo -rm -f ./$(DEPDIR)/libhawk_math_la-mod-math.Plo -rm -f ./$(DEPDIR)/libhawk_str_la-mod-str.Plo -rm -f ./$(DEPDIR)/libhawk_sys_la-mod-sys.Plo @@ -1558,6 +1570,7 @@ maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/libhawk_la-utl-sys.Plo -rm -f ./$(DEPDIR)/libhawk_la-utl.Plo -rm -f ./$(DEPDIR)/libhawk_la-val.Plo + -rm -f ./$(DEPDIR)/libhawk_la-xma.Plo -rm -f ./$(DEPDIR)/libhawk_math_la-mod-math.Plo -rm -f ./$(DEPDIR)/libhawk_str_la-mod-str.Plo -rm -f ./$(DEPDIR)/libhawk_sys_la-mod-sys.Plo diff --git a/hawk/lib/hawk-std.h b/hawk/lib/hawk-std.h index 8abf2dd9..b8a82367 100644 --- a/hawk/lib/hawk-std.h +++ b/hawk/lib/hawk-std.h @@ -260,6 +260,12 @@ HAWK_EXPORT void* hawk_stdmodgetsym ( const hawk_ooch_t* name ); +/* ------------------------------------------------------------------------- */ + +HAWK_EXPORT hawk_mmgr_t* hawk_get_sys_mmgr ( + void +); + #if defined(__cplusplus) } #endif diff --git a/hawk/lib/hawk-xma.h b/hawk/lib/hawk-xma.h new file mode 100644 index 00000000..46f0a7e8 --- /dev/null +++ b/hawk/lib/hawk-xma.h @@ -0,0 +1,243 @@ +/* + * $Id$ + * + Copyright (c) 2006-20202 Chung, Hyung-Hwan. 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. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "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 THE AUTHOR 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. + */ + +#ifndef _HAWK_XMA_H_ +#define _HAWK_XMA_H_ + +/** @file + * This file defines an extravagant memory allocator. Why? It may be so. + * The memory allocator allows you to maintain memory blocks from a + * larger memory chunk allocated with an outer memory allocator. + * Typically, an outer memory allocator is a standard memory allocator + * like malloc(). You can isolate memory blocks into a particular chunk. + * + * See the example below. Note it omits error handling. + * + * @code + * #include + * #include + * #include + * void dumper (void* ctx, const char* fmt, ...) + * { + * va_list ap; + * va_start (ap, fmt); + * vfprintf (fmt, ap); + * va_end (ap); + * } + * int main () + * { + * hawk_xma_t* xma; + * void* ptr1, * ptr2; + * + * // create a new memory allocator obtaining a 100K byte zone + * // with the default memory allocator + * xma = hawk_xma_open(HAWK_NULL, 0, 100000L); + * + * ptr1 = hawk_xma_alloc(xma, 5000); // allocate a 5K block from the zone + * ptr2 = hawk_xma_alloc(xma, 1000); // allocate a 1K block from the zone + * ptr1 = hawk_xma_realloc(xma, ptr1, 6000); // resize the 5K block to 6K. + * + * hawk_xma_dump (xma, dumper, HAWK_NULL); // dump memory blocks + * + * // the following two lines are not actually needed as the allocator + * // is closed after them. + * hawk_xma_free (xma, ptr2); // dispose of the 1K block + * hawk_xma_free (xma, ptr1); // dispose of the 6K block + * + * hawk_xma_close (xma); // destroy the memory allocator + * return 0; + * } + * @endcode + */ +#include + +#if defined(HAWK_BUILD_DEBUG) +# define HAWK_XMA_ENABLE_STAT +#endif + +/** @struct hawk_xma_t + * The hawk_xma_t type defines a simple memory allocator over a memory zone. + * It can obtain a relatively large zone of memory and manage it. + */ +typedef struct hawk_xma_t hawk_xma_t; + +/** + * The hawk_xma_fblk_t type defines a memory block allocated. + */ +typedef struct hawk_xma_fblk_t hawk_xma_fblk_t; +typedef struct hawk_xma_mblk_t hawk_xma_mblk_t; + +#define HAWK_XMA_FIXED 32 +#define HAWK_XMA_SIZE_BITS ((HAWK_SIZEOF_OOW_T*8)-1) + +struct hawk_xma_t +{ + hawk_mmgr_t* _mmgr; + + hawk_uint8_t* start; /* zone beginning */ + hawk_uint8_t* end; /* zone end */ + int internal; + + /** pointer array to free memory blocks */ + hawk_xma_fblk_t* xfree[HAWK_XMA_FIXED + HAWK_XMA_SIZE_BITS + 1]; + + /** pre-computed value for fast xfree index calculation */ + hawk_oow_t bdec; + +#if defined(HAWK_XMA_ENABLE_STAT) + struct + { + hawk_oow_t total; + hawk_oow_t alloc; + hawk_oow_t avail; + hawk_oow_t nused; + hawk_oow_t nfree; + } stat; +#endif +}; + +/** + * The hawk_xma_dumper_t type defines a printf-like output function + * for hawk_xma_dump(). + */ +typedef int (*hawk_xma_dumper_t) ( + void* ctx, + const hawk_bch_t* fmt, + ... +); + +#if defined(__cplusplus) +extern "C" { +#endif + +/** + * The hawk_xma_open() function creates a memory allocator. It obtains a memory + * zone of the @a zonesize bytes with the memory manager @a mmgr. It also makes + * available the extension area of the @a xtnsize bytes that you can get the + * pointer to with hawk_xma_getxtn(). + * + * @return pointer to a memory allocator on success, #HAWK_NULL on failure + */ +HAWK_EXPORT hawk_xma_t* hawk_xma_open ( + hawk_mmgr_t* mmgr, /**< memory manager */ + hawk_oow_t xtnsize, /**< extension size in bytes */ + void* zoneptr, + hawk_oow_t zonesize /**< zone size in bytes */ +); + +/** + * The hawk_xma_close() function destroys a memory allocator. It also frees + * the memory zone obtained, which invalidates the memory blocks within + * the zone. Call this function to destroy a memory allocator created with + * hawk_xma_open(). + */ +HAWK_EXPORT void hawk_xma_close ( + hawk_xma_t* xma /**< memory allocator */ +); + +#if defined(HAWK_HAVE_INLINE) +static HAWK_INLINE hawk_mmgr_t* hawk_xma_getmmgr (hawk_xma_t* xma) { return xma->_mmgr; } +#else +# define hawk_xma_getmmgr(xma) (((hawk_xma_t*)(xma))->_mmgr) +#endif + +#if defined(HAWK_HAVE_INLINE) +static HAWK_INLINE void* hawk_xma_getxtn (hawk_xma_t* xma) { return (void*)(xma + 1); } +#else +#define hawk_xma_getxtn(xma) ((void*)((hawk_xma_t*)(xma) + 1)) +#endif + +/** + * The hawk_xma_init() initializes a memory allocator. If you have the hawk_xma_t + * structure statically declared or already allocated, you may pass the pointer + * to this function instead of calling hawk_xma_open(). It obtains a memory zone + * of @a zonesize bytes with the memory manager @a mmgr. Unlike hawk_xma_open(), + * it does not accept the extension size, thus not creating an extention area. + * @return 0 on success, -1 on failure + */ +HAWK_EXPORT int hawk_xma_init ( + hawk_xma_t* xma, /**< memory allocator */ + hawk_mmgr_t* mmgr, /**< memory manager */ + void* zoneptr, /**< pointer to memory zone. if #HAWK_NULL, a zone is auto-created */ + hawk_oow_t zonesize /**< zone size in bytes */ +); + +/** + * The hawk_xma_fini() function finalizes a memory allocator. Call this + * function to finalize a memory allocator initialized with hawk_xma_init(). + */ +HAWK_EXPORT void hawk_xma_fini ( + hawk_xma_t* xma /**< memory allocator */ +); + +/** + * The hawk_xma_alloc() function allocates @a size bytes. + * @return pointer to a memory block on success, #HAWK_NULL on failure + */ +HAWK_EXPORT void* hawk_xma_alloc ( + hawk_xma_t* xma, /**< memory allocator */ + hawk_oow_t size /**< size in bytes */ +); + +HAWK_EXPORT void* hawk_xma_calloc ( + hawk_xma_t* xma, + hawk_oow_t size +); + +/** + * The hawk_xma_alloc() function resizes the memory block @a b to @a size bytes. + * @return pointer to a resized memory block on success, #HAWK_NULL on failure + */ +HAWK_EXPORT void* hawk_xma_realloc ( + hawk_xma_t* xma, /**< memory allocator */ + void* b, /**< memory block */ + hawk_oow_t size /**< new size in bytes */ +); + +/** + * The hawk_xma_alloc() function frees the memory block @a b. + */ +HAWK_EXPORT void hawk_xma_free ( + hawk_xma_t* xma, /**< memory allocator */ + void* b /**< memory block */ +); + +/** + * The hawk_xma_dump() function dumps the contents of the memory zone + * with the output function @a dumper provided. The debug build shows + * more statistical counters. + */ +HAWK_EXPORT void hawk_xma_dump ( + hawk_xma_t* xma, /**< memory allocator */ + hawk_xma_dumper_t dumper, /**< output function */ + void* ctx /**< first parameter to output function */ +); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/hawk/lib/mod-hawk.c b/hawk/lib/mod-hawk.c index b64374c1..9b8370d2 100644 --- a/hawk/lib/mod-hawk.c +++ b/hawk/lib/mod-hawk.c @@ -161,8 +161,10 @@ static int fnc_gc (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi) { hawk_int_t gen = -1; +#if defined(HAWK_ENABLE_GC) if (hawk_rtx_getnargs(rtx) >= 1 && hawk_rtx_valtoint(rtx, hawk_rtx_getarg(rtx, 0), &gen) <= -1) gen = -1; gen = hawk_rtx_gc(rtx, gen); +#endif HAWK_ASSERT (HAWK_IN_QUICKINT_RANGE(gen)); hawk_rtx_setretval (rtx, hawk_rtx_makeintval(rtx, gen)); diff --git a/hawk/lib/run.c b/hawk/lib/run.c index 9622e877..45124ae9 100644 --- a/hawk/lib/run.c +++ b/hawk/lib/run.c @@ -862,6 +862,10 @@ hawk_rtx_t* hawk_rtx_open (hawk_t* hawk, hawk_oow_t xtnsize, hawk_rio_cbs_t* rio rtx->_instsize = HAWK_SIZEOF(hawk_rtx_t); if (HAWK_UNLIKELY(init_rtx(rtx, hawk, rio) <= -1)) { + /* because the error information is in the gem part, + * it should be ok to copy over rtx error to hawk even if + * rtx initialization fails. */ + hawk_rtx_errortohawk (rtx, hawk); hawk_freemem (hawk, rtx); return HAWK_NULL; } @@ -6827,19 +6831,19 @@ static hawk_val_t** get_reference_indexed (hawk_rtx_t* rtx, hawk_nde_var_t* var) break; default: - if (vtype == HAWK_VAL_NIL /* || (rtx->hawk->opt.trait & HAWK_FLEXMAP) no flexmap because this is in a 'get' context. */) + if (vtype == HAWK_VAL_NIL /* || (rtx->hawk->opt.trait & HAWK_FLEXMAP) no flexmap because this is in a 'get' context */) { if (container_vtype == HAWK_VAL_MAP) { v = assign_newmapval_in_map(rtx, map, str, len); - if (HAWK_UNLIKELY(!v)) { ADJERR_LOC(rtx, &var->loc); goto oops; } + if (HAWK_UNLIKELY(!v)) { ADJERR_LOC (rtx, &var->loc); goto oops; } vtype = HAWK_VAL_MAP; goto val_map; } else { v = assign_newarrval_in_arr(rtx, arr, idx); - if (HAWK_UNLIKELY(!v)) { ADJERR_LOC(rtx, &var->loc); goto oops; } + if (HAWK_UNLIKELY(!v)) { ADJERR_LOC (rtx, &var->loc); goto oops; } vtype = HAWK_VAL_ARR; goto val_arr; } @@ -7059,7 +7063,7 @@ static hawk_val_t* eval_indexed (hawk_rtx_t* rtx, hawk_nde_var_t* var) case HAWK_VAL_ARR: val_arr: idx = idxnde_to_int(rtx, remidx, &remidx); - if (idx <= -1) goto oops; + if (HAWK_UNLIKELY(idx <= -1)) goto oops; arr = ((hawk_val_arr_t*)v)->arr; break; @@ -7081,11 +7085,9 @@ static hawk_val_t* eval_indexed (hawk_rtx_t* rtx, hawk_nde_var_t* var) goto val_arr; } } - else - { - hawk_rtx_seterrnum (rtx, &var->loc, HAWK_ENOTIDXACC); - goto oops; - } + + hawk_rtx_seterrnum (rtx, &var->loc, HAWK_ENOTIDXACC); + goto oops; } } #endif diff --git a/hawk/lib/std.c b/hawk/lib/std.c index d805c3dd..35d566ae 100644 --- a/hawk/lib/std.c +++ b/hawk/lib/std.c @@ -223,6 +223,11 @@ static hawk_mmgr_t sys_mmgr = HAWK_NULL }; + +hawk_mmgr_t* hawk_get_sys_mmgr (void) +{ + return &sys_mmgr; +} /* ----------------------------------------------------------------------- */ @@ -907,9 +912,12 @@ hawk_t* hawk_openstdwithmmgr (hawk_mmgr_t* mmgr, hawk_oow_t xtnsize, hawk_cmgr_t prm.logwrite = log_write; + if (!mmgr) mmgr = &sys_mmgr; + if (!cmgr) cmgr = hawk_get_cmgr_by_id(HAWK_CMGR_UTF8); + /* create an object */ hawk = hawk_open(mmgr, HAWK_SIZEOF(xtn_t) + xtnsize, cmgr, &prm, errnum); - if (!hawk) return HAWK_NULL; + if (HAWK_UNLIKELY(!hawk)) return HAWK_NULL; /* adjust the object size by the sizeof xtn_t so that hawk_getxtn() returns the right pointer. */ hawk->_instsize += HAWK_SIZEOF(xtn_t); @@ -2767,7 +2775,7 @@ static hawk_rtx_t* open_rtx_std ( rio.console = hawk_rio_console; rtx = hawk_rtx_open(hawk, HAWK_SIZEOF(rxtn_t) + xtnsize, &rio); - if (!rtx) return HAWK_NULL; + if (HAWK_UNLIKELY(!rtx)) return HAWK_NULL; rtx->_instsize += HAWK_SIZEOF(rxtn_t); @@ -2841,7 +2849,7 @@ hawk_rtx_t* hawk_rtx_openstdwithbcstr ( #if defined(HAWK_OOCH_IS_UCH) xid = hawk_dupbtoucstr(hawk, id, &wcslen, 0); - if (!xid) return HAWK_NULL; + if (HAWK_UNLIKELY(!xid)) return HAWK_NULL; #else xid = (hawk_ooch_t*)id; #endif diff --git a/hawk/lib/xma.c b/hawk/lib/xma.c new file mode 100644 index 00000000..bc747ba1 --- /dev/null +++ b/hawk/lib/xma.c @@ -0,0 +1,779 @@ +/* + * $Id$ + * + Copyright (c) 2006-2020 Chung, Hyung-Hwan. 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. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "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 THE AUTHOR 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. + */ + +#include +#include "hawk-prv.h" + + +#define ALIGN HAWK_SIZEOF(hawk_oow_t) /* this must be a power of 2 */ +#define MBLKHDRSIZE HAWK_SIZEOF(hawk_xma_mblk_t) +#define MINBLKLEN HAWK_SIZEOF(hawk_xma_fblk_t) /* need space for the free links when the block is freeed */ +#define MINALLOCSIZE (ALIGN + ALIGN) /* as large as the free links in hawk_xma_fblk_t */ + +#define SYS_TO_USR(b) ((hawk_uint8_t*)(b) + MBLKHDRSIZE) +#define USR_TO_SYS(b) ((hawk_uint8_t*)(b) - MBLKHDRSIZE) + +/* + * the xfree array is divided into three region + * 0 ....................... FIXED ......................... XFIMAX-1 ... XFIMAX + * | small fixed-size chains | large chains | huge chain | + */ +#define FIXED HAWK_XMA_FIXED +#define XFIMAX(xma) (HAWK_COUNTOF(xma->xfree)-1) + +#define mblk_size(b) (((hawk_xma_mblk_t*)(b))->size) +#define mblk_prev_size(b) (((hawk_xma_mblk_t*)(b))->prev_size) +#define next_mblk(b) ((hawk_xma_mblk_t*)((hawk_uint8_t*)b + MBLKHDRSIZE + mblk_size(b))) +#define prev_mblk(b) ((hawk_xma_mblk_t*)((hawk_uint8_t*)b - (MBLKHDRSIZE + mblk_prev_size(b)))) + +struct hawk_xma_mblk_t +{ + hawk_oow_t prev_size; + hawk_oow_t avail: 1; + hawk_oow_t size: HAWK_XMA_SIZE_BITS;/**< block size */ +}; + +struct hawk_xma_fblk_t +{ + hawk_oow_t prev_size; + hawk_oow_t avail: 1; + hawk_oow_t size: HAWK_XMA_SIZE_BITS;/**< block size */ + + /* these two fields are used only if the block is free */ + hawk_xma_fblk_t* free_prev; /**< link to the previous free block */ + hawk_xma_fblk_t* free_next; /**< link to the next free block */ +}; + +#if defined(VERIFY) +static void DBG_VERIFY (hawk_xma_t* xma, const char* desc) +{ + hawk_xma_mblk_t* tmp, * next; + hawk_oow_t cnt; + for (tmp = (hawk_xma_mblk_t*)xma->start, cnt = 0; (hawk_uint8_t*)tmp < xma->end; tmp = next, cnt++) + { + next = next_mblk(tmp); + + if ((hawk_uint8_t*)tmp == xma->start) + { + HAWK_ASSERT (tmp->prev_size == 0); + } + if ((hawk_uint8_t*)next < xma->end) + { + HAWK_ASSERT (next->prev_size == tmp->size); + } + } +} +#else +#define DBG_VERIFY(xma, desc) +#endif + +static HAWK_INLINE hawk_oow_t szlog2 (hawk_oow_t n) +{ + /* + * 2**x = n; + * x = log2(n); + * ------------------------------------------- + * unsigned int x = 0; + * while((n >> x) > 1) ++x; + * return x; + */ + +#define BITS (HAWK_SIZEOF_OOW_T * 8) + int x = BITS - 1; + +#if HAWK_SIZEOF_OOW_T >= 128 +# error hawk_oow_t too large. unsupported platform +#endif + +#if HAWK_SIZEOF_OOW_T >= 64 + if ((n & (~(hawk_oow_t)0 << (BITS-128))) == 0) { x -= 256; n <<= 256; } +#endif +#if HAWK_SIZEOF_OOW_T >= 32 + if ((n & (~(hawk_oow_t)0 << (BITS-128))) == 0) { x -= 128; n <<= 128; } +#endif +#if HAWK_SIZEOF_OOW_T >= 16 + if ((n & (~(hawk_oow_t)0 << (BITS-64))) == 0) { x -= 64; n <<= 64; } +#endif +#if HAWK_SIZEOF_OOW_T >= 8 + if ((n & (~(hawk_oow_t)0 << (BITS-32))) == 0) { x -= 32; n <<= 32; } +#endif +#if HAWK_SIZEOF_OOW_T >= 4 + if ((n & (~(hawk_oow_t)0 << (BITS-16))) == 0) { x -= 16; n <<= 16; } +#endif +#if HAWK_SIZEOF_OOW_T >= 2 + if ((n & (~(hawk_oow_t)0 << (BITS-8))) == 0) { x -= 8; n <<= 8; } +#endif +#if HAWK_SIZEOF_OOW_T >= 1 + if ((n & (~(hawk_oow_t)0 << (BITS-4))) == 0) { x -= 4; n <<= 4; } +#endif + if ((n & (~(hawk_oow_t)0 << (BITS-2))) == 0) { x -= 2; n <<= 2; } + if ((n & (~(hawk_oow_t)0 << (BITS-1))) == 0) { x -= 1; } + + return x; +#undef BITS +} + +static HAWK_INLINE hawk_oow_t getxfi (hawk_xma_t* xma, hawk_oow_t size) +{ + hawk_oow_t xfi = ((size) / ALIGN) - 1; + if (xfi >= FIXED) xfi = szlog2(size) - (xma)->bdec + FIXED; + if (xfi > XFIMAX(xma)) xfi = XFIMAX(xma); + return xfi; +} + +hawk_xma_t* hawk_xma_open (hawk_mmgr_t* mmgr, hawk_oow_t xtnsize, void* zoneptr, hawk_oow_t zonesize) +{ + hawk_xma_t* xma; + + xma = (hawk_xma_t*)HAWK_MMGR_ALLOC(mmgr, HAWK_SIZEOF(*xma) + xtnsize); + if (HAWK_UNLIKELY(!xma)) return HAWK_NULL; + + if (hawk_xma_init(xma, mmgr, zoneptr, zonesize) <= -1) + { + HAWK_MMGR_FREE (mmgr, xma); + return HAWK_NULL; + } + + HAWK_MEMSET (xma + 1, 0, xtnsize); + return xma; +} + +void hawk_xma_close (hawk_xma_t* xma) +{ + hawk_xma_fini (xma); + HAWK_MMGR_FREE (xma->_mmgr, xma); +} + +int hawk_xma_init (hawk_xma_t* xma, hawk_mmgr_t* mmgr, void* zoneptr, hawk_oow_t zonesize) +{ + hawk_xma_fblk_t* free; + hawk_oow_t xfi; + int internal = 0; + + if (!zoneptr) + { + /* round 'zonesize' to be the multiples of ALIGN */ + zonesize = HAWK_ALIGN_POW2(zonesize, ALIGN); + + /* adjust 'zonesize' to be large enough to hold a single smallest block */ + if (zonesize < MINBLKLEN) zonesize = MINBLKLEN; + + zoneptr = HAWK_MMGR_ALLOC(mmgr, zonesize); + if (HAWK_UNLIKELY(!zoneptr)) return -1; + + internal = 1; + } + + free = (hawk_xma_fblk_t*)zoneptr; + + /* initialize the header part of the free chunk. the entire zone is a single free block */ + free->prev_size = 0; + free->avail = 1; + free->size = zonesize - MBLKHDRSIZE; /* size excluding the block header */ + free->free_prev = HAWK_NULL; + free->free_next = HAWK_NULL; + + HAWK_MEMSET (xma, 0, HAWK_SIZEOF(*xma)); + xma->_mmgr = mmgr; + xma->bdec = szlog2(FIXED * ALIGN); /* precalculate the decrement value */ + + /* at this point, the 'free' chunk is a only block available */ + + /* get the free block index */ + xfi = getxfi(xma, free->size); + /* locate it into an apporopriate slot */ + xma->xfree[xfi] = free; + /* let it be the head, which is natural with only a block */ + xma->start = (hawk_uint8_t*)free; + xma->end = xma->start + zonesize; + xma->internal = internal; + + /* initialize some statistical variables */ +#if defined(HAWK_XMA_ENABLE_STAT) + xma->stat.total = zonesize; + xma->stat.alloc = 0; + xma->stat.avail = zonesize - MBLKHDRSIZE; + xma->stat.nfree = 1; + xma->stat.nused = 0; +#endif + + return 0; +} + +void hawk_xma_fini (hawk_xma_t* xma) +{ + /* the head must point to the free chunk allocated in init(). + * let's deallocate it */ + if (xma->internal) HAWK_MMGR_FREE (xma->_mmgr, xma->start); + xma->start = HAWK_NULL; + xma->end = HAWK_NULL; +} + +static HAWK_INLINE void attach_to_freelist (hawk_xma_t* xma, hawk_xma_fblk_t* b) +{ + /* + * attach a block to a free list + */ + + /* get the free list index for the block size */ + hawk_oow_t xfi = getxfi(xma, b->size); + + /* let it be the head of the free list doubly-linked */ + b->free_prev = HAWK_NULL; + b->free_next = xma->xfree[xfi]; + if (xma->xfree[xfi]) xma->xfree[xfi]->free_prev = b; + xma->xfree[xfi] = b; +} + +static HAWK_INLINE void detach_from_freelist (hawk_xma_t* xma, hawk_xma_fblk_t* b) +{ + /* detach a block from a free list */ + hawk_xma_fblk_t* p, * n; + + /* alias the previous and the next with short variable names */ + p = b->free_prev; + n = b->free_next; + + if (p) + { + /* the previous item exists. let its 'next' pointer point to + * the block's next item. */ + p->free_next = n; + } + else + { + /* the previous item does not exist. the block is the first + * item in the free list. */ + + hawk_oow_t xfi = getxfi(xma, b->size); + HAWK_ASSERT (b == xma->xfree[xfi]); + /* let's update the free list head */ + xma->xfree[xfi] = n; + } + + /* let the 'prev' pointer of the block's next item point to the + * block's previous item */ + if (n) n->free_prev = p; +} + +static hawk_xma_fblk_t* alloc_from_freelist (hawk_xma_t* xma, hawk_oow_t xfi, hawk_oow_t size) +{ + hawk_xma_fblk_t* free; + + for (free = xma->xfree[xfi]; free; free = free->free_next) + { + if (free->size >= size) + { + hawk_oow_t rem; + + detach_from_freelist (xma, free); + + rem = free->size - size; + if (rem >= MINBLKLEN) + { + hawk_xma_mblk_t* y, * z; + + /* the remaining part is large enough to hold + * another block. let's split it + */ + + /* shrink the size of the 'free' block */ + free->size = size; + + /* let 'tmp' point to the remaining part */ + y = next_mblk(free); /* get the next adjacent block */ + + /* initialize some fields */ + y->avail = 1; + y->size = rem - MBLKHDRSIZE; + y->prev_size = free->size; + + /* add the remaining part to the free list */ + attach_to_freelist (xma, (hawk_xma_fblk_t*)y); + + z = next_mblk(y); + if ((hawk_uint8_t*)z < xma->end) z->prev_size = y->size; + +#if defined(HAWK_XMA_ENABLE_STAT) + xma->stat.avail -= MBLKHDRSIZE; +#endif + } +#if defined(HAWK_XMA_ENABLE_STAT) + else + { + /* decrement the number of free blocks as the current + * block is allocated as a whole without being split */ + xma->stat.nfree--; + } +#endif + + free->avail = 0; + /* + free->free_next = HAWK_NULL; + free->free_prev = HAWK_NULL; + */ + +#if defined(HAWK_XMA_ENABLE_STAT) + xma->stat.nused++; + xma->stat.alloc += free->size; + xma->stat.avail -= free->size; +#endif + return free; + } + } + + return HAWK_NULL; +} + + +void* hawk_xma_alloc (hawk_xma_t* xma, hawk_oow_t size) +{ + hawk_xma_fblk_t* free; + hawk_oow_t xfi; + + DBG_VERIFY (xma, "alloc start"); + + /* round up 'size' to the multiples of ALIGN */ + if (size < MINALLOCSIZE) size = MINALLOCSIZE; + size = HAWK_ALIGN_POW2(size, ALIGN); + + HAWK_ASSERT (size >= ALIGN); + xfi = getxfi(xma, size); + + /*if (xfi < XFIMAX(xma) && xma->xfree[xfi])*/ + if (xfi < FIXED && xma->xfree[xfi]) + { + /* try the best fit */ + free = xma->xfree[xfi]; + + HAWK_ASSERT (free->avail != 0); + HAWK_ASSERT (free->size == size); + + detach_from_freelist (xma, free); + free->avail = 0; + +#if defined(HAWK_XMA_ENABLE_STAT) + xma->stat.nfree--; + xma->stat.nused++; + xma->stat.alloc += free->size; + xma->stat.avail -= free->size; +#endif + } + else if (xfi == XFIMAX(xma)) + { + /* huge block */ + free = alloc_from_freelist(xma, XFIMAX(xma), size); + if (!free) return HAWK_NULL; + } + else + { + if (xfi >= FIXED) + { + /* get the block from its own large chain */ + free = alloc_from_freelist(xma, xfi, size); + if (!free) + { + /* borrow a large block from the huge block chain */ + free = alloc_from_freelist(xma, XFIMAX(xma), size); + } + } + else + { + /* borrow a small block from the huge block chain */ + free = alloc_from_freelist(xma, XFIMAX(xma), size); + if (!free) xfi = FIXED - 1; + } + + if (!free) + { + /* try each large block chain left */ + for (++xfi; xfi < XFIMAX(xma) - 1; xfi++) + { + free = alloc_from_freelist(xma, xfi, size); + if (free) break; + } + if (!free) return HAWK_NULL; + } + } + + DBG_VERIFY (xma, "alloc end"); + return SYS_TO_USR(free); +} + +static void* _realloc_merge (hawk_xma_t* xma, void* b, hawk_oow_t size) +{ + hawk_xma_mblk_t* blk = (hawk_xma_mblk_t*)USR_TO_SYS(b); + + DBG_VERIFY (xma, "realloc merge start"); + /* rounds up 'size' to be multiples of ALIGN */ + if (size < MINALLOCSIZE) size = MINALLOCSIZE; + size = HAWK_ALIGN_POW2(size, ALIGN); + + if (size > blk->size) + { + /* grow the current block */ + hawk_oow_t req; + hawk_xma_mblk_t* n; + hawk_oow_t rem; + + req = size - blk->size; + + n = next_mblk(blk); + /* check if the next adjacent block is available */ + if ((hawk_uint8_t*)n >= xma->end || !n->avail || req > n->size) return HAWK_NULL; /* no! */ + + HAWK_ASSERT (blk->size == n->prev_size); + + /* let's merge the current block with the next block */ + detach_from_freelist (xma, (hawk_xma_fblk_t*)n); + + rem = (MBLKHDRSIZE + n->size) - req; + if (rem >= MINBLKLEN) + { + /* + * the remaining part of the next block is large enough + * to hold a block. break the next block. + */ + + hawk_xma_mblk_t* tmp; + + blk->size += req; + tmp = next_mblk(blk); + tmp->avail = 1; + tmp->size = rem - MBLKHDRSIZE; + tmp->prev_size = blk->size; + attach_to_freelist (xma, (hawk_xma_fblk_t*)tmp); + + n = next_mblk(tmp); + if ((hawk_uint8_t*)n < xma->end) n->prev_size = tmp->size; + +#if defined(HAWK_XMA_ENABLE_STAT) + xma->stat.alloc += req; + xma->stat.avail -= req; /* req + MBLKHDRSIZE(tmp) - MBLKHDRSIZE(n) */ +#endif + } + else + { + /* the remaining part of the next block is too small to form an indepent block. + * utilize the whole block by merging to the resizing block */ + blk->size += MBLKHDRSIZE + n->size; + + n = next_mblk(blk); + if ((hawk_uint8_t*)n < xma->end) n->prev_size = blk->size; + +#if defined(HAWK_XMA_ENABLE_STAT) + xma->stat.nfree--; + xma->stat.alloc += MBLKHDRSIZE + n->size; + xma->stat.avail -= n->size; +#endif + } + } + else if (size < blk->size) + { + /* shrink the block */ + hawk_oow_t rem = blk->size - size; + if (rem >= MINBLKLEN) + { + hawk_xma_mblk_t* tmp; + hawk_xma_mblk_t* n; + + n = next_mblk(blk); + + /* the leftover is large enough to hold a block of minimum size. + * split the current block. let 'tmp' point to the leftover. */ + if ((hawk_uint8_t*)n < xma->end && n->avail) + { + /* let the leftover block merge with the next block */ + detach_from_freelist (xma, (hawk_xma_fblk_t*)n); + + blk->size = size; + + tmp = next_mblk(blk); + tmp->avail = 1; + tmp->size = rem + n->size; + tmp->prev_size = blk->size; + + /* add 'tmp' to the free list */ + attach_to_freelist (xma, (hawk_xma_fblk_t*)tmp); + + n = next_mblk(tmp); + if ((hawk_uint8_t*)n < xma->end) n->prev_size = tmp->size; + + +#if defined(HAWK_XMA_ENABLE_STAT) + xma->stat.alloc -= rem; + /* rem - MBLKHDRSIZE(tmp) + MBLKHDRSIZE(n) */ + xma->stat.avail += rem; +#endif + } + else + { + /* link the leftover block to the free list */ + blk->size = size; + + tmp = next_mblk(blk); + tmp->avail = 1; + tmp->size = rem - MBLKHDRSIZE; + tmp->prev_size = blk->size; + + attach_to_freelist (xma, (hawk_xma_fblk_t*)tmp); + /*n = next_mblk(tmp); + if ((hawk_uint8_t*)n < xma->end)*/ n->prev_size = tmp->size; + +#if defined(HAWK_XMA_ENABLE_STAT) + xma->stat.nfree++; + xma->stat.alloc -= rem; + xma->stat.avail += tmp->size; +#endif + } + } + } + + DBG_VERIFY (xma, "realloc merge end"); + return b; +} + +void* hawk_xma_calloc (hawk_xma_t* xma, hawk_oow_t size) +{ + void* ptr = hawk_xma_alloc(xma, size); + if (ptr) HAWK_MEMSET (ptr, 0, size); + return ptr; +} + +void* hawk_xma_realloc (hawk_xma_t* xma, void* b, hawk_oow_t size) +{ + void* n; + + if (b == HAWK_NULL) + { + /* 'realloc' with NULL is the same as 'alloc' */ + n = hawk_xma_alloc(xma, size); + } + else + { + /* try reallocation by merging the adjacent continuous blocks */ + n = _realloc_merge (xma, b, size); + if (!n) + { + /* reallocation by merging failed. fall back to the slow + * allocation-copy-free scheme */ + n = hawk_xma_alloc(xma, size); + if (n) + { + HAWK_MEMCPY (n, b, size); + hawk_xma_free (xma, b); + } + } + } + + return n; +} + +void hawk_xma_free (hawk_xma_t* xma, void* b) +{ + hawk_xma_mblk_t* blk = (hawk_xma_mblk_t*)USR_TO_SYS(b); + hawk_xma_mblk_t* x, * y; + + DBG_VERIFY (xma, "free start"); + +#if defined(HAWK_XMA_ENABLE_STAT) + /* update statistical variables */ + xma->stat.nused--; + xma->stat.alloc -= blk->size; +#endif + + x = prev_mblk(blk); + y = next_mblk(blk); + if (((hawk_uint8_t*)x >= xma->start && x->avail) && ((hawk_uint8_t*)y < xma->end && y->avail)) + { + /* + * Merge the block with surrounding blocks + * + * blk + * | + * v + * +------------+------------+------------+------------+ + * | X | | Y | Z | + * +------------+------------+------------+------------+ + * + * + * +--------------------------------------+------------+ + * | X | Z | + * +--------------------------------------+------------+ + * + */ + + hawk_xma_mblk_t* z = next_mblk(y); + hawk_oow_t ns = MBLKHDRSIZE + blk->size + MBLKHDRSIZE; + hawk_oow_t bs = ns + y->size; + + detach_from_freelist (xma, (hawk_xma_fblk_t*)x); + detach_from_freelist (xma, (hawk_xma_fblk_t*)y); + + x->size += bs; + attach_to_freelist (xma, (hawk_xma_fblk_t*)x); + + z = next_mblk(x); + if ((hawk_uint8_t*)z < xma->end) z->prev_size = x->size; + +#if defined(HAWK_XMA_ENABLE_STAT) + xma->stat.nfree--; + xma->stat.avail += ns; +#endif + } + else if ((hawk_uint8_t*)y < xma->end && y->avail) + { + /* + * Merge the block with the next block + * + * blk + * | + * v + * +------------+------------+------------+ + * | | Y | Z | + * +------------+------------+------------+ + * + * + * + * blk + * | + * v + * +-------------------------+------------+ + * | | Z | + * +-------------------------+------------+ + * + * + */ + hawk_xma_mblk_t* z = next_mblk(y); + +#if defined(HAWK_XMA_ENABLE_STAT) + xma->stat.avail += blk->size + MBLKHDRSIZE; +#endif + + /* detach y from the free list */ + detach_from_freelist (xma, (hawk_xma_fblk_t*)y); + + /* update the block availability */ + blk->avail = 1; + /* update the block size. MBLKHDRSIZE for the header space in x */ + blk->size += MBLKHDRSIZE + y->size; + + /* update the backward link of Y */ + if ((hawk_uint8_t*)z < xma->end) z->prev_size = blk->size; + + /* attach blk to the free list */ + attach_to_freelist (xma, (hawk_xma_fblk_t*)blk); + } + else if ((hawk_uint8_t*)x >= xma->start && x->avail) + { + /* + * Merge the block with the previous block + * + * blk + * | + * v + * +------------+------------+------------+ + * | X | | Y | + * +------------+------------+------------+ + * + * +-------------------------+------------+ + * | X | Y | + * +-------------------------+------------+ + */ +#if defined(HAWK_XMA_ENABLE_STAT) + xma->stat.avail += MBLKHDRSIZE + blk->size; +#endif + + detach_from_freelist (xma, (hawk_xma_fblk_t*)x); + + x->size += MBLKHDRSIZE + blk->size; + if ((hawk_uint8_t*)y < xma->end) y->prev_size = x->size; + + attach_to_freelist (xma, (hawk_xma_fblk_t*)x); + } + else + { + + blk->avail = 1; + attach_to_freelist (xma, (hawk_xma_fblk_t*)blk); + +#if defined(HAWK_XMA_ENABLE_STAT) + xma->stat.nfree++; + xma->stat.avail += blk->size; +#endif + } + + DBG_VERIFY (xma, "free end"); +} + +void hawk_xma_dump (hawk_xma_t* xma, hawk_xma_dumper_t dumper, void* ctx) +{ + hawk_xma_mblk_t* tmp; + hawk_oow_t fsum, asum; +#if defined(HAWK_XMA_ENABLE_STAT) + hawk_oow_t isum; +#endif + + dumper (ctx, "\n"); + +#if defined(HAWK_XMA_ENABLE_STAT) + dumper (ctx, "== statistics ==\n"); + dumper (ctx, "total = %zu\n", xma->stat.total); + dumper (ctx, "alloc = %zu\n", xma->stat.alloc); + dumper (ctx, "avail = %zu\n", xma->stat.avail); +#endif + + dumper (ctx, "== blocks ==\n"); + dumper (ctx, " size avail address\n"); + for (tmp = (hawk_xma_mblk_t*)xma->start, fsum = 0, asum = 0; (hawk_uint8_t*)tmp < xma->end; tmp = next_mblk(tmp)) + { + dumper (ctx, " %-18zu %-5u %p\n", tmp->size, (unsigned int)tmp->avail, tmp); + if (tmp->avail) fsum += tmp->size; + else asum += tmp->size; + } + +#if defined(HAWK_XMA_ENABLE_STAT) + isum = (xma->stat.nfree + xma->stat.nused) * MBLKHDRSIZE; +#endif + + dumper (ctx, "---------------------------------------\n"); + dumper (ctx, "Allocated blocks: %18zu bytes\n", asum); + dumper (ctx, "Available blocks: %18zu bytes\n", fsum); + + +#if defined(HAWK_XMA_ENABLE_STAT) + dumper (ctx, "Internal use : %18zu bytes\n", isum); + dumper (ctx, "Total : %18zu bytes\n", (asum + fsum + isum)); +#endif + +#if defined(HAWK_XMA_ENABLE_STAT) + HAWK_ASSERT (asum == xma->stat.alloc); + HAWK_ASSERT (fsum == xma->stat.avail); + HAWK_ASSERT (isum == xma->stat.total - (xma->stat.alloc + xma->stat.avail)); + HAWK_ASSERT (asum + fsum + isum == xma->stat.total); +#endif +} +