backporting of xma
This commit is contained in:
@ -1,6 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
* $Id$
|
|
||||||
*
|
|
||||||
Copyright (c) 2014-2019 Chung, Hyung-Hwan. All rights reserved.
|
Copyright (c) 2014-2019 Chung, Hyung-Hwan. All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@ -52,15 +50,15 @@
|
|||||||
* moo_xma_t* xma;
|
* moo_xma_t* xma;
|
||||||
* void* ptr1, * ptr2;
|
* void* ptr1, * ptr2;
|
||||||
*
|
*
|
||||||
* // create a new memory allocator obtaining a 100K byte zone
|
* // create a new memory allocator obtaining a 100K byte zone
|
||||||
* // with the default memory allocator
|
* // with the default memory allocator
|
||||||
* xma = moo_xma_open(MOO_NULL, 0, 100000L);
|
* xma = moo_xma_open(MOO_NULL, 0, 100000L);
|
||||||
*
|
*
|
||||||
* ptr1 = moo_xma_alloc(xma, 5000); // allocate a 5K block from the zone
|
* ptr1 = moo_xma_alloc(xma, 5000); // allocate a 5K block from the zone
|
||||||
* ptr2 = moo_xma_alloc(xma, 1000); // allocate a 1K block from the zone
|
* ptr2 = moo_xma_alloc(xma, 1000); // allocate a 1K block from the zone
|
||||||
* ptr1 = moo_xma_realloc(xma, ptr1, 6000); // resize the 5K block to 6K.
|
* ptr1 = moo_xma_realloc(xma, ptr1, 6000); // resize the 5K block to 6K.
|
||||||
*
|
*
|
||||||
* moo_xma_dump (xma, dumper, MOO_NULL); // dump memory blocks
|
* moo_xma_dump (xma, dumper, MOO_NULL); // dump memory blocks
|
||||||
*
|
*
|
||||||
* // the following two lines are not actually needed as the allocator
|
* // the following two lines are not actually needed as the allocator
|
||||||
* // is closed after them.
|
* // is closed after them.
|
||||||
@ -74,9 +72,7 @@
|
|||||||
*/
|
*/
|
||||||
#include <moo-cmn.h>
|
#include <moo-cmn.h>
|
||||||
|
|
||||||
#ifdef MOO_BUILD_DEBUG
|
#define MOO_XMA_ENABLE_STAT
|
||||||
# define MOO_XMA_ENABLE_STAT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** @struct moo_xma_t
|
/** @struct moo_xma_t
|
||||||
* The moo_xma_t type defines a simple memory allocator over a memory zone.
|
* The moo_xma_t type defines a simple memory allocator over a memory zone.
|
||||||
@ -90,7 +86,7 @@ typedef struct moo_xma_t moo_xma_t;
|
|||||||
typedef struct moo_xma_fblk_t moo_xma_fblk_t;
|
typedef struct moo_xma_fblk_t moo_xma_fblk_t;
|
||||||
typedef struct moo_xma_mblk_t moo_xma_mblk_t;
|
typedef struct moo_xma_mblk_t moo_xma_mblk_t;
|
||||||
|
|
||||||
#define MOO_XMA_FIXED 32
|
#define MOO_XMA_FIXED (32)
|
||||||
#define MOO_XMA_SIZE_BITS ((MOO_SIZEOF_OOW_T*8)-1)
|
#define MOO_XMA_SIZE_BITS ((MOO_SIZEOF_OOW_T*8)-1)
|
||||||
|
|
||||||
struct moo_xma_t
|
struct moo_xma_t
|
||||||
@ -102,19 +98,27 @@ struct moo_xma_t
|
|||||||
int internal;
|
int internal;
|
||||||
|
|
||||||
/** pointer array to free memory blocks */
|
/** pointer array to free memory blocks */
|
||||||
moo_xma_fblk_t* xfree[MOO_XMA_FIXED + MOO_XMA_SIZE_BITS + 1];
|
moo_xma_fblk_t* xfree[MOO_XMA_FIXED + MOO_XMA_SIZE_BITS + 1];
|
||||||
|
|
||||||
/** pre-computed value for fast xfree index calculation */
|
/** pre-computed value for fast xfree index calculation */
|
||||||
moo_oow_t bdec;
|
moo_oow_t bdec;
|
||||||
|
|
||||||
#ifdef MOO_XMA_ENABLE_STAT
|
#if defined(MOO_XMA_ENABLE_STAT)
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
moo_oow_t total;
|
moo_oow_t total;
|
||||||
moo_oow_t alloc;
|
moo_oow_t alloc; /* allocated size */
|
||||||
moo_oow_t avail;
|
moo_oow_t avail; /* available size */
|
||||||
moo_oow_t nused;
|
moo_oow_t nused; /* nubmer of used blocks */
|
||||||
moo_oow_t nfree;
|
moo_oow_t nfree; /* number of free blocks */
|
||||||
|
moo_oow_t alloc_hwmark; /* high watermark - highest total memory ever allocated */
|
||||||
|
moo_oow_t nallocops; /* number of alloc operations */
|
||||||
|
moo_oow_t nallocgoodops; /* number of successful alloc operations */
|
||||||
|
moo_oow_t nallocbadops; /* number of failed alloc operations */
|
||||||
|
moo_oow_t nreallocops; /* number of realloc operations */
|
||||||
|
moo_oow_t nreallocgoodops; /* number of good realloc operations */
|
||||||
|
moo_oow_t nreallocbadops; /* number of failed realloc operations - could fall back to normal alloc*/
|
||||||
|
moo_oow_t nfreeops; /* number of free operations */
|
||||||
} stat;
|
} stat;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
@ -150,7 +154,7 @@ MOO_EXPORT moo_xma_t* moo_xma_open (
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The moo_xma_close() function destroys a memory allocator. It also frees
|
* The moo_xma_close() function destroys a memory allocator. It also frees
|
||||||
* the memory zone obtained, which invalidates the memory blocks within
|
* the memory zone obtained, which invalidates the memory blocks within
|
||||||
* the zone. Call this function to destroy a memory allocator created with
|
* the zone. Call this function to destroy a memory allocator created with
|
||||||
* moo_xma_open().
|
* moo_xma_open().
|
||||||
*/
|
*/
|
||||||
@ -186,7 +190,7 @@ MOO_EXPORT int moo_xma_init (
|
|||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The moo_xma_fini() function finalizes a memory allocator. Call this
|
* The moo_xma_fini() function finalizes a memory allocator. Call this
|
||||||
* function to finalize a memory allocator initialized with moo_xma_init().
|
* function to finalize a memory allocator initialized with moo_xma_init().
|
||||||
*/
|
*/
|
||||||
MOO_EXPORT void moo_xma_fini (
|
MOO_EXPORT void moo_xma_fini (
|
||||||
|
415
lib/xma.c
415
lib/xma.c
@ -1,6 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
* $Id$
|
|
||||||
*
|
|
||||||
Copyright (c) 2014-2019 Chung, Hyung-Hwan. All rights reserved.
|
Copyright (c) 2014-2019 Chung, Hyung-Hwan. All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@ -26,12 +24,12 @@
|
|||||||
|
|
||||||
#include <moo-xma.h>
|
#include <moo-xma.h>
|
||||||
#include "moo-prv.h"
|
#include "moo-prv.h"
|
||||||
#include <assert.h> /* TODO: replace assert() with builtin substition */
|
#include <assert.h> /* TODO: replace assert() with MOO_ASSERT() or something */
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* in the following run, movaps tries to write to the address 0x7fffea722f78.
|
* in the following run, movaps tries to write to the address 0x7fffea722f78.
|
||||||
* since the instruction deals with 16-byte aligned data only, it triggered
|
* since the instruction deals with 16-byte aligned data only, it triggered
|
||||||
* the general protection error.
|
* the general protection error.
|
||||||
*
|
*
|
||||||
$ gdb ~/xxx/bin/xxx
|
$ gdb ~/xxx/bin/xxx
|
||||||
@ -67,9 +65,23 @@ $1 = (xxx_int_t *) 0x7fffea722f78
|
|||||||
#define FIXED MOO_XMA_FIXED
|
#define FIXED MOO_XMA_FIXED
|
||||||
#define XFIMAX(xma) (MOO_COUNTOF(xma->xfree)-1)
|
#define XFIMAX(xma) (MOO_COUNTOF(xma->xfree)-1)
|
||||||
|
|
||||||
|
|
||||||
|
#define fblk_free(b) (((moo_xma_fblk_t*)(b))->free)
|
||||||
|
#define fblk_size(b) (((moo_xma_fblk_t*)(b))->size)
|
||||||
|
#define fblk_prev_size(b) (((moo_xma_fblk_t*)(b))->prev_size)
|
||||||
|
#if 0
|
||||||
|
#define mblk_free(b) (((moo_xma_mblk_t*)(b))->free)
|
||||||
#define mblk_size(b) (((moo_xma_mblk_t*)(b))->size)
|
#define mblk_size(b) (((moo_xma_mblk_t*)(b))->size)
|
||||||
#define mblk_prev_size(b) (((moo_xma_mblk_t*)(b))->prev_size)
|
#define mblk_prev_size(b) (((moo_xma_mblk_t*)(b))->prev_size)
|
||||||
|
#else
|
||||||
|
/* Let mblk_free(), mblk_size(), mblk_prev_size() be an alias to
|
||||||
|
* fblk_free(), fblk_size(), fblk_prev_size() to follow strict aliasing rule.
|
||||||
|
* if gcc/clang is used, specifying __attribute__((__may_alias__)) to moo_xma_mblk_t
|
||||||
|
* and moo_xma_fblk_t would also work. */
|
||||||
|
#define mblk_free(b) fblk_free(b)
|
||||||
|
#define mblk_size(b) fblk_size(b)
|
||||||
|
#define mblk_prev_size(b) fblk_prev_size(b)
|
||||||
|
#endif
|
||||||
#define next_mblk(b) ((moo_xma_mblk_t*)((moo_uint8_t*)b + MBLKHDRSIZE + mblk_size(b)))
|
#define next_mblk(b) ((moo_xma_mblk_t*)((moo_uint8_t*)b + MBLKHDRSIZE + mblk_size(b)))
|
||||||
#define prev_mblk(b) ((moo_xma_mblk_t*)((moo_uint8_t*)b - (MBLKHDRSIZE + mblk_prev_size(b))))
|
#define prev_mblk(b) ((moo_xma_mblk_t*)((moo_uint8_t*)b - (MBLKHDRSIZE + mblk_prev_size(b))))
|
||||||
|
|
||||||
@ -79,22 +91,23 @@ struct moo_xma_mblk_t
|
|||||||
|
|
||||||
/* the block size is shifted by 1 bit and the maximum value is
|
/* the block size is shifted by 1 bit and the maximum value is
|
||||||
* offset by 1 bit because of the 'free' bit-field.
|
* offset by 1 bit because of the 'free' bit-field.
|
||||||
* i could keep 'size' without shifting with bit manipulation
|
* i could keep 'size' without shifting with bit manipulation
|
||||||
* because the actual size is aligned and the last bit will
|
* because the actual size is aligned and the last bit will
|
||||||
* never be 1. i don't think there is a practical use case where
|
* never be 1. i don't think there is a practical use case where
|
||||||
* you need to allocate a huge chunk covering the entire
|
* you need to allocate a huge chunk covering the entire
|
||||||
* address space of your machine. */
|
* address space of your machine. */
|
||||||
moo_oow_t free: 1;
|
moo_oow_t free: 1;
|
||||||
moo_oow_t size: MOO_XMA_SIZE_BITS; /**< block size */
|
moo_oow_t size: MOO_XMA_SIZE_BITS; /**< block size */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct moo_xma_fblk_t
|
struct moo_xma_fblk_t
|
||||||
{
|
{
|
||||||
moo_oow_t prev_size;
|
moo_oow_t prev_size;
|
||||||
moo_oow_t free: 1;
|
moo_oow_t free: 1;
|
||||||
moo_oow_t size: MOO_XMA_SIZE_BITS;/**< block size */
|
moo_oow_t size: MOO_XMA_SIZE_BITS;/**< block size */
|
||||||
|
|
||||||
/* these two fields are used only if the block is free */
|
/* the fields are must be identical to the fields of moo_xma_mblk_t */
|
||||||
|
/* the two fields below are used only if the block is free */
|
||||||
moo_xma_fblk_t* free_prev; /**< link to the previous free block */
|
moo_xma_fblk_t* free_prev; /**< link to the previous free block */
|
||||||
moo_xma_fblk_t* free_next; /**< link to the next free block */
|
moo_xma_fblk_t* free_next; /**< link to the next free block */
|
||||||
};
|
};
|
||||||
@ -105,7 +118,7 @@ static void DBG_VERIFY (moo_xma_t* xma, const char* desc)
|
|||||||
{
|
{
|
||||||
moo_xma_mblk_t* tmp, * next;
|
moo_xma_mblk_t* tmp, * next;
|
||||||
moo_oow_t cnt;
|
moo_oow_t cnt;
|
||||||
moo_oow_t fsum, asum;
|
moo_oow_t fsum, asum;
|
||||||
#if defined(MOO_XMA_ENABLE_STAT)
|
#if defined(MOO_XMA_ENABLE_STAT)
|
||||||
moo_oow_t isum;
|
moo_oow_t isum;
|
||||||
#endif
|
#endif
|
||||||
@ -139,7 +152,7 @@ static void DBG_VERIFY (moo_xma_t* xma, const char* desc)
|
|||||||
#define DBG_VERIFY(xma, desc)
|
#define DBG_VERIFY(xma, desc)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static MOO_INLINE moo_oow_t szlog2 (moo_oow_t n)
|
static MOO_INLINE moo_oow_t szlog2 (moo_oow_t n)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* 2**x = n;
|
* 2**x = n;
|
||||||
@ -169,7 +182,7 @@ static MOO_INLINE moo_oow_t szlog2 (moo_oow_t n)
|
|||||||
#if MOO_SIZEOF_OOW_T >= 8
|
#if MOO_SIZEOF_OOW_T >= 8
|
||||||
if ((n & (~(moo_oow_t)0 << (BITS-32))) == 0) { x -= 32; n <<= 32; }
|
if ((n & (~(moo_oow_t)0 << (BITS-32))) == 0) { x -= 32; n <<= 32; }
|
||||||
#endif
|
#endif
|
||||||
#if MOO_SIZEOF_OOW_T >= 4
|
#if MOO_SIZEOF_OOW_T >= 4
|
||||||
if ((n & (~(moo_oow_t)0 << (BITS-16))) == 0) { x -= 16; n <<= 16; }
|
if ((n & (~(moo_oow_t)0 << (BITS-16))) == 0) { x -= 16; n <<= 16; }
|
||||||
#endif
|
#endif
|
||||||
#if MOO_SIZEOF_OOW_T >= 2
|
#if MOO_SIZEOF_OOW_T >= 2
|
||||||
@ -185,7 +198,7 @@ static MOO_INLINE moo_oow_t szlog2 (moo_oow_t n)
|
|||||||
#undef BITS
|
#undef BITS
|
||||||
}
|
}
|
||||||
|
|
||||||
static MOO_INLINE moo_oow_t getxfi (moo_xma_t* xma, moo_oow_t size)
|
static MOO_INLINE moo_oow_t getxfi (moo_xma_t* xma, moo_oow_t size)
|
||||||
{
|
{
|
||||||
moo_oow_t xfi = ((size) / ALIGN) - 1;
|
moo_oow_t xfi = ((size) / ALIGN) - 1;
|
||||||
if (xfi >= FIXED) xfi = szlog2(size) - (xma)->bdec + FIXED;
|
if (xfi >= FIXED) xfi = szlog2(size) - (xma)->bdec + FIXED;
|
||||||
@ -193,7 +206,6 @@ static MOO_INLINE moo_oow_t getxfi (moo_xma_t* xma, moo_oow_t size)
|
|||||||
return xfi;
|
return xfi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
moo_xma_t* moo_xma_open (moo_mmgr_t* mmgr, moo_oow_t xtnsize, void* zoneptr, moo_oow_t zonesize)
|
moo_xma_t* moo_xma_open (moo_mmgr_t* mmgr, moo_oow_t xtnsize, void* zoneptr, moo_oow_t zonesize)
|
||||||
{
|
{
|
||||||
moo_xma_t* xma;
|
moo_xma_t* xma;
|
||||||
@ -236,7 +248,7 @@ int moo_xma_init (moo_xma_t* xma, moo_mmgr_t* mmgr, void* zoneptr, moo_oow_t zon
|
|||||||
|
|
||||||
internal = 1; /* internally created. must be freed upon moo_xma_fini() */
|
internal = 1; /* internally created. must be freed upon moo_xma_fini() */
|
||||||
}
|
}
|
||||||
else if (zonesize < FBLKMINSIZE)
|
else if (zonesize < FBLKMINSIZE)
|
||||||
{
|
{
|
||||||
/* the zone size is too small for an externally allocated zone. */
|
/* the zone size is too small for an externally allocated zone. */
|
||||||
/* TODO: difference error code from memory allocation failure.. this is not really memory shortage */
|
/* TODO: difference error code from memory allocation failure.. this is not really memory shortage */
|
||||||
@ -252,7 +264,7 @@ int moo_xma_init (moo_xma_t* xma, moo_mmgr_t* mmgr, void* zoneptr, moo_oow_t zon
|
|||||||
first->free_prev = MOO_NULL;
|
first->free_prev = MOO_NULL;
|
||||||
first->free_next = MOO_NULL;
|
first->free_next = MOO_NULL;
|
||||||
|
|
||||||
MOO_MEMSET (xma, 0, MOO_SIZEOF(*xma));
|
MOO_MEMSET(xma, 0, MOO_SIZEOF(*xma));
|
||||||
xma->_mmgr = mmgr;
|
xma->_mmgr = mmgr;
|
||||||
xma->bdec = szlog2(FIXED * ALIGN); /* precalculate the decrement value */
|
xma->bdec = szlog2(FIXED * ALIGN); /* precalculate the decrement value */
|
||||||
|
|
||||||
@ -261,7 +273,7 @@ int moo_xma_init (moo_xma_t* xma, moo_mmgr_t* mmgr, void* zoneptr, moo_oow_t zon
|
|||||||
/* get the free block index */
|
/* get the free block index */
|
||||||
xfi = getxfi(xma, first->size);
|
xfi = getxfi(xma, first->size);
|
||||||
/* locate it into an apporopriate slot */
|
/* locate it into an apporopriate slot */
|
||||||
xma->xfree[xfi] = first;
|
xma->xfree[xfi] = first;
|
||||||
/* let it be the head, which is natural with only a block */
|
/* let it be the head, which is natural with only a block */
|
||||||
xma->start = (moo_uint8_t*)first;
|
xma->start = (moo_uint8_t*)first;
|
||||||
xma->end = xma->start + zonesize;
|
xma->end = xma->start + zonesize;
|
||||||
@ -274,8 +286,17 @@ int moo_xma_init (moo_xma_t* xma, moo_mmgr_t* mmgr, void* zoneptr, moo_oow_t zon
|
|||||||
xma->stat.avail = zonesize - MBLKHDRSIZE;
|
xma->stat.avail = zonesize - MBLKHDRSIZE;
|
||||||
xma->stat.nfree = 1;
|
xma->stat.nfree = 1;
|
||||||
xma->stat.nused = 0;
|
xma->stat.nused = 0;
|
||||||
|
xma->stat.alloc_hwmark = 0;
|
||||||
|
|
||||||
|
xma->stat.nallocops = 0;
|
||||||
|
xma->stat.nallocgoodops = 0;
|
||||||
|
xma->stat.nallocbadops = 0;
|
||||||
|
xma->stat.nreallocops = 0;
|
||||||
|
xma->stat.nreallocgoodops = 0;
|
||||||
|
xma->stat.nreallocbadops = 0;
|
||||||
|
xma->stat.nfreeops = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -290,15 +311,15 @@ void moo_xma_fini (moo_xma_t* xma)
|
|||||||
|
|
||||||
static MOO_INLINE void attach_to_freelist (moo_xma_t* xma, moo_xma_fblk_t* b)
|
static MOO_INLINE void attach_to_freelist (moo_xma_t* xma, moo_xma_fblk_t* b)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* attach a block to a free list
|
* attach a block to a free list
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* get the free list index for the block size */
|
/* get the free list index for the block size */
|
||||||
moo_oow_t xfi = getxfi(xma, b->size);
|
moo_oow_t xfi = getxfi(xma, b->size);
|
||||||
|
|
||||||
/* let it be the head of the free list doubly-linked */
|
/* let it be the head of the free list doubly-linked */
|
||||||
b->free_prev = MOO_NULL;
|
b->free_prev = MOO_NULL;
|
||||||
b->free_next = xma->xfree[xfi];
|
b->free_next = xma->xfree[xfi];
|
||||||
if (xma->xfree[xfi]) xma->xfree[xfi]->free_prev = b;
|
if (xma->xfree[xfi]) xma->xfree[xfi]->free_prev = b;
|
||||||
xma->xfree[xfi] = b;
|
xma->xfree[xfi] = b;
|
||||||
@ -315,22 +336,21 @@ static MOO_INLINE void detach_from_freelist (moo_xma_t* xma, moo_xma_fblk_t* b)
|
|||||||
|
|
||||||
if (p)
|
if (p)
|
||||||
{
|
{
|
||||||
/* the previous item exists. let its 'next' pointer point to
|
/* the previous item exists. let its 'next' pointer point to
|
||||||
* the block's next item. */
|
* the block's next item. */
|
||||||
p->free_next = n;
|
p->free_next = n;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* the previous item does not exist. the block is the first
|
/* the previous item does not exist. the block is the first
|
||||||
* item in the free list. */
|
* item in the free list. */
|
||||||
|
|
||||||
moo_oow_t xfi = getxfi(xma, b->size);
|
moo_oow_t xfi = getxfi(xma, b->size);
|
||||||
assert (b == xma->xfree[xfi]);
|
assert (b == xma->xfree[xfi]);
|
||||||
/* let's update the free list head */
|
/* let's update the free list head */
|
||||||
xma->xfree[xfi] = n;
|
xma->xfree[xfi] = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* let the 'prev' pointer of the block's next item point to the
|
/* let the 'prev' pointer of the block's next item point to the
|
||||||
* block's previous item */
|
* block's previous item */
|
||||||
if (n) n->free_prev = p;
|
if (n) n->free_prev = p;
|
||||||
}
|
}
|
||||||
@ -345,15 +365,15 @@ static moo_xma_fblk_t* alloc_from_freelist (moo_xma_t* xma, moo_oow_t xfi, moo_o
|
|||||||
{
|
{
|
||||||
moo_oow_t rem;
|
moo_oow_t rem;
|
||||||
|
|
||||||
detach_from_freelist (xma, cand);
|
detach_from_freelist(xma, cand);
|
||||||
|
|
||||||
rem = cand->size - size;
|
rem = cand->size - size;
|
||||||
if (rem >= FBLKMINSIZE)
|
if (rem >= FBLKMINSIZE)
|
||||||
{
|
{
|
||||||
moo_xma_mblk_t* y, * z;
|
moo_xma_mblk_t* y, * z;
|
||||||
|
|
||||||
/* the remaining part is large enough to hold
|
/* the remaining part is large enough to hold
|
||||||
* another block. let's split it
|
* another block. let's split it
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* shrink the size of the 'cand' block */
|
/* shrink the size of the 'cand' block */
|
||||||
@ -368,7 +388,7 @@ static moo_xma_fblk_t* alloc_from_freelist (moo_xma_t* xma, moo_oow_t xfi, moo_o
|
|||||||
y->prev_size = cand->size;
|
y->prev_size = cand->size;
|
||||||
|
|
||||||
/* add the remaining part to the free list */
|
/* add the remaining part to the free list */
|
||||||
attach_to_freelist (xma, (moo_xma_fblk_t*)y);
|
attach_to_freelist(xma, (moo_xma_fblk_t*)y);
|
||||||
|
|
||||||
z = next_mblk(y);
|
z = next_mblk(y);
|
||||||
if ((moo_uint8_t*)z < xma->end) z->prev_size = y->size;
|
if ((moo_uint8_t*)z < xma->end) z->prev_size = y->size;
|
||||||
@ -396,6 +416,7 @@ static moo_xma_fblk_t* alloc_from_freelist (moo_xma_t* xma, moo_oow_t xfi, moo_o
|
|||||||
xma->stat.nused++;
|
xma->stat.nused++;
|
||||||
xma->stat.alloc += cand->size;
|
xma->stat.alloc += cand->size;
|
||||||
xma->stat.avail -= cand->size;
|
xma->stat.avail -= cand->size;
|
||||||
|
if (xma->stat.alloc > xma->stat.alloc_hwmark) xma->stat.alloc_hwmark = xma->stat.alloc;
|
||||||
#endif
|
#endif
|
||||||
return cand;
|
return cand;
|
||||||
}
|
}
|
||||||
@ -408,9 +429,13 @@ static moo_xma_fblk_t* alloc_from_freelist (moo_xma_t* xma, moo_oow_t xfi, moo_o
|
|||||||
void* moo_xma_alloc (moo_xma_t* xma, moo_oow_t size)
|
void* moo_xma_alloc (moo_xma_t* xma, moo_oow_t size)
|
||||||
{
|
{
|
||||||
moo_xma_fblk_t* cand;
|
moo_xma_fblk_t* cand;
|
||||||
moo_oow_t xfi;
|
moo_oow_t xfi, native_xfi;
|
||||||
|
|
||||||
DBG_VERIFY (xma, "alloc start");
|
DBG_VERIFY(xma, "alloc start");
|
||||||
|
|
||||||
|
#if defined(MOO_XMA_ENABLE_STAT)
|
||||||
|
xma->stat.nallocops++;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* round up 'size' to the multiples of ALIGN */
|
/* round up 'size' to the multiples of ALIGN */
|
||||||
if (size < MINALLOCSIZE) size = MINALLOCSIZE;
|
if (size < MINALLOCSIZE) size = MINALLOCSIZE;
|
||||||
@ -418,6 +443,7 @@ void* moo_xma_alloc (moo_xma_t* xma, moo_oow_t size)
|
|||||||
|
|
||||||
assert (size >= ALIGN);
|
assert (size >= ALIGN);
|
||||||
xfi = getxfi(xma, size);
|
xfi = getxfi(xma, size);
|
||||||
|
native_xfi = xfi;
|
||||||
|
|
||||||
/*if (xfi < XFIMAX(xma) && xma->xfree[xfi])*/
|
/*if (xfi < XFIMAX(xma) && xma->xfree[xfi])*/
|
||||||
if (xfi < FIXED && xma->xfree[xfi])
|
if (xfi < FIXED && xma->xfree[xfi])
|
||||||
@ -428,7 +454,7 @@ void* moo_xma_alloc (moo_xma_t* xma, moo_oow_t size)
|
|||||||
assert (cand->free != 0);
|
assert (cand->free != 0);
|
||||||
assert (cand->size == size);
|
assert (cand->size == size);
|
||||||
|
|
||||||
detach_from_freelist (xma, cand);
|
detach_from_freelist(xma, cand);
|
||||||
cand->free = 0;
|
cand->free = 0;
|
||||||
|
|
||||||
#if defined(MOO_XMA_ENABLE_STAT)
|
#if defined(MOO_XMA_ENABLE_STAT)
|
||||||
@ -436,13 +462,20 @@ void* moo_xma_alloc (moo_xma_t* xma, moo_oow_t size)
|
|||||||
xma->stat.nused++;
|
xma->stat.nused++;
|
||||||
xma->stat.alloc += cand->size;
|
xma->stat.alloc += cand->size;
|
||||||
xma->stat.avail -= cand->size;
|
xma->stat.avail -= cand->size;
|
||||||
|
if (xma->stat.alloc > xma->stat.alloc_hwmark) xma->stat.alloc_hwmark = xma->stat.alloc;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if (xfi == XFIMAX(xma))
|
else if (xfi == XFIMAX(xma))
|
||||||
{
|
{
|
||||||
/* huge block */
|
/* huge block */
|
||||||
cand = alloc_from_freelist(xma, XFIMAX(xma), size);
|
cand = alloc_from_freelist(xma, XFIMAX(xma), size);
|
||||||
if (!cand) return MOO_NULL;
|
if (!cand)
|
||||||
|
{
|
||||||
|
#if defined(MOO_XMA_ENABLE_STAT)
|
||||||
|
xma->stat.nallocbadops++;
|
||||||
|
#endif
|
||||||
|
return MOO_NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -471,149 +504,168 @@ void* moo_xma_alloc (moo_xma_t* xma, moo_oow_t size)
|
|||||||
cand = alloc_from_freelist(xma, xfi, size);
|
cand = alloc_from_freelist(xma, xfi, size);
|
||||||
if (cand) break;
|
if (cand) break;
|
||||||
}
|
}
|
||||||
if (!cand) return MOO_NULL;
|
if (!cand)
|
||||||
|
{
|
||||||
|
/* try fixed-sized free chains */
|
||||||
|
for (xfi = native_xfi + 1; xfi < FIXED; xfi++)
|
||||||
|
{
|
||||||
|
cand = alloc_from_freelist(xma, xfi, size);
|
||||||
|
if (cand) break;
|
||||||
|
}
|
||||||
|
if (!cand)
|
||||||
|
{
|
||||||
|
#if defined(MOO_XMA_ENABLE_STAT)
|
||||||
|
xma->stat.nallocbadops++;
|
||||||
|
#endif
|
||||||
|
return MOO_NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DBG_VERIFY (xma, "alloc end");
|
#if defined(MOO_XMA_ENABLE_STAT)
|
||||||
|
xma->stat.nallocgoodops++;
|
||||||
|
#endif
|
||||||
|
DBG_VERIFY(xma, "alloc end");
|
||||||
return SYS_TO_USR(cand);
|
return SYS_TO_USR(cand);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* _realloc_merge (moo_xma_t* xma, void* b, moo_oow_t size)
|
static void* _realloc_merge (moo_xma_t* xma, void* b, moo_oow_t size)
|
||||||
{
|
{
|
||||||
moo_xma_mblk_t* blk = (moo_xma_mblk_t*)USR_TO_SYS(b);
|
moo_uint8_t* blk = (moo_uint8_t*)USR_TO_SYS(b);
|
||||||
|
|
||||||
DBG_VERIFY (xma, "realloc merge start");
|
DBG_VERIFY(xma, "realloc merge start");
|
||||||
/* rounds up 'size' to be multiples of ALIGN */
|
/* rounds up 'size' to be multiples of ALIGN */
|
||||||
if (size < MINALLOCSIZE) size = MINALLOCSIZE;
|
if (size < MINALLOCSIZE) size = MINALLOCSIZE;
|
||||||
size = MOO_ALIGN_POW2(size, ALIGN);
|
size = MOO_ALIGN_POW2(size, ALIGN);
|
||||||
|
|
||||||
if (size > blk->size)
|
if (size > mblk_size(blk))
|
||||||
{
|
{
|
||||||
/* grow the current block */
|
/* grow the current block */
|
||||||
moo_oow_t req;
|
moo_oow_t req;
|
||||||
moo_xma_mblk_t* n;
|
moo_uint8_t* n;
|
||||||
moo_oow_t rem;
|
moo_oow_t rem;
|
||||||
|
|
||||||
req = size - blk->size; /* required size additionally */
|
req = size - mblk_size(blk); /* required size additionally */
|
||||||
|
|
||||||
n = next_mblk(blk);
|
n = (moo_uint8_t*)next_mblk(blk);
|
||||||
/* check if the next adjacent block is available */
|
/* check if the next adjacent block is available */
|
||||||
if ((moo_uint8_t*)n >= xma->end || !n->free || req > n->size) return MOO_NULL; /* no! */
|
if (n >= xma->end || !mblk_free(n) || req > mblk_size(n)) return MOO_NULL; /* no! */
|
||||||
/* TODO: check more blocks if the next block is free but small in size.
|
/* TODO: check more blocks if the next block is free but small in size.
|
||||||
* check the previous adjacent blocks also */
|
* check the previous adjacent blocks also */
|
||||||
|
|
||||||
assert (blk->size == n->prev_size);
|
assert(mblk_size(blk) == mblk_prev_size(n));
|
||||||
|
|
||||||
/* let's merge the current block with the next block */
|
/* let's merge the current block with the next block */
|
||||||
detach_from_freelist (xma, (moo_xma_fblk_t*)n);
|
detach_from_freelist(xma, (moo_xma_fblk_t*)n);
|
||||||
|
|
||||||
rem = (MBLKHDRSIZE + n->size) - req;
|
rem = (MBLKHDRSIZE + mblk_size(n)) - req;
|
||||||
if (rem >= FBLKMINSIZE)
|
if (rem >= FBLKMINSIZE)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* the remaining part of the next block is large enough
|
* the remaining part of the next block is large enough
|
||||||
* to hold a block. break the next block.
|
* to hold a block. break the next block.
|
||||||
*/
|
*/
|
||||||
|
moo_uint8_t* y, * z;
|
||||||
|
|
||||||
moo_xma_mblk_t* y, * z;
|
mblk_size(blk) += req;
|
||||||
|
y = (moo_uint8_t*)next_mblk(blk);
|
||||||
|
mblk_free(y) = 1;
|
||||||
|
mblk_size(y) = rem - MBLKHDRSIZE;
|
||||||
|
mblk_prev_size(y) = mblk_size(blk);
|
||||||
|
attach_to_freelist(xma, (moo_xma_fblk_t*)y);
|
||||||
|
|
||||||
blk->size += req;
|
z = (moo_uint8_t*)next_mblk(y);
|
||||||
y = next_mblk(blk);
|
if (z < xma->end) mblk_prev_size(z) = mblk_size(y);
|
||||||
y->free = 1;
|
|
||||||
y->size = rem - MBLKHDRSIZE;
|
|
||||||
y->prev_size = blk->size;
|
|
||||||
attach_to_freelist (xma, (moo_xma_fblk_t*)y);
|
|
||||||
|
|
||||||
z = next_mblk(y);
|
#if defined(MOO_XMA_ENABLE_STAT)
|
||||||
if ((moo_uint8_t*)z < xma->end) z->prev_size = y->size;
|
|
||||||
|
|
||||||
#if defined(MOO_XMA_ENABLE_STAT)
|
|
||||||
xma->stat.alloc += req;
|
xma->stat.alloc += req;
|
||||||
xma->stat.avail -= req; /* req + MBLKHDRSIZE(tmp) - MBLKHDRSIZE(n) */
|
xma->stat.avail -= req; /* req + MBLKHDRSIZE(tmp) - MBLKHDRSIZE(n) */
|
||||||
#endif
|
if (xma->stat.alloc > xma->stat.alloc_hwmark) xma->stat.alloc_hwmark = xma->stat.alloc;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
moo_xma_mblk_t* z;
|
moo_uint8_t* z;
|
||||||
|
|
||||||
/* the remaining part of the next block is too small to form an indepent block.
|
/* 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 */
|
* utilize the whole block by merging to the resizing block */
|
||||||
blk->size += MBLKHDRSIZE + n->size;
|
mblk_size(blk) += MBLKHDRSIZE + mblk_size(n);
|
||||||
|
|
||||||
z = next_mblk(blk);
|
z = (moo_uint8_t*)next_mblk(blk);
|
||||||
if ((moo_uint8_t*)z < xma->end) z->prev_size = blk->size;
|
if (z < xma->end) mblk_prev_size(z) = mblk_size(blk);
|
||||||
|
|
||||||
#if defined(MOO_XMA_ENABLE_STAT)
|
#if defined(MOO_XMA_ENABLE_STAT)
|
||||||
xma->stat.nfree--;
|
xma->stat.nfree--;
|
||||||
xma->stat.alloc += MBLKHDRSIZE + n->size;
|
xma->stat.alloc += MBLKHDRSIZE + mblk_size(n);
|
||||||
xma->stat.avail -= n->size;
|
xma->stat.avail -= mblk_size(n);
|
||||||
#endif
|
if (xma->stat.alloc > xma->stat.alloc_hwmark) xma->stat.alloc_hwmark = xma->stat.alloc;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (size < blk->size)
|
else if (size < mblk_size(blk))
|
||||||
{
|
{
|
||||||
/* shrink the block */
|
/* shrink the block */
|
||||||
moo_oow_t rem = blk->size - size;
|
moo_oow_t rem = mblk_size(blk) - size;
|
||||||
if (rem >= FBLKMINSIZE)
|
if (rem >= FBLKMINSIZE)
|
||||||
{
|
{
|
||||||
moo_xma_mblk_t* n;
|
moo_uint8_t* n;
|
||||||
|
|
||||||
n = next_mblk(blk);
|
n = (moo_uint8_t*)next_mblk(blk);
|
||||||
|
|
||||||
/* the leftover is large enough to hold a block of minimum size.split the current block */
|
/* the leftover is large enough to hold a block of minimum size.split the current block */
|
||||||
if ((moo_uint8_t*)n < xma->end && n->free)
|
if (n < xma->end && mblk_free(n))
|
||||||
{
|
{
|
||||||
moo_xma_mblk_t* y, * z;
|
moo_uint8_t* y, * z;
|
||||||
|
|
||||||
/* make the leftover block merge with the next block */
|
/* make the leftover block merge with the next block */
|
||||||
|
|
||||||
detach_from_freelist (xma, (moo_xma_fblk_t*)n);
|
detach_from_freelist(xma, (moo_xma_fblk_t*)n);
|
||||||
|
|
||||||
blk->size = size;
|
mblk_size(blk) = size;
|
||||||
|
|
||||||
y = next_mblk(blk); /* update y to the leftover block with the new block size set above */
|
y = (moo_uint8_t*)next_mblk(blk); /* update y to the leftover block with the new block size set above */
|
||||||
y->free = 1;
|
mblk_free(y) = 1;
|
||||||
y->size = rem + n->size; /* add up the adjust block - (rem + MBLKHDRSIZE(n) + n->size) - MBLKHDRSIZE(y) */
|
mblk_size(y) = rem + mblk_size(n); /* add up the adjust block - (rem + MBLKHDRSIZE(n) + n->size) - MBLKHDRSIZE(y) */
|
||||||
y->prev_size = blk->size;
|
mblk_prev_size(y) = mblk_size(blk);
|
||||||
|
|
||||||
/* add 'y' to the free list */
|
/* add 'y' to the free list */
|
||||||
attach_to_freelist (xma, (moo_xma_fblk_t*)y);
|
attach_to_freelist(xma, (moo_xma_fblk_t*)y);
|
||||||
|
|
||||||
z = next_mblk(y); /* get adjacent block to the merged block */
|
z = (moo_uint8_t*)next_mblk(y); /* get adjacent block to the merged block */
|
||||||
if ((moo_uint8_t*)z < xma->end) z->prev_size = y->size;
|
if (z < xma->end) mblk_prev_size(z) = mblk_size(y);
|
||||||
|
|
||||||
#if defined(MOO_XMA_ENABLE_STAT)
|
#if defined(MOO_XMA_ENABLE_STAT)
|
||||||
xma->stat.alloc -= rem;
|
xma->stat.alloc -= rem;
|
||||||
xma->stat.avail += rem; /* rem - MBLKHDRSIZE(y) + MBLKHDRSIZE(n) */
|
xma->stat.avail += rem; /* rem - MBLKHDRSIZE(y) + MBLKHDRSIZE(n) */
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
moo_xma_mblk_t* y;
|
moo_uint8_t* y;
|
||||||
|
|
||||||
/* link the leftover block to the free list */
|
/* link the leftover block to the free list */
|
||||||
blk->size = size;
|
mblk_size(blk) = size;
|
||||||
|
|
||||||
y = next_mblk(blk); /* update y to the leftover block with the new block size set above */
|
y = (moo_uint8_t*)next_mblk(blk); /* update y to the leftover block with the new block size set above */
|
||||||
y->free = 1;
|
mblk_free(y) = 1;
|
||||||
y->size = rem - MBLKHDRSIZE;
|
mblk_size(y) = rem - MBLKHDRSIZE;
|
||||||
y->prev_size = blk->size;
|
mblk_prev_size(y) = mblk_size(blk);
|
||||||
|
|
||||||
attach_to_freelist (xma, (moo_xma_fblk_t*)y);
|
attach_to_freelist(xma, (moo_xma_fblk_t*)y);
|
||||||
/*n = next_mblk(y);
|
/*n = (moo_uint8_t*)next_mblk(y);
|
||||||
if ((moo_uint8_t*)n < xma->end)*/ n->prev_size = y->size;
|
if (n < xma->end)*/ mblk_prev_size(n) = mblk_size(y);
|
||||||
|
|
||||||
#if defined(MOO_XMA_ENABLE_STAT)
|
#if defined(MOO_XMA_ENABLE_STAT)
|
||||||
xma->stat.nfree++;
|
xma->stat.nfree++;
|
||||||
xma->stat.alloc -= rem;
|
xma->stat.alloc -= rem;
|
||||||
xma->stat.avail += y->size;
|
xma->stat.avail += mblk_size(y);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DBG_VERIFY (xma, "realloc merge end");
|
DBG_VERIFY(xma, "realloc merge end");
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -628,7 +680,7 @@ void* moo_xma_realloc (moo_xma_t* xma, void* b, moo_oow_t size)
|
|||||||
{
|
{
|
||||||
void* n;
|
void* n;
|
||||||
|
|
||||||
if (b == MOO_NULL)
|
if (!b)
|
||||||
{
|
{
|
||||||
/* 'realloc' with NULL is the same as 'alloc' */
|
/* 'realloc' with NULL is the same as 'alloc' */
|
||||||
n = moo_xma_alloc(xma, size);
|
n = moo_xma_alloc(xma, size);
|
||||||
@ -636,18 +688,30 @@ void* moo_xma_realloc (moo_xma_t* xma, void* b, moo_oow_t size)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* try reallocation by merging the adjacent continuous blocks */
|
/* try reallocation by merging the adjacent continuous blocks */
|
||||||
n = _realloc_merge (xma, b, size);
|
#if defined(HAWK_XMA_ENABLE_STAT)
|
||||||
|
xma->stat.nreallocops++;
|
||||||
|
#endif
|
||||||
|
n = _realloc_merge(xma, b, size);
|
||||||
if (!n)
|
if (!n)
|
||||||
{
|
{
|
||||||
|
#if defined(MOO_XMA_ENABLE_STAT)
|
||||||
|
xma->stat.nreallocbadops++;
|
||||||
|
#endif
|
||||||
/* reallocation by merging failed. fall back to the slow
|
/* reallocation by merging failed. fall back to the slow
|
||||||
* allocation-copy-free scheme */
|
* allocation-copy-free scheme */
|
||||||
n = moo_xma_alloc(xma, size);
|
n = moo_xma_alloc(xma, size);
|
||||||
if (n)
|
if (n)
|
||||||
{
|
{
|
||||||
MOO_MEMCPY (n, b, size);
|
MOO_MEMCPY(n, b, size);
|
||||||
moo_xma_free (xma, b);
|
moo_xma_free(xma, b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#if defined(MOO_XMA_ENABLE_STAT)
|
||||||
|
xma->stat.nreallocgoodops++;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
@ -655,60 +719,62 @@ void* moo_xma_realloc (moo_xma_t* xma, void* b, moo_oow_t size)
|
|||||||
|
|
||||||
void moo_xma_free (moo_xma_t* xma, void* b)
|
void moo_xma_free (moo_xma_t* xma, void* b)
|
||||||
{
|
{
|
||||||
moo_xma_mblk_t* blk = (moo_xma_mblk_t*)USR_TO_SYS(b);
|
moo_uint8_t* blk = (moo_uint8_t*)USR_TO_SYS(b);
|
||||||
moo_xma_mblk_t* x, * y;
|
moo_uint8_t* x, * y;
|
||||||
moo_oow_t org_blk_size;
|
moo_oow_t org_blk_size;
|
||||||
|
|
||||||
DBG_VERIFY (xma, "free start");
|
DBG_VERIFY(xma, "free start");
|
||||||
|
|
||||||
org_blk_size = blk->size;
|
org_blk_size = mblk_size(blk);
|
||||||
|
|
||||||
#if defined(MOO_XMA_ENABLE_STAT)
|
#if defined(MOO_XMA_ENABLE_STAT)
|
||||||
/* update statistical variables */
|
/* update statistical variables */
|
||||||
xma->stat.nused--;
|
xma->stat.nused--;
|
||||||
xma->stat.alloc -= org_blk_size;
|
xma->stat.alloc -= org_blk_size;
|
||||||
|
xma->stat.nfreeops++;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
x = prev_mblk(blk);
|
x = (moo_uint8_t*)prev_mblk(blk);
|
||||||
y = next_mblk(blk);
|
y = (moo_uint8_t*)next_mblk(blk);
|
||||||
if (((moo_uint8_t*)x >= xma->start && x->free) && ((moo_uint8_t*)y < xma->end && y->free))
|
if ((x >= xma->start && mblk_free(x)) && (y < xma->end && mblk_free(y)))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Merge the block with surrounding blocks
|
* Merge the block with surrounding blocks
|
||||||
*
|
*
|
||||||
* blk
|
* blk
|
||||||
* |
|
* |
|
||||||
* v
|
* v
|
||||||
* +------------+------------+------------+------------+
|
* +------------+------------+------------+------------+
|
||||||
* | X | | Y | Z |
|
* | X | | Y | Z |
|
||||||
* +------------+------------+------------+------------+
|
* +------------+------------+------------+------------+
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* +--------------------------------------+------------+
|
* +--------------------------------------+------------+
|
||||||
* | X | Z |
|
* | X | Z |
|
||||||
* +--------------------------------------+------------+
|
* +--------------------------------------+------------+
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
moo_xma_mblk_t* z = next_mblk(y);
|
moo_uint8_t* z;
|
||||||
moo_oow_t ns = MBLKHDRSIZE + org_blk_size + MBLKHDRSIZE;
|
moo_oow_t ns = MBLKHDRSIZE + org_blk_size + MBLKHDRSIZE;
|
||||||
moo_oow_t bs = ns + y->size;
|
/* blk's header size + blk->size + y's header size */
|
||||||
|
moo_oow_t bs = ns + mblk_size(y);
|
||||||
|
|
||||||
detach_from_freelist (xma, (moo_xma_fblk_t*)x);
|
detach_from_freelist(xma, (moo_xma_fblk_t*)x);
|
||||||
detach_from_freelist (xma, (moo_xma_fblk_t*)y);
|
detach_from_freelist(xma, (moo_xma_fblk_t*)y);
|
||||||
|
|
||||||
x->size += bs;
|
mblk_size(x) += bs;
|
||||||
attach_to_freelist (xma, (moo_xma_fblk_t*)x);
|
attach_to_freelist(xma, (moo_xma_fblk_t*)x);
|
||||||
|
|
||||||
z = next_mblk(x);
|
z = (moo_uint8_t*)next_mblk(x);
|
||||||
if ((moo_uint8_t*)z < xma->end) z->prev_size = x->size;
|
if ((moo_uint8_t*)z < xma->end) mblk_prev_size(z) = mblk_size(x);
|
||||||
|
|
||||||
#if defined(MOO_XMA_ENABLE_STAT)
|
#if defined(MOO_XMA_ENABLE_STAT)
|
||||||
xma->stat.nfree--;
|
xma->stat.nfree--;
|
||||||
xma->stat.avail += ns;
|
xma->stat.avail += ns;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if ((moo_uint8_t*)y < xma->end && y->free)
|
else if (y < xma->end && mblk_free(y))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Merge the block with the next block
|
* Merge the block with the next block
|
||||||
@ -719,8 +785,8 @@ void moo_xma_free (moo_xma_t* xma, void* b)
|
|||||||
* +------------+------------+------------+
|
* +------------+------------+------------+
|
||||||
* | | Y | Z |
|
* | | Y | Z |
|
||||||
* +------------+------------+------------+
|
* +------------+------------+------------+
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* blk
|
* blk
|
||||||
* |
|
* |
|
||||||
@ -728,33 +794,33 @@ void moo_xma_free (moo_xma_t* xma, void* b)
|
|||||||
* +-------------------------+------------+
|
* +-------------------------+------------+
|
||||||
* | | Z |
|
* | | Z |
|
||||||
* +-------------------------+------------+
|
* +-------------------------+------------+
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
moo_xma_mblk_t* z = next_mblk(y);
|
moo_uint8_t* z = (moo_uint8_t*)next_mblk(y);
|
||||||
|
|
||||||
/* detach y from the free list */
|
/* detach y from the free list */
|
||||||
detach_from_freelist (xma, (moo_xma_fblk_t*)y);
|
detach_from_freelist(xma, (moo_xma_fblk_t*)y);
|
||||||
|
|
||||||
/* update the block availability */
|
/* update the block availability */
|
||||||
blk->free = 1;
|
mblk_free(blk) = 1;
|
||||||
/* update the block size. MBLKHDRSIZE for the header space in x */
|
/* update the block size. MBLKHDRSIZE for the header space in x */
|
||||||
blk->size += MBLKHDRSIZE + y->size;
|
mblk_size(blk) += MBLKHDRSIZE + mblk_size(y);
|
||||||
|
|
||||||
/* update the backward link of Y */
|
/* update the backward link of Y */
|
||||||
if ((moo_uint8_t*)z < xma->end) z->prev_size = blk->size;
|
if ((moo_uint8_t*)z < xma->end) mblk_prev_size(z) = mblk_size(blk);
|
||||||
|
|
||||||
/* attach blk to the free list */
|
/* attach blk to the free list */
|
||||||
attach_to_freelist (xma, (moo_xma_fblk_t*)blk);
|
attach_to_freelist(xma, (moo_xma_fblk_t*)blk);
|
||||||
|
|
||||||
#if defined(MOO_XMA_ENABLE_STAT)
|
#if defined(MOO_XMA_ENABLE_STAT)
|
||||||
xma->stat.avail += org_blk_size + MBLKHDRSIZE;
|
xma->stat.avail += org_blk_size + MBLKHDRSIZE;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if ((moo_uint8_t*)x >= xma->start && x->free)
|
else if (x >= xma->start && mblk_free(x))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Merge the block with the previous block
|
* Merge the block with the previous block
|
||||||
*
|
*
|
||||||
* blk
|
* blk
|
||||||
* |
|
* |
|
||||||
@ -767,14 +833,14 @@ void moo_xma_free (moo_xma_t* xma, void* b)
|
|||||||
* | X | Y |
|
* | X | Y |
|
||||||
* +-------------------------+------------+
|
* +-------------------------+------------+
|
||||||
*/
|
*/
|
||||||
detach_from_freelist (xma, (moo_xma_fblk_t*)x);
|
detach_from_freelist(xma, (moo_xma_fblk_t*)x);
|
||||||
|
|
||||||
x->size += MBLKHDRSIZE + org_blk_size;
|
mblk_size(x) += MBLKHDRSIZE + org_blk_size;
|
||||||
|
|
||||||
assert (y == next_mblk(x));
|
assert(y == next_mblk(x));
|
||||||
if ((moo_uint8_t*)y < xma->end) y->prev_size = x->size;
|
if ((moo_uint8_t*)y < xma->end) mblk_prev_size(y) = mblk_size(x);
|
||||||
|
|
||||||
attach_to_freelist (xma, (moo_xma_fblk_t*)x);
|
attach_to_freelist(xma, (moo_xma_fblk_t*)x);
|
||||||
|
|
||||||
#if defined(MOO_XMA_ENABLE_STAT)
|
#if defined(MOO_XMA_ENABLE_STAT)
|
||||||
xma->stat.avail += MBLKHDRSIZE + org_blk_size;
|
xma->stat.avail += MBLKHDRSIZE + org_blk_size;
|
||||||
@ -782,8 +848,8 @@ void moo_xma_free (moo_xma_t* xma, void* b)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
blk->free = 1;
|
mblk_free(blk) = 1;
|
||||||
attach_to_freelist (xma, (moo_xma_fblk_t*)blk);
|
attach_to_freelist(xma, (moo_xma_fblk_t*)blk);
|
||||||
|
|
||||||
#if defined(MOO_XMA_ENABLE_STAT)
|
#if defined(MOO_XMA_ENABLE_STAT)
|
||||||
xma->stat.nfree++;
|
xma->stat.nfree++;
|
||||||
@ -791,54 +857,75 @@ void moo_xma_free (moo_xma_t* xma, void* b)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
DBG_VERIFY (xma, "free end");
|
DBG_VERIFY(xma, "free end");
|
||||||
}
|
}
|
||||||
|
|
||||||
void moo_xma_dump (moo_xma_t* xma, moo_xma_dumper_t dumper, void* ctx)
|
void moo_xma_dump (moo_xma_t* xma, moo_xma_dumper_t dumper, void* ctx)
|
||||||
{
|
{
|
||||||
moo_xma_mblk_t* tmp;
|
moo_xma_mblk_t* tmp;
|
||||||
moo_oow_t fsum, asum;
|
moo_oow_t fsum, asum, xfi;
|
||||||
#if defined(MOO_XMA_ENABLE_STAT)
|
#if defined(MOO_XMA_ENABLE_STAT)
|
||||||
moo_oow_t isum;
|
moo_oow_t isum;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
dumper (ctx, "<XMA DUMP>\n");
|
dumper(ctx, "[XMA DUMP]\n");
|
||||||
|
|
||||||
#if defined(MOO_XMA_ENABLE_STAT)
|
#if defined(MOO_XMA_ENABLE_STAT)
|
||||||
dumper (ctx, "== statistics ==\n");
|
dumper(ctx, "== statistics ==\n");
|
||||||
dumper (ctx, "total = %zu\n", xma->stat.total);
|
dumper(ctx, "Total = %zu\n", xma->stat.total);
|
||||||
dumper (ctx, "alloc = %zu\n", xma->stat.alloc);
|
dumper(ctx, "Alloc = %zu\n", xma->stat.alloc);
|
||||||
dumper (ctx, "avail = %zu\n", xma->stat.avail);
|
dumper(ctx, "Avail = %zu\n", xma->stat.avail);
|
||||||
|
dumper(ctx, "Alloc High Watermark = %zu\n", xma->stat.alloc_hwmark);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
dumper (ctx, "== blocks ==\n");
|
dumper(ctx, "== blocks ==\n");
|
||||||
dumper (ctx, " size avail address\n");
|
dumper(ctx, " size avail address\n");
|
||||||
for (tmp = (moo_xma_mblk_t*)xma->start, fsum = 0, asum = 0; (moo_uint8_t*)tmp < xma->end; tmp = next_mblk(tmp))
|
for (tmp = (moo_xma_mblk_t*)xma->start, fsum = 0, asum = 0; (moo_uint8_t*)tmp < xma->end; tmp = next_mblk(tmp))
|
||||||
{
|
{
|
||||||
dumper (ctx, " %-18zu %-5u %p\n", tmp->size, (unsigned int)tmp->free, tmp);
|
dumper(ctx, " %-18zu %-5u %p\n", tmp->size, (unsigned int)tmp->free, tmp);
|
||||||
if (tmp->free) fsum += tmp->size;
|
if (tmp->free) fsum += tmp->size;
|
||||||
else asum += tmp->size;
|
else asum += tmp->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dumper(ctx, "== free list ==\n");
|
||||||
|
for (xfi = 0; xfi <= XFIMAX(xma); xfi++)
|
||||||
|
{
|
||||||
|
if (xma->xfree[xfi])
|
||||||
|
{
|
||||||
|
moo_xma_fblk_t* f;
|
||||||
|
for (f = xma->xfree[xfi]; f; f = f->free_next)
|
||||||
|
{
|
||||||
|
dumper(ctx, " xfi %d fblk %p size %lu\n", xfi, f, (unsigned long)f->size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(MOO_XMA_ENABLE_STAT)
|
#if defined(MOO_XMA_ENABLE_STAT)
|
||||||
isum = (xma->stat.nfree + xma->stat.nused) * MBLKHDRSIZE;
|
isum = (xma->stat.nfree + xma->stat.nused) * MBLKHDRSIZE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
dumper (ctx, "---------------------------------------\n");
|
dumper(ctx, "---------------------------------------\n");
|
||||||
dumper (ctx, "Allocated blocks: %18zu bytes\n", asum);
|
dumper(ctx, "Allocated blocks : %18zu bytes\n", asum);
|
||||||
dumper (ctx, "Available blocks: %18zu bytes\n", fsum);
|
dumper(ctx, "Available blocks : %18zu bytes\n", fsum);
|
||||||
|
|
||||||
|
|
||||||
#if defined(MOO_XMA_ENABLE_STAT)
|
#if defined(MOO_XMA_ENABLE_STAT)
|
||||||
dumper (ctx, "Internal use : %18zu bytes\n", isum);
|
dumper(ctx, "Internal use : %18zu bytes\n", isum);
|
||||||
dumper (ctx, "Total : %18zu bytes\n", (asum + fsum + isum));
|
dumper(ctx, "Total : %18zu bytes\n", (asum + fsum + isum));
|
||||||
|
dumper(ctx, "Alloc operations : %18zu\n", xma->stat.nallocops);
|
||||||
|
dumper(ctx, "Good alloc operations : %18zu\n", xma->stat.nallocgoodops);
|
||||||
|
dumper(ctx, "Bad alloc operations : %18zu\n", xma->stat.nallocbadops);
|
||||||
|
dumper(ctx, "Realloc operations : %18zu\n", xma->stat.nreallocops);
|
||||||
|
dumper(ctx, "Good realloc operations: %18zu\n", xma->stat.nreallocgoodops);
|
||||||
|
dumper(ctx, "Bad realloc operations : %18zu\n", xma->stat.nreallocbadops);
|
||||||
|
dumper(ctx, "Free operations : %18zu\n", xma->stat.nfreeops);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(MOO_XMA_ENABLE_STAT)
|
#if defined(MOO_XMA_ENABLE_STAT)
|
||||||
assert (asum == xma->stat.alloc);
|
assert(asum == xma->stat.alloc);
|
||||||
assert (fsum == xma->stat.avail);
|
assert(fsum == xma->stat.avail);
|
||||||
assert (isum == xma->stat.total - (xma->stat.alloc + xma->stat.avail));
|
assert(isum == xma->stat.total - (xma->stat.alloc + xma->stat.avail));
|
||||||
assert (asum + fsum + isum == xma->stat.total);
|
assert(asum + fsum + isum == xma->stat.total);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user