added the xma memory manager

This commit is contained in:
hyung-hwan 2020-11-02 09:54:12 +00:00
parent b17dfeea3c
commit 200f5f1d94
9 changed files with 1100 additions and 54 deletions

View File

@ -28,6 +28,7 @@
#include <hawk-utl.h>
#include <hawk-fmt.h>
#include <hawk-cli.h>
#include <hawk-xma.h>
#include <stdio.h>
#include <string.h>
@ -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)

View File

@ -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 \

View File

@ -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

View File

@ -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

243
hawk/lib/hawk-xma.h Normal file
View File

@ -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 <hawk-xma.h>
* #include <stdio.h>
* #include <stdarg.h>
* 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 <hawk-cmn.h>
#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

View File

@ -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));

View File

@ -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

View File

@ -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

779
hawk/lib/xma.c Normal file
View File

@ -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 <hawk-xma.h>
#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, "<XMA DUMP>\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
}