mirror of
https://codeberg.org/andyscott/marCsweep.git
synced 2024-12-22 01:33:11 -05:00
malloc: defined gc_malloc
, gc_free
, and debug func chk_freelist
This commit is contained in:
parent
5749c68035
commit
3ecb5d560f
1 changed files with 58 additions and 5 deletions
|
@ -19,8 +19,9 @@ static inline struct gc_chunk *magic(void *mem)
|
||||||
return (struct gc_chunk *)((uint64_t *)mem - MAGIC);
|
return (struct gc_chunk *)((uint64_t *)mem - MAGIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Aligns the amount of memory requested by the user with chunk size
|
|
||||||
/*
|
/*
|
||||||
|
* Aligns the amount of memory requested by the user with chunk size
|
||||||
|
*
|
||||||
* Example: User requests 1 byte
|
* Example: User requests 1 byte
|
||||||
* LHS
|
* LHS
|
||||||
* requested size = 0b00000001
|
* requested size = 0b00000001
|
||||||
|
@ -42,6 +43,26 @@ static inline uint32_t align(uint32_t size)
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Useful for debugging after find or merge are called
|
||||||
|
static void chk_freelist(void)
|
||||||
|
{
|
||||||
|
struct gc_chunk *next = freelist;
|
||||||
|
struct gc_chunk *prev = NULL;
|
||||||
|
|
||||||
|
while (next != NULL) {
|
||||||
|
assert(next->free);
|
||||||
|
assert(next->merge == 0);
|
||||||
|
assert(next->size >= MIN);
|
||||||
|
assert(get_footer(next) == next->size);
|
||||||
|
assert(next->prev == prev);
|
||||||
|
struct gc_chunk *after = find_next_chunk(next);
|
||||||
|
assert(after->merge == 1);
|
||||||
|
assert(after->free == 0);
|
||||||
|
prev = next;
|
||||||
|
next = next->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct gc_chunk *find_next_chunk(struct gc_chunk *curr)
|
struct gc_chunk *find_next_chunk(struct gc_chunk *curr)
|
||||||
{
|
{
|
||||||
unsigned size = curr->size;
|
unsigned size = curr->size;
|
||||||
|
@ -69,8 +90,7 @@ int get_footer(struct gc_chunk *curr)
|
||||||
|
|
||||||
struct gc_chunk *init_gc_chunk(void)
|
struct gc_chunk *init_gc_chunk(void)
|
||||||
{
|
{
|
||||||
const size_t page_size = getpagesize();
|
const size_t len = getpagesize();
|
||||||
const size_t len = page_size * sizeof(uint64_t);
|
|
||||||
struct gc_chunk *chunk =
|
struct gc_chunk *chunk =
|
||||||
(struct gc_chunk *)mmap(NULL, len, PROT_READ | PROT_WRITE,
|
(struct gc_chunk *)mmap(NULL, len, PROT_READ | PROT_WRITE,
|
||||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||||
|
@ -78,7 +98,7 @@ struct gc_chunk *init_gc_chunk(void)
|
||||||
if (chunk == MAP_FAILED)
|
if (chunk == MAP_FAILED)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
chunk->size = page_size - MAGIC - OVERHEAD;
|
chunk->size = len - MAGIC - OVERHEAD;
|
||||||
chunk->merge = 0;
|
chunk->merge = 0;
|
||||||
chunk->free = 1;
|
chunk->free = 1;
|
||||||
chunk->next = NULL;
|
chunk->next = NULL;
|
||||||
|
@ -92,11 +112,16 @@ struct gc_chunk *init_gc_chunk(void)
|
||||||
sentinel->next = NULL;
|
sentinel->next = NULL;
|
||||||
sentinel->prev = chunk;
|
sentinel->prev = chunk;
|
||||||
|
|
||||||
|
chk_freelist(); // TODO: Remove this line after debugging
|
||||||
return chunk;
|
return chunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct gc_chunk *find_free_chunk(size_t size)
|
struct gc_chunk *find_free_chunk(size_t size)
|
||||||
{
|
{
|
||||||
|
// HACK: The first loop will run forever if we can never get a big enough chunk
|
||||||
|
if (size > getpagesize())
|
||||||
|
return NULL;
|
||||||
|
|
||||||
struct gc_chunk *found;
|
struct gc_chunk *found;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
@ -104,6 +129,7 @@ struct gc_chunk *find_free_chunk(size_t size)
|
||||||
while (found != NULL) {
|
while (found != NULL) {
|
||||||
if (found->size >= size) {
|
if (found->size >= size) {
|
||||||
// found, TODO: split when appropriate
|
// found, TODO: split when appropriate
|
||||||
|
// remaining block needs to be at least MIN + OVERHEAD
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
found = found->next;
|
found = found->next;
|
||||||
|
@ -129,7 +155,9 @@ void merge_chunk(struct gc_chunk *curr)
|
||||||
{
|
{
|
||||||
if (curr->merge) {
|
if (curr->merge) {
|
||||||
struct gc_chunk *prev = find_prev_chunk(curr);
|
struct gc_chunk *prev = find_prev_chunk(curr);
|
||||||
|
chk_freelist(); // TODO: Remove this line after debugging
|
||||||
struct gc_chunk *next = find_next_chunk(curr);
|
struct gc_chunk *next = find_next_chunk(curr);
|
||||||
|
chk_freelist(); // TODO: Remove this line after debugging
|
||||||
if (next->free) {
|
if (next->free) {
|
||||||
// TODO Case 1: merge prev and next
|
// TODO Case 1: merge prev and next
|
||||||
|
|
||||||
|
@ -139,6 +167,7 @@ void merge_chunk(struct gc_chunk *curr)
|
||||||
set_footer(prev);
|
set_footer(prev);
|
||||||
} else {
|
} else {
|
||||||
struct gc_chunk *next = find_next_chunk(curr);
|
struct gc_chunk *next = find_next_chunk(curr);
|
||||||
|
chk_freelist(); // TODO: Remove this line after debugging
|
||||||
if (next->free) {
|
if (next->free) {
|
||||||
// TODO Case 3: merge with after
|
// TODO Case 3: merge with after
|
||||||
} else {
|
} else {
|
||||||
|
@ -148,3 +177,27 @@ void merge_chunk(struct gc_chunk *curr)
|
||||||
set_footer(curr);
|
set_footer(curr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *gc_malloc(size_t size)
|
||||||
|
{
|
||||||
|
if (size == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
uint32_t bytes = align(size);
|
||||||
|
struct gc_chunk *curr = find_free_chunk(bytes);
|
||||||
|
chk_freelist(); // TODO: Remove this line after debugging
|
||||||
|
|
||||||
|
if (curr == NULL)
|
||||||
|
return curr;
|
||||||
|
|
||||||
|
return hide(curr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gc_free(void *ptr)
|
||||||
|
{
|
||||||
|
if (ptr != NULL) {
|
||||||
|
struct gc_chunk *curr = magic(ptr);
|
||||||
|
merge_chunk(curr);
|
||||||
|
chk_freelist(); // TODO: Remove this line after debugging
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue