spaceship: add defragmentation and make sub-allocations optional
This commit is contained in:
parent
f7c6de4679
commit
c0973f37c5
|
@ -1,12 +1,15 @@
|
|||
#include <string.h>
|
||||
#include "spaceship.h"
|
||||
|
||||
|
||||
void spaceship_init(void *p, size_t size)
|
||||
{
|
||||
struct spaceship_chunk *chunk = p;
|
||||
chunk->ssc_base = size;
|
||||
chunk->ssc_size = size;
|
||||
chunk->ssc_flags = SPACESHIP_FLAG_LAST;
|
||||
#if SPACESHIP_WITH_SUB
|
||||
chunk->ssc_base = size;
|
||||
#endif
|
||||
#if SPACESHIP_WITH_PARENT
|
||||
chunk->ssc_parent = 0;
|
||||
#endif
|
||||
|
@ -55,7 +58,9 @@ void *spaceship_alloc(void *p, size_t size)
|
|||
}
|
||||
}
|
||||
/* this chunk is now in use */
|
||||
#if SPACESHIP_WITH_SUB
|
||||
chunk->ssc_base = chunk->ssc_size;
|
||||
#endif
|
||||
chunk->ssc_flags |= SPACESHIP_FLAG_USED;
|
||||
return chunk;
|
||||
}
|
||||
|
@ -86,6 +91,7 @@ void spaceship_free(struct spaceship_chunk *chunk)
|
|||
}
|
||||
}
|
||||
|
||||
#if SPACESHIP_WITH_SUB
|
||||
int spaceship_init_sub(struct spaceship_chunk *chunk, size_t base_size)
|
||||
{
|
||||
size_t div_size = chunk->ssc_size - base_size;
|
||||
|
@ -101,3 +107,65 @@ int spaceship_init_sub(struct spaceship_chunk *chunk, size_t base_size)
|
|||
#endif
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
void spaceship_defrag(struct spaceship_chunk *unused)
|
||||
{
|
||||
#if SPACESHIP_WITH_PREV
|
||||
size_t prev_size = 0;
|
||||
#endif
|
||||
|
||||
for (;;) {
|
||||
/* find first unused chunk */
|
||||
while (unused && unused->ssc_flags & SPACESHIP_FLAG_USED) {
|
||||
unused = spaceship_get_next(unused);
|
||||
}
|
||||
if (!unused) {
|
||||
break;
|
||||
}
|
||||
#if SPACESHIP_WITH_PREV
|
||||
prev_size = unused->ssc_prev;
|
||||
#endif
|
||||
|
||||
/* find used chunk after */
|
||||
struct spaceship_chunk *used = spaceship_get_next_sibling(unused);
|
||||
if (!used) {
|
||||
break;
|
||||
}
|
||||
size_t unused_size = (uintptr_t)used - (uintptr_t)unused;
|
||||
|
||||
/* find chain length of used chunks */
|
||||
struct spaceship_chunk *last, *end = used;
|
||||
do {
|
||||
last = end;
|
||||
end = spaceship_get_next(end);
|
||||
} while (end && end->ssc_flags & SPACESHIP_FLAG_USED);
|
||||
|
||||
/* move used chunk up front */
|
||||
end = (struct spaceship_chunk *)((uintptr_t)last + spaceship_get_size(last));
|
||||
size_t used_size = (uintptr_t)end - (uintptr_t)used;
|
||||
memmove(unused, used, used_size);
|
||||
|
||||
/* fixup and defrag children */
|
||||
#if SPACESHIP_WITH_PREV
|
||||
unused->ssc_prev = prev_size;
|
||||
#endif
|
||||
uint8_t flags;
|
||||
end = (struct spaceship_chunk *)((intptr_t)unused + used_size);
|
||||
for (last = unused; last != end; last = spaceship_get_next(last)) {
|
||||
flags = last->ssc_flags;
|
||||
last->ssc_flags &= ~SPACESHIP_FLAG_LAST;
|
||||
#if SPACESHIP_WITH_SUB
|
||||
spaceship_defrag(spaceship_get_sub(last));
|
||||
#endif
|
||||
#if SPACESHIP_WITH_PARENT
|
||||
last->ssc_parent -= unused_size;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* create unused chunk at end */
|
||||
spaceship_init(end, unused_size);
|
||||
end->ssc_flags = flags;
|
||||
unused = end;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define SPACESHIP_WITH_PARENT 1
|
||||
#define SPACESHIP_WITH_SUB 1
|
||||
#define SPACESHIP_WITH_PARENT 1 && SPACESHIP_WITH_SUB
|
||||
#define SPACESHIP_WITH_PREV 1
|
||||
|
||||
|
||||
|
@ -19,7 +20,10 @@ enum spaceship_flag
|
|||
|
||||
struct spaceship_chunk
|
||||
{
|
||||
size_t ssc_base, ssc_size;
|
||||
size_t ssc_size;
|
||||
#if SPACESHIP_WITH_SUB
|
||||
size_t ssc_base;
|
||||
#endif
|
||||
#if SPACESHIP_WITH_PARENT
|
||||
ptrdiff_t ssc_parent;
|
||||
#endif
|
||||
|
@ -36,12 +40,12 @@ struct spaceship_chunk
|
|||
|
||||
/* init spaceship static memory chunk */
|
||||
void spaceship_init(void *chunk, size_t size);
|
||||
/* init sub-allocation space, leaving `base_size` bytes for the base structure */
|
||||
int spaceship_init_sub(struct spaceship_chunk *chunk, size_t base_size);
|
||||
/* allocate `size` bytes in chunk */
|
||||
void *spaceship_alloc(void *chunk, size_t size);
|
||||
/* free previously-allocated bytes */
|
||||
void spaceship_free(struct spaceship_chunk *chunk);
|
||||
/* defragment chunk. only do this if there are no active pointers. */
|
||||
void spaceship_defrag(struct spaceship_chunk *chunk);
|
||||
|
||||
static inline size_t spaceship_get_size(struct spaceship_chunk *chunk)
|
||||
{
|
||||
|
@ -51,6 +55,19 @@ static inline size_t spaceship_get_size(struct spaceship_chunk *chunk)
|
|||
return chunk->ssc_size;
|
||||
}
|
||||
|
||||
#if SPACESHIP_WITH_SUB
|
||||
/* init sub-allocation space, leaving `base_size` bytes for the base structure */
|
||||
int spaceship_init_sub(struct spaceship_chunk *chunk, size_t base_size);
|
||||
|
||||
static inline size_t spaceship_get_sub_size(struct spaceship_chunk *chunk)
|
||||
{
|
||||
if (!chunk || !(chunk->ssc_flags & SPACESHIP_FLAG_USED)) {
|
||||
return 0;
|
||||
}
|
||||
return chunk->ssc_size - chunk->ssc_base;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* tree features
|
||||
|
@ -92,6 +109,8 @@ static inline void *spaceship_get_next_sibling(struct spaceship_chunk *chunk)
|
|||
return spaceship_get_first_used(spaceship_get_next(chunk));
|
||||
}
|
||||
|
||||
|
||||
#if SPACESHIP_WITH_SUB
|
||||
/* get sub-allocation chunk */
|
||||
static inline struct spaceship_chunk *spaceship_get_sub(struct spaceship_chunk *chunk)
|
||||
{
|
||||
|
@ -112,6 +131,7 @@ static inline void *spaceship_get_last_child(struct spaceship_chunk *chunk)
|
|||
{
|
||||
return spaceship_get_last_used(spaceship_get_sub(chunk));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if SPACESHIP_WITH_PARENT
|
||||
|
|
Loading…
Reference in New Issue