Apply tweaks to handle larger addresses (thanks @HaydenKow)
This commit is contained in:
parent
8a02ee55cc
commit
ddf23974bd
|
@ -3,6 +3,7 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#define ALIGN(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
|
||||||
|
|
||||||
#if defined(YALLOC_VALGRIND) && !defined(NVALGRIND)
|
#if defined(YALLOC_VALGRIND) && !defined(NVALGRIND)
|
||||||
# define USE_VALGRIND 1
|
# define USE_VALGRIND 1
|
||||||
|
@ -323,8 +324,8 @@ void * yalloc_alloc(void * pool, size_t size)
|
||||||
return NULL; /* no free block, no chance to allocate anything */ // TODO: Just read up which C standard supports single line comments and then fucking use them!
|
return NULL; /* no free block, no chance to allocate anything */ // TODO: Just read up which C standard supports single line comments and then fucking use them!
|
||||||
}
|
}
|
||||||
|
|
||||||
while (size % 4)
|
/* round up to alignment */
|
||||||
++size; /* round up to alignment TODO: do it the clever way */
|
size = ALIGN(size, 64);
|
||||||
|
|
||||||
size_t bruttoSize = size + sizeof(Header);
|
size_t bruttoSize = size + sizeof(Header);
|
||||||
Header * prev = NULL;
|
Header * prev = NULL;
|
||||||
|
@ -373,7 +374,7 @@ void * yalloc_alloc(void * pool, size_t size)
|
||||||
prev[1].next = cur[1].next;
|
prev[1].next = cur[1].next;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uint16_t freeBit = isFree(root);
|
uint32_t freeBit = isFree(root);
|
||||||
root->prev = (cur[1].next & NIL) | freeBit;
|
root->prev = (cur[1].next & NIL) | freeBit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -405,7 +406,7 @@ static void unlink_from_free_list(Header * pool, Header * blk)
|
||||||
if (isNil(blk[1].prev))
|
if (isNil(blk[1].prev))
|
||||||
{ // the block is the first in the free-list
|
{ // the block is the first in the free-list
|
||||||
// make the pools first-free-pointer point to the next in the free list
|
// make the pools first-free-pointer point to the next in the free list
|
||||||
uint16_t freeBit = isFree(pool);
|
uint32_t freeBit = isFree(pool);
|
||||||
pool->prev = (blk[1].next & NIL) | freeBit;
|
pool->prev = (blk[1].next & NIL) | freeBit;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -528,7 +529,7 @@ void yalloc_free(void * pool_, void * p)
|
||||||
// now the freed block is the first in the free-list
|
// now the freed block is the first in the free-list
|
||||||
|
|
||||||
// update the offset to the first element of the free list
|
// update the offset to the first element of the free list
|
||||||
uint16_t freeBit = isFree(pool); // remember the free-bit of the offset
|
uint32_t freeBit = isFree(pool); // remember the free-bit of the offset
|
||||||
pool->prev = HDR_OFFSET(cur) | freeBit; // update the offset and restore the free-bit
|
pool->prev = HDR_OFFSET(cur) | freeBit; // update the offset and restore the free-bit
|
||||||
_yalloc_validate(pool);
|
_yalloc_validate(pool);
|
||||||
_protect_pool(pool);
|
_protect_pool(pool);
|
||||||
|
@ -576,6 +577,43 @@ size_t yalloc_count_free(void * pool_)
|
||||||
return bruttoFree - sizeof(Header);
|
return bruttoFree - sizeof(Header);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t yalloc_count_continuous(void * pool_)
|
||||||
|
{
|
||||||
|
assert_is_pool(pool_);
|
||||||
|
_unprotect_pool(pool_);
|
||||||
|
assert(!_yalloc_defrag_in_progress(pool_));
|
||||||
|
Header * pool = (Header*)pool_;
|
||||||
|
size_t largestFree = 0;
|
||||||
|
Header * cur = pool;
|
||||||
|
|
||||||
|
_yalloc_validate(pool);
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (isFree(cur))
|
||||||
|
{ // it is a free block
|
||||||
|
size_t temp = (uintptr_t)HDR_PTR(cur->next) - (uintptr_t)cur;
|
||||||
|
if(temp > largestFree)
|
||||||
|
largestFree = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNil(cur->next))
|
||||||
|
break;
|
||||||
|
|
||||||
|
cur = HDR_PTR(cur->next);
|
||||||
|
}
|
||||||
|
|
||||||
|
_protect_pool(pool);
|
||||||
|
|
||||||
|
if (largestFree < sizeof(Header))
|
||||||
|
{
|
||||||
|
internal_assert(!largestFree); // free space should always be a multiple of sizeof(Header)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return largestFree - sizeof(Header);
|
||||||
|
}
|
||||||
|
|
||||||
void * yalloc_first_used(void * pool)
|
void * yalloc_first_used(void * pool)
|
||||||
{
|
{
|
||||||
assert_is_pool(pool);
|
assert_is_pool(pool);
|
||||||
|
@ -654,7 +692,7 @@ void yalloc_defrag_start(void * pool_)
|
||||||
internal_assert(!isFree(blk));
|
internal_assert(!isFree(blk));
|
||||||
|
|
||||||
// mark the pool as "defragementation in progress"
|
// mark the pool as "defragementation in progress"
|
||||||
uint16_t freeBit = isFree(pool);
|
uint32_t freeBit = isFree(pool);
|
||||||
pool->prev = (HDR_OFFSET(blk) & NIL) | freeBit;
|
pool->prev = (HDR_OFFSET(blk) & NIL) | freeBit;
|
||||||
|
|
||||||
_yalloc_validate(pool);
|
_yalloc_validate(pool);
|
||||||
|
|
|
@ -12,7 +12,7 @@ API of the yalloc allocator.
|
||||||
/**
|
/**
|
||||||
Maximum supported pool size. yalloc_init() will fail for larger pools.
|
Maximum supported pool size. yalloc_init() will fail for larger pools.
|
||||||
*/
|
*/
|
||||||
#define MAX_POOL_SIZE ((2 << 16) - 4)
|
#define MAX_POOL_SIZE ((2 << 24) - 4)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Creates a pool inside a given buffer.
|
Creates a pool inside a given buffer.
|
||||||
|
@ -77,6 +77,14 @@ After defragmentation the first allocation with the returned size is guaranteed
|
||||||
*/
|
*/
|
||||||
size_t yalloc_count_free(void * pool);
|
size_t yalloc_count_free(void * pool);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the maximum continuous free area.
|
||||||
|
|
||||||
|
@param pool The starting address of an initialized pool.
|
||||||
|
@return Number of free bytes that exist continuously.
|
||||||
|
*/
|
||||||
|
size_t yalloc_count_continuous(void * pool_);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Queries the usable size of an allocated block.
|
Queries the usable size of an allocated block.
|
||||||
|
|
||||||
|
|
|
@ -5,19 +5,19 @@
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
uint16_t prev; // low bit set if free
|
uint32_t prev; // low bit set if free
|
||||||
uint16_t next; // for used blocks: low bit set if unused header at the end
|
uint32_t next; // for used blocks: low bit set if unused header at the end
|
||||||
} Header;
|
} Header;
|
||||||
|
|
||||||
// NOTE: We have 32bit aligned data and 16bit offsets where the lowest bit is used as flag. So we remove the low bit and shift by 1 to address 128k bytes with the 15bit significant offset bits.
|
// NOTE: We have 32bit aligned data and 16bit offsets where the lowest bit is used as flag. So we remove the low bit and shift by 1 to address 128k bytes with the 15bit significant offset bits.
|
||||||
|
|
||||||
#define NIL 0xFFFEu
|
#define NIL 0xFFFFFFFEu
|
||||||
|
|
||||||
// return Header-address for a prev/next
|
// return Header-address for a prev/next
|
||||||
#define HDR_PTR(offset) ((Header*)((char*)pool + (((offset) & NIL)<<1)))
|
#define HDR_PTR(offset) ((Header*)((char*)pool + (((offset) & NIL)<<1)))
|
||||||
|
|
||||||
// return a prev/next for a Header-address
|
// return a prev/next for a Header-address
|
||||||
#define HDR_OFFSET(blockPtr) ((uint16_t)(((char*)blockPtr - (char*)pool) >> 1))
|
#define HDR_OFFSET(blockPtr) ((uint32_t)(((char*)blockPtr - (char*)pool) >> 1))
|
||||||
|
|
||||||
#ifndef YALLOC_INTERNAL_VALIDATE
|
#ifndef YALLOC_INTERNAL_VALIDATE
|
||||||
# ifdef NDEBUG
|
# ifdef NDEBUG
|
||||||
|
@ -40,9 +40,9 @@ In other cases this should be deactivated.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// detects offsets that point nowhere
|
// detects offsets that point nowhere
|
||||||
static inline int isNil(uint16_t offset)
|
static inline int isNil(uint32_t offset)
|
||||||
{
|
{
|
||||||
return (offset | 1) == 0xFFFF;
|
return (offset | 1) == 0xFFFFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int isFree(Header * hdr)
|
static inline int isFree(Header * hdr)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user