2010-07-24 07:24:44 +00:00
|
|
|
/*
|
|
|
|
* $Id$
|
|
|
|
*
|
2019-06-06 05:28:23 +00:00
|
|
|
Copyright (c) 2006-2019 Chung, Hyung-Hwan. All rights reserved.
|
2010-07-24 07:24:44 +00:00
|
|
|
|
2014-11-19 14:42:24 +00:00
|
|
|
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.
|
2010-07-24 07:24:44 +00:00
|
|
|
|
2014-11-19 14:42:24 +00:00
|
|
|
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.
|
2010-07-24 07:24:44 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <qse/cmn/xma.h>
|
2016-04-29 03:55:42 +00:00
|
|
|
#include "mem-prv.h"
|
2010-07-24 07:24:44 +00:00
|
|
|
|
2016-04-27 06:54:18 +00:00
|
|
|
#define ALIGN QSE_SIZEOF(qse_size_t) /* this must be a power of 2 */
|
2010-07-24 07:24:44 +00:00
|
|
|
#define HDRSIZE QSE_SIZEOF(qse_xma_blk_t)
|
2010-07-31 07:24:19 +00:00
|
|
|
#define MINBLKLEN (HDRSIZE + ALIGN)
|
2010-07-24 07:24:44 +00:00
|
|
|
|
|
|
|
#define SYS_TO_USR(_) (((qse_xma_blk_t*)_) + 1)
|
|
|
|
#define USR_TO_SYS(_) (((qse_xma_blk_t*)_) - 1)
|
|
|
|
|
2010-07-29 07:27:03 +00:00
|
|
|
/*
|
|
|
|
* the xfree array is divided into three region
|
|
|
|
* 0 ....................... FIXED ......................... XFIMAX-1 ... XFIMAX
|
|
|
|
* | small fixed-size chains | large chains | huge chain |
|
|
|
|
*/
|
|
|
|
#define FIXED QSE_XMA_FIXED
|
2010-07-25 06:43:26 +00:00
|
|
|
#define XFIMAX(xma) (QSE_COUNTOF(xma->xfree)-1)
|
2010-07-24 07:24:44 +00:00
|
|
|
|
|
|
|
struct qse_xma_blk_t
|
|
|
|
{
|
|
|
|
qse_size_t avail: 1;
|
2010-07-29 07:27:03 +00:00
|
|
|
qse_size_t size: QSE_XMA_SIZE_BITS;/**< block size */
|
2010-07-24 07:24:44 +00:00
|
|
|
|
2010-07-25 06:43:26 +00:00
|
|
|
struct
|
|
|
|
{
|
|
|
|
qse_xma_blk_t* prev; /**< link to the previous free block */
|
|
|
|
qse_xma_blk_t* next; /**< link to the next free block */
|
|
|
|
} f;
|
|
|
|
|
|
|
|
struct
|
|
|
|
{
|
2011-09-03 09:27:44 +00:00
|
|
|
qse_xma_blk_t* prev; /**< link to the previous adjacent block */
|
|
|
|
qse_xma_blk_t* next; /**< link to the next adjacent block */
|
2010-07-25 06:43:26 +00:00
|
|
|
} b;
|
2010-07-24 07:24:44 +00:00
|
|
|
};
|
|
|
|
|
2010-07-31 07:24:19 +00:00
|
|
|
static QSE_INLINE_ALWAYS qse_size_t szlog2 (qse_size_t n)
|
2010-07-29 07:27:03 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* 2**x = n;
|
|
|
|
* x = log2(n);
|
|
|
|
* -------------------------------------------
|
|
|
|
* unsigned int x = 0;
|
|
|
|
* while((n >> x) > 1) ++x;
|
|
|
|
* return x;
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define BITS (QSE_SIZEOF_SIZE_T * 8)
|
|
|
|
int x = BITS - 1;
|
|
|
|
|
2014-03-11 14:54:05 +00:00
|
|
|
#if QSE_SIZEOF_SIZE_T >= 128
|
2010-07-29 07:27:03 +00:00
|
|
|
# error qse_size_t too large. unsupported platform
|
|
|
|
#endif
|
|
|
|
|
2014-03-11 14:54:05 +00:00
|
|
|
#if QSE_SIZEOF_SIZE_T >= 64
|
|
|
|
if ((n & (~(qse_size_t)0 << (BITS-128))) == 0) { x -= 256; n <<= 256; }
|
|
|
|
#endif
|
|
|
|
#if QSE_SIZEOF_SIZE_T >= 32
|
|
|
|
if ((n & (~(qse_size_t)0 << (BITS-128))) == 0) { x -= 128; n <<= 128; }
|
|
|
|
#endif
|
2010-07-29 07:27:03 +00:00
|
|
|
#if QSE_SIZEOF_SIZE_T >= 16
|
|
|
|
if ((n & (~(qse_size_t)0 << (BITS-64))) == 0) { x -= 64; n <<= 64; }
|
|
|
|
#endif
|
|
|
|
#if QSE_SIZEOF_SIZE_T >= 8
|
|
|
|
if ((n & (~(qse_size_t)0 << (BITS-32))) == 0) { x -= 32; n <<= 32; }
|
|
|
|
#endif
|
|
|
|
#if QSE_SIZEOF_SIZE_T >= 4
|
|
|
|
if ((n & (~(qse_size_t)0 << (BITS-16))) == 0) { x -= 16; n <<= 16; }
|
|
|
|
#endif
|
|
|
|
#if QSE_SIZEOF_SIZE_T >= 2
|
|
|
|
if ((n & (~(qse_size_t)0 << (BITS-8))) == 0) { x -= 8; n <<= 8; }
|
|
|
|
#endif
|
|
|
|
#if QSE_SIZEOF_SIZE_T >= 1
|
|
|
|
if ((n & (~(qse_size_t)0 << (BITS-4))) == 0) { x -= 4; n <<= 4; }
|
|
|
|
#endif
|
|
|
|
if ((n & (~(qse_size_t)0 << (BITS-2))) == 0) { x -= 2; n <<= 2; }
|
|
|
|
if ((n & (~(qse_size_t)0 << (BITS-1))) == 0) { x -= 1; }
|
|
|
|
|
|
|
|
return x;
|
|
|
|
#undef BITS
|
|
|
|
}
|
|
|
|
|
2010-07-31 07:24:19 +00:00
|
|
|
static QSE_INLINE_ALWAYS qse_size_t getxfi (qse_xma_t* xma, qse_size_t size)
|
|
|
|
{
|
|
|
|
qse_size_t xfi = ((size) / ALIGN) - 1;
|
|
|
|
if (xfi >= FIXED) xfi = szlog2(size) - (xma)->bdec + FIXED;
|
|
|
|
if (xfi > XFIMAX(xma)) xfi = XFIMAX(xma);
|
|
|
|
return xfi;
|
|
|
|
}
|
|
|
|
|
2010-08-05 01:25:48 +00:00
|
|
|
qse_xma_t* qse_xma_open (
|
|
|
|
qse_mmgr_t* mmgr, qse_size_t xtnsize, qse_size_t zonesize)
|
2010-07-25 06:43:26 +00:00
|
|
|
{
|
|
|
|
qse_xma_t* xma;
|
|
|
|
|
2010-08-05 01:25:48 +00:00
|
|
|
xma = (qse_xma_t*) QSE_MMGR_ALLOC (mmgr, QSE_SIZEOF(*xma) + xtnsize);
|
2010-07-25 06:43:26 +00:00
|
|
|
if (xma == QSE_NULL) return QSE_NULL;
|
|
|
|
|
2011-09-01 09:43:46 +00:00
|
|
|
if (qse_xma_init (xma, mmgr, zonesize) <= -1)
|
2010-07-25 06:43:26 +00:00
|
|
|
{
|
|
|
|
QSE_MMGR_FREE (mmgr, xma);
|
|
|
|
return QSE_NULL;
|
|
|
|
}
|
|
|
|
|
2014-07-11 14:17:00 +00:00
|
|
|
QSE_MEMSET (QSE_XTN(xma), 0, xtnsize);
|
2010-07-25 06:43:26 +00:00
|
|
|
return xma;
|
|
|
|
}
|
|
|
|
|
|
|
|
void qse_xma_close (qse_xma_t* xma)
|
|
|
|
{
|
|
|
|
qse_xma_fini (xma);
|
|
|
|
QSE_MMGR_FREE (xma->mmgr, xma);
|
|
|
|
}
|
|
|
|
|
2011-09-01 09:43:46 +00:00
|
|
|
int qse_xma_init (qse_xma_t* xma, qse_mmgr_t* mmgr, qse_size_t zonesize)
|
2010-07-24 07:24:44 +00:00
|
|
|
{
|
|
|
|
qse_xma_blk_t* free;
|
2010-07-29 07:27:03 +00:00
|
|
|
qse_size_t xfi;
|
2010-07-24 07:24:44 +00:00
|
|
|
|
2010-08-26 07:15:40 +00:00
|
|
|
/* round 'zonesize' to be the multiples of ALIGN */
|
2016-04-27 06:54:18 +00:00
|
|
|
zonesize = QSE_ALIGNTO_POW2(zonesize, ALIGN);
|
2010-08-26 07:15:40 +00:00
|
|
|
|
2010-08-05 01:25:48 +00:00
|
|
|
/* adjust 'zonesize' to be large enough to hold a single smallest block */
|
|
|
|
if (zonesize < MINBLKLEN) zonesize = MINBLKLEN;
|
2010-07-24 07:24:44 +00:00
|
|
|
|
2010-07-29 07:27:03 +00:00
|
|
|
/* allocate a memory chunk to use for actual memory allocation */
|
2010-08-05 01:25:48 +00:00
|
|
|
free = QSE_MMGR_ALLOC (mmgr, zonesize);
|
2011-09-01 09:43:46 +00:00
|
|
|
if (free == QSE_NULL) return -1;
|
2010-07-24 07:24:44 +00:00
|
|
|
|
2010-07-29 07:27:03 +00:00
|
|
|
/* initialize the header part of the free chunk */
|
|
|
|
free->avail = 1;
|
2010-08-05 01:25:48 +00:00
|
|
|
free->size = zonesize - HDRSIZE; /* size excluding the block header */
|
2010-07-25 06:43:26 +00:00
|
|
|
free->f.prev = QSE_NULL;
|
|
|
|
free->f.next = QSE_NULL;
|
|
|
|
free->b.next = QSE_NULL;
|
|
|
|
free->b.prev = QSE_NULL;
|
2010-07-24 07:24:44 +00:00
|
|
|
|
2010-07-25 06:43:26 +00:00
|
|
|
QSE_MEMSET (xma, 0, QSE_SIZEOF(*xma));
|
|
|
|
xma->mmgr = mmgr;
|
2014-03-11 14:54:05 +00:00
|
|
|
xma->bdec = szlog2(FIXED * ALIGN); /* precalculate the decrement value */
|
2010-07-25 06:43:26 +00:00
|
|
|
|
2010-08-26 07:15:40 +00:00
|
|
|
/* at this point, the 'free' chunk is a only block available */
|
|
|
|
|
|
|
|
/* get the free block index */
|
2010-07-31 07:24:19 +00:00
|
|
|
xfi = getxfi(xma,free->size);
|
2010-08-26 07:15:40 +00:00
|
|
|
/* locate it into an apporopriate slot */
|
|
|
|
xma->xfree[xfi] = free;
|
|
|
|
/* let it be the head, which is natural with only a block */
|
|
|
|
xma->head = free;
|
2010-07-24 07:24:44 +00:00
|
|
|
|
|
|
|
/* initialize some statistical variables */
|
2014-11-14 02:44:20 +00:00
|
|
|
#if defined(QSE_XMA_ENABLE_STAT)
|
2010-08-05 01:25:48 +00:00
|
|
|
xma->stat.total = zonesize;
|
2010-07-25 06:43:26 +00:00
|
|
|
xma->stat.alloc = 0;
|
2010-08-05 01:25:48 +00:00
|
|
|
xma->stat.avail = zonesize - HDRSIZE;
|
2010-07-25 06:43:26 +00:00
|
|
|
xma->stat.nfree = 1;
|
|
|
|
xma->stat.nused = 0;
|
2010-07-29 07:27:03 +00:00
|
|
|
#endif
|
|
|
|
|
2011-09-01 09:43:46 +00:00
|
|
|
return 0;
|
2010-07-24 07:24:44 +00:00
|
|
|
}
|
|
|
|
|
2010-07-25 06:43:26 +00:00
|
|
|
void qse_xma_fini (qse_xma_t* xma)
|
2010-07-24 07:24:44 +00:00
|
|
|
{
|
2010-08-26 07:15:40 +00:00
|
|
|
/* the head must point to the free chunk allocated in init().
|
|
|
|
* let's deallocate it */
|
2010-07-25 06:43:26 +00:00
|
|
|
QSE_MMGR_FREE (xma->mmgr, xma->head);
|
2010-07-24 07:24:44 +00:00
|
|
|
}
|
|
|
|
|
2012-11-29 14:03:59 +00:00
|
|
|
qse_mmgr_t* qse_xma_getmmgr (qse_xma_t* xma)
|
|
|
|
{
|
|
|
|
return xma->mmgr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void* qse_xma_getxtn (qse_xma_t* xma)
|
|
|
|
{
|
|
|
|
return QSE_XTN (xma);
|
|
|
|
}
|
|
|
|
|
2010-07-29 07:27:03 +00:00
|
|
|
static QSE_INLINE void attach_to_freelist (qse_xma_t* xma, qse_xma_blk_t* b)
|
2010-07-24 07:24:44 +00:00
|
|
|
{
|
2010-08-26 07:15:40 +00:00
|
|
|
/*
|
|
|
|
* attach a block to a free list
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* get the free list index for the block size */
|
|
|
|
qse_size_t xfi = getxfi(xma,b->size);
|
2010-07-24 07:24:44 +00:00
|
|
|
|
2010-08-26 07:15:40 +00:00
|
|
|
/* let it be the head of the free list doubly-linked */
|
|
|
|
b->f.prev = QSE_NULL;
|
2010-07-25 06:43:26 +00:00
|
|
|
b->f.next = xma->xfree[xfi];
|
|
|
|
if (xma->xfree[xfi]) xma->xfree[xfi]->f.prev = b;
|
|
|
|
xma->xfree[xfi] = b;
|
2010-07-24 07:24:44 +00:00
|
|
|
}
|
|
|
|
|
2010-07-29 07:27:03 +00:00
|
|
|
static QSE_INLINE void detach_from_freelist (qse_xma_t* xma, qse_xma_blk_t* b)
|
2010-07-24 07:24:44 +00:00
|
|
|
{
|
2010-08-26 07:15:40 +00:00
|
|
|
/*
|
|
|
|
* detach a block from a free list
|
|
|
|
*/
|
2010-07-29 07:27:03 +00:00
|
|
|
qse_xma_blk_t* p, * n;
|
2010-07-24 07:24:44 +00:00
|
|
|
|
2010-08-26 07:15:40 +00:00
|
|
|
/* alias the previous and the next with short variable names */
|
2010-07-29 07:27:03 +00:00
|
|
|
p = b->f.prev;
|
|
|
|
n = b->f.next;
|
2010-07-24 07:24:44 +00:00
|
|
|
|
2010-07-29 07:27:03 +00:00
|
|
|
if (p)
|
|
|
|
{
|
2010-08-26 07:15:40 +00:00
|
|
|
/* the previous item exists. let its 'next' pointer point to
|
|
|
|
* the block's next item. */
|
2010-07-29 07:27:03 +00:00
|
|
|
p->f.next = n;
|
|
|
|
}
|
2010-07-24 07:24:44 +00:00
|
|
|
else
|
|
|
|
{
|
2010-08-26 07:15:40 +00:00
|
|
|
/* the previous item does not exist. the block is the first
|
|
|
|
* item in the free list. */
|
|
|
|
|
2010-07-31 07:24:19 +00:00
|
|
|
qse_size_t xfi = getxfi(xma,b->size);
|
2010-07-29 07:27:03 +00:00
|
|
|
QSE_ASSERT (b == xma->xfree[xfi]);
|
2010-08-26 07:15:40 +00:00
|
|
|
/* let's update the free list head */
|
2010-07-29 07:27:03 +00:00
|
|
|
xma->xfree[xfi] = n;
|
2010-07-24 07:24:44 +00:00
|
|
|
}
|
2010-08-26 07:15:40 +00:00
|
|
|
|
|
|
|
/* let the 'prev' pointer of the block's next item point to the
|
|
|
|
* block's previous item */
|
|
|
|
if (n) n->f.prev = p;
|
2010-07-24 07:24:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static qse_xma_blk_t* alloc_from_freelist (
|
2010-07-25 06:43:26 +00:00
|
|
|
qse_xma_t* xma, qse_size_t xfi, qse_size_t size)
|
2010-07-24 07:24:44 +00:00
|
|
|
{
|
|
|
|
qse_xma_blk_t* free;
|
|
|
|
|
2010-07-25 06:43:26 +00:00
|
|
|
for (free = xma->xfree[xfi]; free; free = free->f.next)
|
2010-07-24 07:24:44 +00:00
|
|
|
{
|
|
|
|
if (free->size >= size)
|
|
|
|
{
|
2010-11-04 08:24:29 +00:00
|
|
|
qse_size_t rem;
|
|
|
|
|
2010-07-29 07:27:03 +00:00
|
|
|
detach_from_freelist (xma, free);
|
2010-07-24 07:24:44 +00:00
|
|
|
|
2010-11-04 08:24:29 +00:00
|
|
|
rem = free->size - size;
|
2010-07-31 07:24:19 +00:00
|
|
|
if (rem >= MINBLKLEN)
|
2010-07-24 07:24:44 +00:00
|
|
|
{
|
|
|
|
qse_xma_blk_t* tmp;
|
|
|
|
|
|
|
|
/* the remaining part is large enough to hold
|
2010-07-29 07:27:03 +00:00
|
|
|
* another block. let's split it
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* shrink the size of the 'free' block */
|
|
|
|
free->size = size;
|
|
|
|
|
|
|
|
/* let 'tmp' point to the remaining part */
|
2010-07-24 07:24:44 +00:00
|
|
|
tmp = (qse_xma_blk_t*)(((qse_byte_t*)(free + 1)) + size);
|
|
|
|
|
2010-07-29 07:27:03 +00:00
|
|
|
/* initialize some fields */
|
2010-07-24 07:24:44 +00:00
|
|
|
tmp->avail = 1;
|
|
|
|
tmp->size = rem - HDRSIZE;
|
2010-07-29 07:27:03 +00:00
|
|
|
|
|
|
|
/* link 'tmp' to the block list */
|
2010-07-25 06:43:26 +00:00
|
|
|
tmp->b.next = free->b.next;
|
|
|
|
tmp->b.prev = free;
|
|
|
|
if (free->b.next) free->b.next->b.prev = tmp;
|
|
|
|
free->b.next = tmp;
|
2010-07-24 07:24:44 +00:00
|
|
|
|
2010-07-29 07:27:03 +00:00
|
|
|
/* add the remaining part to the free list */
|
|
|
|
attach_to_freelist (xma, tmp);
|
2010-07-24 07:24:44 +00:00
|
|
|
|
2014-11-14 02:44:20 +00:00
|
|
|
#if defined(QSE_XMA_ENABLE_STAT)
|
2010-07-25 06:43:26 +00:00
|
|
|
xma->stat.avail -= HDRSIZE;
|
2010-07-29 07:27:03 +00:00
|
|
|
#endif
|
2010-07-24 07:24:44 +00:00
|
|
|
}
|
2014-11-14 02:44:20 +00:00
|
|
|
#if defined(QSE_XMA_ENABLE_STAT)
|
2010-07-24 07:24:44 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
/* decrement the number of free blocks as the current
|
|
|
|
* block is allocated as a whole without being split */
|
2010-07-25 06:43:26 +00:00
|
|
|
xma->stat.nfree--;
|
2010-07-24 07:24:44 +00:00
|
|
|
}
|
2010-07-29 07:27:03 +00:00
|
|
|
#endif
|
2010-07-24 07:24:44 +00:00
|
|
|
|
|
|
|
free->avail = 0;
|
|
|
|
/*
|
2010-07-25 06:43:26 +00:00
|
|
|
free->f.next = QSE_NULL;
|
|
|
|
free->f.prev = QSE_NULL;
|
2010-07-24 07:24:44 +00:00
|
|
|
*/
|
|
|
|
|
2014-11-14 02:44:20 +00:00
|
|
|
#if defined(QSE_XMA_ENABLE_STAT)
|
2010-07-25 06:43:26 +00:00
|
|
|
xma->stat.nused++;
|
|
|
|
xma->stat.alloc += free->size;
|
|
|
|
xma->stat.avail -= free->size;
|
2010-07-29 07:27:03 +00:00
|
|
|
#endif
|
2010-07-24 07:24:44 +00:00
|
|
|
return free;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return QSE_NULL;
|
|
|
|
}
|
|
|
|
|
2010-07-25 06:43:26 +00:00
|
|
|
void* qse_xma_alloc (qse_xma_t* xma, qse_size_t size)
|
2010-07-24 07:24:44 +00:00
|
|
|
{
|
|
|
|
qse_xma_blk_t* free;
|
|
|
|
qse_size_t xfi;
|
|
|
|
|
|
|
|
if (size <= 0) size = 1;
|
|
|
|
|
|
|
|
/* round up 'size' to the multiples of ALIGN */
|
2016-04-27 06:54:18 +00:00
|
|
|
size = QSE_ALIGNTO_POW2(size, ALIGN);
|
2010-07-24 07:24:44 +00:00
|
|
|
|
|
|
|
QSE_ASSERT (size >= ALIGN);
|
2010-07-31 07:24:19 +00:00
|
|
|
xfi = getxfi(xma,size);
|
2010-07-24 07:24:44 +00:00
|
|
|
|
2010-07-29 07:27:03 +00:00
|
|
|
/*if (xfi < XFIMAX(xma) && xma->xfree[xfi])*/
|
|
|
|
if (xfi < FIXED && xma->xfree[xfi])
|
2010-07-24 07:24:44 +00:00
|
|
|
{
|
|
|
|
/* try the best fit */
|
2010-07-25 06:43:26 +00:00
|
|
|
free = xma->xfree[xfi];
|
2010-07-24 07:24:44 +00:00
|
|
|
|
|
|
|
QSE_ASSERT (free->avail != 0);
|
|
|
|
QSE_ASSERT (free->size == size);
|
|
|
|
|
2010-07-29 07:27:03 +00:00
|
|
|
detach_from_freelist (xma, free);
|
2010-07-24 07:24:44 +00:00
|
|
|
free->avail = 0;
|
|
|
|
|
2014-11-14 02:44:20 +00:00
|
|
|
#if defined(QSE_XMA_ENABLE_STAT)
|
2010-07-25 06:43:26 +00:00
|
|
|
xma->stat.nfree--;
|
|
|
|
xma->stat.nused++;
|
|
|
|
xma->stat.alloc += free->size;
|
|
|
|
xma->stat.avail -= free->size;
|
2010-07-29 07:27:03 +00:00
|
|
|
#endif
|
2010-07-24 07:24:44 +00:00
|
|
|
}
|
2010-07-29 07:27:03 +00:00
|
|
|
else if (xfi == XFIMAX(xma))
|
2010-07-24 07:24:44 +00:00
|
|
|
{
|
2010-07-29 07:27:03 +00:00
|
|
|
/* huge block */
|
2010-07-25 06:43:26 +00:00
|
|
|
free = alloc_from_freelist (xma, XFIMAX(xma), size);
|
2010-07-29 07:27:03 +00:00
|
|
|
if (free == QSE_NULL) return QSE_NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (xfi >= FIXED)
|
|
|
|
{
|
|
|
|
/* get the block from its own large chain */
|
|
|
|
free = alloc_from_freelist (xma, xfi, size);
|
|
|
|
if (free == QSE_NULL)
|
|
|
|
{
|
|
|
|
/* 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 == QSE_NULL) xfi = FIXED - 1;
|
|
|
|
}
|
|
|
|
|
2010-07-24 07:24:44 +00:00
|
|
|
if (free == QSE_NULL)
|
|
|
|
{
|
2010-07-29 07:27:03 +00:00
|
|
|
/* try each large block chain left */
|
2010-07-25 06:43:26 +00:00
|
|
|
for (++xfi; xfi < XFIMAX(xma) - 1; xfi++)
|
2010-07-24 07:24:44 +00:00
|
|
|
{
|
2010-07-25 06:43:26 +00:00
|
|
|
free = alloc_from_freelist (xma, xfi, size);
|
2011-09-03 09:27:44 +00:00
|
|
|
if (free) break;
|
2010-07-24 07:24:44 +00:00
|
|
|
}
|
|
|
|
if (free == QSE_NULL) return QSE_NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return SYS_TO_USR(free);
|
|
|
|
}
|
|
|
|
|
2010-07-31 07:24:19 +00:00
|
|
|
static void* _realloc_merge (qse_xma_t* xma, void* b, qse_size_t size)
|
|
|
|
{
|
|
|
|
qse_xma_blk_t* blk = USR_TO_SYS(b);
|
|
|
|
|
2011-09-03 09:27:44 +00:00
|
|
|
/* rounds up 'size' to be multiples of ALIGN */
|
2016-04-27 06:54:18 +00:00
|
|
|
size = QSE_ALIGNTO_POW2 (size, ALIGN);
|
2011-09-03 09:27:44 +00:00
|
|
|
|
2010-07-31 07:24:19 +00:00
|
|
|
if (size > blk->size)
|
|
|
|
{
|
2010-08-26 07:15:40 +00:00
|
|
|
/*
|
|
|
|
* grow the current block
|
|
|
|
*/
|
2011-09-03 09:27:44 +00:00
|
|
|
qse_size_t req;
|
2010-07-31 07:24:19 +00:00
|
|
|
qse_xma_blk_t* n;
|
|
|
|
qse_size_t rem;
|
|
|
|
|
2011-09-03 09:27:44 +00:00
|
|
|
req = size - blk->size;
|
|
|
|
|
2010-07-31 07:24:19 +00:00
|
|
|
n = blk->b.next;
|
|
|
|
|
2010-08-26 07:15:40 +00:00
|
|
|
/* check if the next adjacent block is available */
|
|
|
|
if (!n || !n->avail || req > n->size) return QSE_NULL; /* no! */
|
2010-07-31 07:24:19 +00:00
|
|
|
|
2010-08-26 07:15:40 +00:00
|
|
|
/* let's merge the current block with the next block */
|
2010-07-31 07:24:19 +00:00
|
|
|
detach_from_freelist (xma, n);
|
|
|
|
|
|
|
|
rem = (HDRSIZE + n->size) - req;
|
|
|
|
if (rem >= MINBLKLEN)
|
|
|
|
{
|
2010-08-26 07:15:40 +00:00
|
|
|
/*
|
|
|
|
* the remaining part of the next block is large enough
|
|
|
|
* to hold a block. break the next block.
|
|
|
|
*/
|
|
|
|
|
2010-07-31 07:24:19 +00:00
|
|
|
qse_xma_blk_t* tmp;
|
2010-08-26 07:15:40 +00:00
|
|
|
|
2010-07-31 07:24:19 +00:00
|
|
|
/* store n->b.next in case 'tmp' begins somewhere
|
|
|
|
* in the header part of n */
|
|
|
|
qse_xma_blk_t* nn = n->b.next;
|
|
|
|
|
|
|
|
tmp = (qse_xma_blk_t*)(((qse_byte_t*)n) + req);
|
|
|
|
|
|
|
|
tmp->avail = 1;
|
|
|
|
tmp->size = rem - HDRSIZE;
|
|
|
|
attach_to_freelist (xma, tmp);
|
|
|
|
|
|
|
|
blk->size += req;
|
|
|
|
|
|
|
|
tmp->b.next = nn;
|
|
|
|
if (nn) nn->b.prev = tmp;
|
|
|
|
|
|
|
|
blk->b.next = tmp;
|
|
|
|
tmp->b.prev = blk;
|
|
|
|
|
2014-11-14 02:44:20 +00:00
|
|
|
#if defined(QSE_XMA_ENABLE_STAT)
|
2010-07-31 07:24:19 +00:00
|
|
|
xma->stat.alloc += req;
|
|
|
|
xma->stat.avail -= req; /* req + HDRSIZE(tmp) - HDRSIZE(n) */
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-08-26 07:15:40 +00:00
|
|
|
/* the remaining part of the next block is negligible.
|
|
|
|
* utilize the whole block by merging to the resizing block */
|
2010-07-31 07:24:19 +00:00
|
|
|
blk->size += HDRSIZE + n->size;
|
|
|
|
blk->b.next = n->b.next;
|
|
|
|
if (n->b.next) n->b.next->b.prev = blk;
|
|
|
|
|
2014-11-14 02:44:20 +00:00
|
|
|
#if defined(QSE_XMA_ENABLE_STAT)
|
2010-07-31 07:24:19 +00:00
|
|
|
xma->stat.nfree--;
|
|
|
|
xma->stat.alloc += HDRSIZE + n->size;
|
|
|
|
xma->stat.avail -= n->size;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (size < blk->size)
|
|
|
|
{
|
2010-08-26 07:15:40 +00:00
|
|
|
/*
|
|
|
|
* shrink the block
|
|
|
|
*/
|
|
|
|
|
2010-07-31 07:24:19 +00:00
|
|
|
qse_size_t rem = blk->size - size;
|
|
|
|
if (rem >= MINBLKLEN)
|
|
|
|
{
|
|
|
|
qse_xma_blk_t* tmp;
|
2010-08-01 01:45:47 +00:00
|
|
|
qse_xma_blk_t* n = blk->b.next;
|
2010-07-31 07:24:19 +00:00
|
|
|
|
|
|
|
/* the leftover is large enough to hold a block
|
|
|
|
* of minimum size. split the current block.
|
|
|
|
* let 'tmp' point to the leftover. */
|
|
|
|
tmp = (qse_xma_blk_t*)(((qse_byte_t*)(blk + 1)) + size);
|
|
|
|
tmp->avail = 1;
|
|
|
|
|
2010-08-01 01:45:47 +00:00
|
|
|
if (n && n->avail)
|
|
|
|
{
|
|
|
|
/* merge with the next block */
|
|
|
|
detach_from_freelist (xma, n);
|
2010-07-31 07:24:19 +00:00
|
|
|
|
2010-08-01 01:45:47 +00:00
|
|
|
tmp->b.next = n->b.next;
|
|
|
|
tmp->b.prev = blk;
|
|
|
|
if (n->b.next) n->b.next->b.prev = tmp;
|
|
|
|
blk->b.next = tmp;
|
|
|
|
blk->size = size;
|
2010-07-31 07:24:19 +00:00
|
|
|
|
2010-08-01 01:45:47 +00:00
|
|
|
tmp->size = rem - HDRSIZE + HDRSIZE + n->size;
|
2010-07-31 07:24:19 +00:00
|
|
|
|
2014-11-14 02:44:20 +00:00
|
|
|
#if defined(QSE_XMA_ENABLE_STAT)
|
2010-08-01 01:45:47 +00:00
|
|
|
xma->stat.alloc -= rem;
|
|
|
|
/* rem - HDRSIZE(tmp) + HDRSIZE(n) */
|
|
|
|
xma->stat.avail += rem;
|
2010-07-31 07:24:19 +00:00
|
|
|
#endif
|
2010-08-01 01:45:47 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* link 'tmp' to the block list */
|
|
|
|
tmp->b.next = n;
|
|
|
|
tmp->b.prev = blk;
|
|
|
|
if (n) n->b.prev = tmp;
|
|
|
|
blk->b.next = tmp;
|
|
|
|
blk->size = size;
|
|
|
|
|
|
|
|
tmp->size = rem - HDRSIZE;
|
|
|
|
|
2014-11-14 02:44:20 +00:00
|
|
|
#if defined(QSE_XMA_ENABLE_STAT)
|
2010-08-01 01:45:47 +00:00
|
|
|
xma->stat.nfree++;
|
|
|
|
xma->stat.alloc -= rem;
|
|
|
|
xma->stat.avail += tmp->size;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/* add 'tmp' to the free list */
|
|
|
|
attach_to_freelist (xma, tmp);
|
2010-07-31 07:24:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return b;
|
|
|
|
}
|
|
|
|
|
2011-08-22 23:26:26 +00:00
|
|
|
void* qse_xma_calloc (qse_xma_t* xma, qse_size_t size)
|
|
|
|
{
|
|
|
|
void* ptr = qse_xma_alloc (xma, size);
|
2012-12-01 13:13:13 +00:00
|
|
|
if (ptr) QSE_MEMSET (ptr, 0, size);
|
2011-08-22 23:26:26 +00:00
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
2010-07-29 07:27:03 +00:00
|
|
|
void* qse_xma_realloc (qse_xma_t* xma, void* b, qse_size_t size)
|
|
|
|
{
|
2010-07-31 07:24:19 +00:00
|
|
|
void* n;
|
|
|
|
|
|
|
|
if (b == QSE_NULL)
|
|
|
|
{
|
|
|
|
/* 'realloc' with NULL is the same as 'alloc' */
|
|
|
|
n = qse_xma_alloc (xma, size);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* try reallocation by merging the adjacent continuous blocks */
|
|
|
|
n = _realloc_merge (xma, b, size);
|
|
|
|
if (n == QSE_NULL)
|
|
|
|
{
|
|
|
|
/* reallocation by merging failed. fall back to the slow
|
|
|
|
* allocation-copy-free scheme */
|
|
|
|
n = qse_xma_alloc (xma, size);
|
|
|
|
if (n)
|
|
|
|
{
|
|
|
|
QSE_MEMCPY (n, b, size);
|
|
|
|
qse_xma_free (xma, b);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return n;
|
2010-07-29 07:27:03 +00:00
|
|
|
}
|
|
|
|
|
2010-07-25 06:43:26 +00:00
|
|
|
void qse_xma_free (qse_xma_t* xma, void* b)
|
2010-07-24 07:24:44 +00:00
|
|
|
{
|
|
|
|
qse_xma_blk_t* blk = USR_TO_SYS(b);
|
|
|
|
|
2010-07-25 06:43:26 +00:00
|
|
|
/*QSE_ASSERT (blk->f.next == QSE_NULL);*/
|
2010-07-24 07:24:44 +00:00
|
|
|
|
2014-11-14 02:44:20 +00:00
|
|
|
#if defined(QSE_XMA_ENABLE_STAT)
|
2010-07-24 07:24:44 +00:00
|
|
|
/* update statistical variables */
|
2010-07-25 06:43:26 +00:00
|
|
|
xma->stat.nused--;
|
|
|
|
xma->stat.alloc -= blk->size;
|
2010-07-29 07:27:03 +00:00
|
|
|
#endif
|
2010-07-24 07:24:44 +00:00
|
|
|
|
2010-07-25 06:43:26 +00:00
|
|
|
if ((blk->b.prev && blk->b.prev->avail) &&
|
|
|
|
(blk->b.next && blk->b.next->avail))
|
2010-07-24 07:24:44 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Merge the block with surrounding blocks
|
|
|
|
*
|
|
|
|
* blk
|
|
|
|
* +-----+ | +-----+ +------+
|
|
|
|
* | V v | v | V
|
|
|
|
* +------------+------------+------------+------------+
|
|
|
|
* | X | | Y | Z |
|
|
|
|
* +------------+------------+------------+------------+
|
|
|
|
* ^ | ^ | ^ |
|
|
|
|
* +-----+ +------+ +------+
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* +-----------------------------------+
|
|
|
|
* | V
|
|
|
|
* +--------------------------------------+------------+
|
|
|
|
* | X | Z |
|
|
|
|
* +--------------------------------------+------------+
|
|
|
|
* ^ |
|
|
|
|
* +-----------------------------------+
|
|
|
|
*/
|
2010-07-25 06:43:26 +00:00
|
|
|
qse_xma_blk_t* x = blk->b.prev;
|
|
|
|
qse_xma_blk_t* y = blk->b.next;
|
|
|
|
qse_xma_blk_t* z = y->b.next;
|
2010-07-31 07:24:19 +00:00
|
|
|
qse_size_t ns = HDRSIZE + blk->size + HDRSIZE;
|
|
|
|
qse_size_t bs = ns + y->size;
|
2010-07-24 07:24:44 +00:00
|
|
|
|
2010-07-29 07:27:03 +00:00
|
|
|
detach_from_freelist (xma, x);
|
|
|
|
detach_from_freelist (xma, y);
|
2010-07-24 07:24:44 +00:00
|
|
|
|
|
|
|
x->size += bs;
|
2010-07-25 06:43:26 +00:00
|
|
|
x->b.next = z;
|
|
|
|
if (z) z->b.prev = x;
|
2010-07-24 07:24:44 +00:00
|
|
|
|
2010-07-29 07:27:03 +00:00
|
|
|
attach_to_freelist (xma, x);
|
2010-07-24 07:24:44 +00:00
|
|
|
|
2014-11-14 02:44:20 +00:00
|
|
|
#if defined(QSE_XMA_ENABLE_STAT)
|
2010-07-25 06:43:26 +00:00
|
|
|
xma->stat.nfree--;
|
2010-07-31 07:24:19 +00:00
|
|
|
xma->stat.avail += ns;
|
2010-07-29 07:27:03 +00:00
|
|
|
#endif
|
2010-07-24 07:24:44 +00:00
|
|
|
}
|
2010-07-25 06:43:26 +00:00
|
|
|
else if (blk->b.next && blk->b.next->avail)
|
2010-07-24 07:24:44 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Merge the block with the next block
|
|
|
|
*
|
|
|
|
* blk
|
|
|
|
* | +-----+ +------+
|
|
|
|
* v | v | V
|
|
|
|
* +------------+------------+------------+
|
|
|
|
* | | X | Y |
|
|
|
|
* +------------+------------+------------+
|
|
|
|
* ^ | ^ |
|
|
|
|
* +------+ +------+
|
|
|
|
*
|
|
|
|
* blk
|
|
|
|
* | +------------------+
|
|
|
|
* v | V
|
|
|
|
* +-------------------------+------------+
|
|
|
|
* | | Y |
|
|
|
|
* +-------------------------+------------+
|
|
|
|
* ^ |
|
|
|
|
* +-------------------+
|
|
|
|
*/
|
2010-07-25 06:43:26 +00:00
|
|
|
qse_xma_blk_t* x = blk->b.next;
|
|
|
|
qse_xma_blk_t* y = x->b.next;
|
2010-07-31 07:24:19 +00:00
|
|
|
|
2014-11-14 02:44:20 +00:00
|
|
|
#if defined(QSE_XMA_ENABLE_STAT)
|
2010-07-31 07:24:19 +00:00
|
|
|
xma->stat.avail += blk->size + HDRSIZE;
|
|
|
|
#endif
|
2010-07-24 07:24:44 +00:00
|
|
|
|
|
|
|
/* detach x from the free list */
|
2010-07-29 07:27:03 +00:00
|
|
|
detach_from_freelist (xma, x);
|
2010-07-24 07:24:44 +00:00
|
|
|
|
|
|
|
/* update the block availability */
|
|
|
|
blk->avail = 1;
|
|
|
|
/* update the block size. HDRSIZE for the header space in x */
|
2010-07-31 07:24:19 +00:00
|
|
|
blk->size += HDRSIZE + x->size;
|
2010-07-24 07:24:44 +00:00
|
|
|
|
|
|
|
/* update the backward link of Y */
|
2010-07-25 06:43:26 +00:00
|
|
|
if (y) y->b.prev = blk;
|
2010-07-24 07:24:44 +00:00
|
|
|
/* update the forward link of the block being freed */
|
2010-07-25 06:43:26 +00:00
|
|
|
blk->b.next = y;
|
2010-07-24 07:24:44 +00:00
|
|
|
|
|
|
|
/* attach blk to the free list */
|
2010-07-29 07:27:03 +00:00
|
|
|
attach_to_freelist (xma, blk);
|
2010-07-24 07:24:44 +00:00
|
|
|
|
|
|
|
}
|
2010-07-25 06:43:26 +00:00
|
|
|
else if (blk->b.prev && blk->b.prev->avail)
|
2010-07-24 07:24:44 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Merge the block with the previous block
|
|
|
|
*
|
|
|
|
* blk
|
|
|
|
* +-----+ | +-----+
|
|
|
|
* | V v | v
|
|
|
|
* +------------+------------+------------+
|
|
|
|
* | X | | Y |
|
|
|
|
* +------------+------------+------------+
|
|
|
|
* ^ | ^ |
|
|
|
|
* +------+ +------+
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* +---------------------+
|
|
|
|
* | v
|
|
|
|
* +-------------------------+------------+
|
|
|
|
* | X | Y |
|
|
|
|
* +-------------------------+------------+
|
|
|
|
* ^ |
|
|
|
|
* +--------------------+
|
|
|
|
*
|
|
|
|
*/
|
2010-07-25 06:43:26 +00:00
|
|
|
qse_xma_blk_t* x = blk->b.prev;
|
|
|
|
qse_xma_blk_t* y = blk->b.next;
|
2010-07-31 07:24:19 +00:00
|
|
|
|
2014-11-14 02:44:20 +00:00
|
|
|
#if defined(QSE_XMA_ENABLE_STAT)
|
2010-07-31 07:24:19 +00:00
|
|
|
xma->stat.avail += HDRSIZE + blk->size;
|
|
|
|
#endif
|
2010-07-24 07:24:44 +00:00
|
|
|
|
2010-07-29 07:27:03 +00:00
|
|
|
detach_from_freelist (xma, x);
|
2010-07-24 07:24:44 +00:00
|
|
|
|
2010-07-31 07:24:19 +00:00
|
|
|
x->size += HDRSIZE + blk->size;
|
2010-07-25 06:43:26 +00:00
|
|
|
x->b.next = y;
|
|
|
|
if (y) y->b.prev = x;
|
2010-07-24 07:24:44 +00:00
|
|
|
|
2010-07-29 07:27:03 +00:00
|
|
|
attach_to_freelist (xma, x);
|
2010-07-24 07:24:44 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
blk->avail = 1;
|
2010-07-29 07:27:03 +00:00
|
|
|
attach_to_freelist (xma, blk);
|
2010-07-24 07:24:44 +00:00
|
|
|
|
2014-11-14 02:44:20 +00:00
|
|
|
#if defined(QSE_XMA_ENABLE_STAT)
|
2010-07-25 06:43:26 +00:00
|
|
|
xma->stat.nfree++;
|
|
|
|
xma->stat.avail += blk->size;
|
2010-07-29 07:27:03 +00:00
|
|
|
#endif
|
2010-07-24 07:24:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-21 10:17:16 +00:00
|
|
|
void qse_xma_dump (qse_xma_t* xma, qse_xma_dumper_t dumper, void* ctx)
|
2010-07-24 07:24:44 +00:00
|
|
|
{
|
|
|
|
qse_xma_blk_t* tmp;
|
2010-10-22 07:29:12 +00:00
|
|
|
qse_ulong_t fsum, asum;
|
2014-11-14 02:44:20 +00:00
|
|
|
#if defined(QSE_XMA_ENABLE_STAT)
|
2010-10-22 07:29:12 +00:00
|
|
|
qse_ulong_t isum;
|
2010-07-31 07:24:19 +00:00
|
|
|
#endif
|
2010-07-24 07:24:44 +00:00
|
|
|
|
2011-07-21 10:17:16 +00:00
|
|
|
dumper (ctx, QSE_T("<XMA DUMP>\n"));
|
2010-10-22 07:29:12 +00:00
|
|
|
|
2014-11-14 02:44:20 +00:00
|
|
|
#if defined(QSE_XMA_ENABLE_STAT)
|
2011-07-21 10:17:16 +00:00
|
|
|
dumper (ctx, QSE_T("== statistics ==\n"));
|
2011-08-12 09:11:02 +00:00
|
|
|
#if (QSE_SIZEOF_SIZE_T == QSE_SIZEOF_LONG)
|
2011-07-21 10:17:16 +00:00
|
|
|
dumper (ctx, QSE_T("total = %lu\n"), (unsigned long)xma->stat.total);
|
|
|
|
dumper (ctx, QSE_T("alloc = %lu\n"), (unsigned long)xma->stat.alloc);
|
|
|
|
dumper (ctx, QSE_T("avail = %lu\n"), (unsigned long)xma->stat.avail);
|
2011-08-12 09:11:02 +00:00
|
|
|
#elif (QSE_SIZEOF_SIZE_T == QSE_SIZEOF_LONG_LONG)
|
2011-07-21 10:17:16 +00:00
|
|
|
dumper (ctx, QSE_T("total = %llu\n"), (unsigned long long)xma->stat.total);
|
|
|
|
dumper (ctx, QSE_T("alloc = %llu\n"), (unsigned long long)xma->stat.alloc);
|
|
|
|
dumper (ctx, QSE_T("avail = %llu\n"), (unsigned long long)xma->stat.avail);
|
2011-08-12 09:11:02 +00:00
|
|
|
#elif (QSE_SIZEOF_SIZE_T == QSE_SIZEOF_INT)
|
|
|
|
dumper (ctx, QSE_T("total = %u\n"), (unsigned int)xma->stat.total);
|
|
|
|
dumper (ctx, QSE_T("alloc = %u\n"), (unsigned int)xma->stat.alloc);
|
|
|
|
dumper (ctx, QSE_T("avail = %u\n"), (unsigned int)xma->stat.avail);
|
|
|
|
#else
|
|
|
|
# error weird size of qse_size_t. unsupported platform
|
2010-10-22 07:29:12 +00:00
|
|
|
#endif
|
2010-07-31 07:24:19 +00:00
|
|
|
#endif
|
2010-07-24 07:24:44 +00:00
|
|
|
|
2011-07-21 10:17:16 +00:00
|
|
|
dumper (ctx, QSE_T("== blocks ==\n"));
|
|
|
|
dumper (ctx, QSE_T(" size avail address\n"));
|
2010-07-25 06:43:26 +00:00
|
|
|
for (tmp = xma->head, fsum = 0, asum = 0; tmp; tmp = tmp->b.next)
|
2010-07-24 07:24:44 +00:00
|
|
|
{
|
2011-08-12 09:11:02 +00:00
|
|
|
#if (QSE_SIZEOF_SIZE_T == QSE_SIZEOF_LONG)
|
|
|
|
dumper (ctx, QSE_T(" %-18lu %-5u %p\n"),
|
|
|
|
(unsigned long)tmp->size, (unsigned int)tmp->avail, tmp
|
2010-10-22 07:29:12 +00:00
|
|
|
);
|
2011-08-12 09:11:02 +00:00
|
|
|
#elif (QSE_SIZEOF_SIZE_T == QSE_SIZEOF_LONG_LONG)
|
|
|
|
dumper (ctx, QSE_T(" %-18llu %-5u %p\n"),
|
|
|
|
(unsigned long long)tmp->size, (unsigned int)tmp->avail, tmp
|
2010-10-22 07:29:12 +00:00
|
|
|
);
|
2011-08-12 09:11:02 +00:00
|
|
|
#elif (QSE_SIZEOF_SIZE_T == QSE_SIZEOF_INT)
|
|
|
|
dumper (ctx, QSE_T(" %-18u %-5u %p\n"),
|
|
|
|
(unsigned int)tmp->size, (unsigned int)tmp->avail, tmp
|
|
|
|
);
|
|
|
|
#else
|
|
|
|
# error weird size of qse_size_t. unsupported platform
|
2010-10-22 07:29:12 +00:00
|
|
|
#endif
|
2010-07-24 07:24:44 +00:00
|
|
|
if (tmp->avail) fsum += tmp->size;
|
|
|
|
else asum += tmp->size;
|
|
|
|
}
|
|
|
|
|
2014-11-14 02:44:20 +00:00
|
|
|
#if defined(QSE_XMA_ENABLE_STAT)
|
2010-07-25 06:43:26 +00:00
|
|
|
isum = (xma->stat.nfree + xma->stat.nused) * HDRSIZE;
|
2010-07-31 07:24:19 +00:00
|
|
|
#endif
|
2010-07-24 07:24:44 +00:00
|
|
|
|
2011-07-21 10:17:16 +00:00
|
|
|
dumper (ctx, QSE_T("---------------------------------------\n"));
|
2011-08-12 09:11:02 +00:00
|
|
|
#if (QSE_SIZEOF_ULONG_T == QSE_SIZEOF_LONG)
|
2011-07-21 10:17:16 +00:00
|
|
|
dumper (ctx, QSE_T("Allocated blocks: %18lu bytes\n"), (unsigned long)asum);
|
|
|
|
dumper (ctx, QSE_T("Available blocks: %18lu bytes\n"), (unsigned long)fsum);
|
2011-08-12 09:11:02 +00:00
|
|
|
#elif (QSE_SIZEOF_ULONG_T == QSE_SIZEOF_LONG_LONG)
|
2011-07-21 10:17:16 +00:00
|
|
|
dumper (ctx, QSE_T("Allocated blocks: %18llu bytes\n"), (unsigned long long)asum);
|
|
|
|
dumper (ctx, QSE_T("Available blocks: %18llu bytes\n"), (unsigned long long)fsum);
|
2011-08-12 09:11:02 +00:00
|
|
|
#elif (QSE_SIZEOF_ULONG_T == QSE_SIZEOF_INT)
|
|
|
|
dumper (ctx, QSE_T("Allocated blocks: %18u bytes\n"), (unsigned int)asum);
|
|
|
|
dumper (ctx, QSE_T("Available blocks: %18u bytes\n"), (unsigned int)fsum);
|
|
|
|
#else
|
|
|
|
# error weird size of qse_ulong_t. unsupported platform
|
2010-10-22 07:29:12 +00:00
|
|
|
#endif
|
|
|
|
|
2014-11-14 02:44:20 +00:00
|
|
|
#if defined(QSE_XMA_ENABLE_STAT)
|
2011-08-12 09:11:02 +00:00
|
|
|
#if (QSE_SIZEOF_ULONG_T == QSE_SIZEOF_LONG)
|
2011-07-21 10:17:16 +00:00
|
|
|
dumper (ctx, QSE_T("Internal use : %18lu bytes\n"), (unsigned long)isum);
|
|
|
|
dumper (ctx, QSE_T("Total : %18lu bytes\n"), (unsigned long)(asum + fsum + isum));
|
2011-08-12 09:11:02 +00:00
|
|
|
#elif (QSE_SIZEOF_ULONG_T == QSE_SIZEOF_LONG_LONG)
|
2011-07-21 10:17:16 +00:00
|
|
|
dumper (ctx, QSE_T("Internal use : %18llu bytes\n"), (unsigned long long)isum);
|
|
|
|
dumper (ctx, QSE_T("Total : %18llu bytes\n"), (unsigned long long)(asum + fsum + isum));
|
2011-08-12 09:11:02 +00:00
|
|
|
#elif (QSE_SIZEOF_ULONG_T == QSE_SIZEOF_INT)
|
|
|
|
dumper (ctx, QSE_T("Internal use : %18u bytes\n"), (unsigned int)isum);
|
|
|
|
dumper (ctx, QSE_T("Total : %18u bytes\n"), (unsigned int)(asum + fsum + isum));
|
|
|
|
#else
|
|
|
|
# error weird size of qse_ulong_t. unsupported platform
|
2010-10-22 07:29:12 +00:00
|
|
|
#endif
|
2010-07-31 07:24:19 +00:00
|
|
|
#endif
|
2011-03-17 02:37:06 +00:00
|
|
|
|
2014-11-14 02:44:20 +00:00
|
|
|
#if defined(QSE_XMA_ENABLE_STAT)
|
2010-08-01 01:45:47 +00:00
|
|
|
QSE_ASSERT (asum == xma->stat.alloc);
|
|
|
|
QSE_ASSERT (fsum == xma->stat.avail);
|
|
|
|
QSE_ASSERT (isum == xma->stat.total - (xma->stat.alloc + xma->stat.avail));
|
|
|
|
QSE_ASSERT (asum + fsum + isum == xma->stat.total);
|
2010-07-24 07:24:44 +00:00
|
|
|
#endif
|
2010-08-01 01:45:47 +00:00
|
|
|
}
|
|
|
|
|