feat: working and refactored to remove dedicated linked-list in favor of just using the headers

This commit is contained in:
jackjohn7 2026-06-17 01:10:19 -05:00
parent 8af978556a
commit 1f058f0c4e

View file

@ -14,38 +14,32 @@ struct Header {
size_t size; size_t size;
bool is_free; bool is_free;
struct Header *next; struct Header *next;
struct Header *next_free;
}; };
struct Footer { struct Footer {
struct Header *header; struct Header *header;
}; };
struct Block {
struct Header *header;
struct Block *next;
};
static uint8_t heap[HEAP_SIZE]; static uint8_t heap[HEAP_SIZE];
static struct Block *free_stack; static struct Header *free_stack;
static bool initialized = false; static bool initialized = false;
struct Footer *footer(struct Header *hdr) { struct Footer *footer(struct Header *hdr) {
return (struct Footer *)((uint8_t *)hdr + hdr->size); return (struct Footer *)((uint8_t *)hdr + HEADER_SIZE + hdr->size);
} }
struct Block *pop_first_fit(size_t size) { struct Header *pop_first_fit(size_t size) {
struct Block *head = free_stack; struct Header *head = free_stack;
if (head->header->size >= size) { if (head->size >= size) {
free_stack = head->next; // remove from free stack free_stack = head->next_free; // remove from free stack
return head; return head;
} }
while (head != NULL) { while (head != NULL) {
struct Block *next = head->next; struct Header *next = head->next_free;
if (next == NULL) return NULL; if (next == NULL) return NULL;
if (next->header->size >= size) { if (next->size >= size) {
head->next = next->next; // remove from free stack head->next_free = next->next_free; // remove from free stack
return next; return next;
} }
head = next; head = next;
@ -53,32 +47,28 @@ struct Block *pop_first_fit(size_t size) {
return NULL; return NULL;
} }
struct Block *pop(struct Block *ptr) { struct Header *pop(struct Header *ptr) {
struct Block *head = free_stack; struct Header *head = free_stack;
if (head == ptr) { if (head == ptr) {
free_stack = head->next; free_stack = head->next_free;
return head; return head;
} }
while (head != NULL) { while (head != NULL) {
struct Block *next = head->next; struct Header *next = head->next_free;
if (next == NULL) break; // if next is NULL, deref below will fault if (next == NULL) break; // if next is NULL, deref below will fault
if (next == ptr) { if (next == ptr) {
head->next = next->next; head->next_free = next->next_free;
return next; return next;
} }
head = next;
} }
return NULL; return NULL;
} }
struct Block *push_header(struct Header *hdr) { struct Header *push_header(struct Header *hdr) {
struct Block *blk = malloc(sizeof(struct Block)); hdr->next_free = free_stack;
blk->header = hdr; free_stack = hdr;
blk->next = free_stack; return hdr;
free_stack = blk;
}
struct Block *pop_header(struct Header *ptr) {
return NULL;
} }
size_t next_multiple_of_align(size_t size) { size_t next_multiple_of_align(size_t size) {
@ -88,28 +78,27 @@ size_t next_multiple_of_align(size_t size) {
void initialize() { void initialize() {
// initialize the free list to be a single element containing the entire block // initialize the free list to be a single element containing the entire block
size_t initial_block_size = HEAP_SIZE - (HEADER_SIZE + FOOTER_SIZE); size_t initial_block_size = HEAP_SIZE - (HEADER_SIZE + FOOTER_SIZE);
free_stack = malloc(sizeof(struct Block));
// write a header // write a header
struct Header *hdr = (struct Header *) heap; // first two alignment slots taken by initial header struct Header *hdr = (struct Header *) heap; // first two alignment slots taken by initial header
free_stack = hdr;
push_header(hdr); push_header(hdr);
free_stack->header->is_free = true; free_stack->is_free = true;
free_stack->header->size = initial_block_size; free_stack->size = initial_block_size;
free_stack->header->next = NULL;
free_stack->next = NULL; free_stack->next = NULL;
free_stack->next_free = NULL;
// write a footer to heap // write a footer to heap
struct Footer *ftr = (struct Footer *) (heap + initial_block_size - ALIGNMENT); struct Footer *ftr = footer(hdr);
ftr->header = hdr; ftr->header = hdr;
initialized = true; initialized = true;
} }
struct Block *shrink(struct Block *ptr, size_t size) { struct Header *shrink(struct Header *hdr, size_t size) {
// given a size, shrink a block down to the appropriate alignment. // given a size, shrink a block down to the appropriate alignment.
// if align(size) + ALIGNMENT*3 is equal to current size, just return initial ptr with noop // if align(size) + ALIGNMENT*3 is equal to current size, just return initial ptr with noop
// otherwise, shrink it down so that we have two blocks. // otherwise, shrink it down so that we have two blocks.
// Push the right block to the free stack // Push the right block to the free stack
// Return left block // Return left block
size = next_multiple_of_align(size); // align if not already so size = next_multiple_of_align(size); // align if not already so
struct Header *hdr = ptr->header;
size_t other_size = hdr->size-size-(HEADER_SIZE + FOOTER_SIZE); size_t other_size = hdr->size-size-(HEADER_SIZE + FOOTER_SIZE);
// if we have space for a full alignment, then a single block of 16 bytes can be allocated there // if we have space for a full alignment, then a single block of 16 bytes can be allocated there
if (other_size >= ALIGNMENT) { if (other_size >= ALIGNMENT) {
@ -130,46 +119,41 @@ struct Block *shrink(struct Block *ptr, size_t size) {
// push new block to stack // push new block to stack
push_header(next_hdr); push_header(next_hdr);
} }
return ptr; return hdr;
} }
/** /**
* Allocate memory via bump allocation * Allocate memory via free-list allocation
*/ */
void *jalloc(size_t size) { void *jalloc(size_t size) {
if (!initialized) initialize(); if (!initialized) initialize();
// Total size of allocation = HEADER(padded to ALIGNMENT) + size(padded to ALIGNMENT) + FOOTER(padded to ALIGNMENT) // Total size of allocation = HEADER(padded to ALIGNMENT) + size(padded to ALIGNMENT) + FOOTER(padded to ALIGNMENT)
size_t aligned_size = next_multiple_of_align(size); size_t aligned_size = next_multiple_of_align(size);
struct Block *blk = pop_first_fit(aligned_size); struct Header *hdr = pop_first_fit(aligned_size);
if (blk == NULL) return NULL; if (hdr == NULL) return NULL;
blk = shrink(blk, aligned_size); hdr = shrink(hdr, aligned_size);
struct Header *hdr = blk->header;
struct Footer *ftr = footer(hdr); struct Footer *ftr = footer(hdr);
uint8_t* heap_ptr = (void *) ftr + FOOTER_SIZE; // set next ptr
if ((uint8_t *)heap_ptr > (heap + HEAP_SIZE)) heap_ptr = NULL; uint8_t* next_ptr = (void *) ftr + FOOTER_SIZE; // set next adjacent ptr
if ((uint8_t *)next_ptr > (heap + HEAP_SIZE)) next_ptr = NULL;
hdr->size = aligned_size; hdr->size = aligned_size;
hdr->next = (struct Header *)heap_ptr; hdr->next = (struct Header *)next_ptr;
hdr->is_free = false; hdr->is_free = false;
ftr->header = hdr; ftr->header = hdr;
return (void*)hdr + HEADER_SIZE; return (void*)hdr + HEADER_SIZE;
} }
void jfree(void *ptr) { void jfree(void *ptr) {
printf("freeing\n\n");
struct Header *hdr = (struct Header *)(ptr-HEADER_SIZE); struct Header *hdr = (struct Header *)(ptr-HEADER_SIZE);
struct Footer *ftr = (struct Footer *)((uint8_t *)hdr+hdr->size); struct Footer *ftr = footer(hdr);
hdr->is_free = true; hdr->is_free = true;
if ((uint8_t *)hdr > heap) { // if this is greater, then there ought to be a foot to the left if ((uint8_t *)hdr > heap) { // if this is greater, then there ought to be a foot to the left
printf("checking coalescing left\n\n");
struct Footer *prev_ftr = (struct Footer *)((uint8_t *)hdr-FOOTER_SIZE); struct Footer *prev_ftr = (struct Footer *)((uint8_t *)hdr-FOOTER_SIZE);
struct Header *prev_hdr = prev_ftr->header; struct Header *prev_hdr = prev_ftr->header;
if (prev_hdr->is_free) { if (prev_hdr->is_free) {
printf("coalescing left\n\n"); pop(prev_hdr);
pop_header(prev_hdr);
printf("header popped\n\n");
prev_hdr->size += hdr->size + HEADER_SIZE + FOOTER_SIZE; prev_hdr->size += hdr->size + HEADER_SIZE + FOOTER_SIZE;
prev_hdr->next=hdr->next; prev_hdr->next=hdr->next;
ftr->header=prev_hdr; ftr->header=prev_hdr;
@ -177,24 +161,16 @@ void jfree(void *ptr) {
} }
} }
if (hdr->next != NULL) { if (hdr->next != NULL) {
printf("checking coalescing right\n\n");
struct Header *next_hdr = hdr->next; struct Header *next_hdr = hdr->next;
struct Footer *next_ftr = footer(next_hdr); struct Footer *next_ftr = footer(next_hdr);
assert(next_ftr != NULL);
assert(next_ftr->header != NULL);
if (next_hdr->is_free) { if (next_hdr->is_free) {
printf("coalescing right\n\n"); pop(next_hdr);
pop_header(next_hdr);
printf("header popped\n\n");
hdr->size += next_hdr->size + HEADER_SIZE + FOOTER_SIZE; hdr->size += next_hdr->size + HEADER_SIZE + FOOTER_SIZE;
hdr->next = (struct Header *) ((uint8_t*)next_ftr + FOOTER_SIZE); hdr->next = (struct Header *) ((uint8_t*)next_ftr + FOOTER_SIZE);
if ((uint8_t *)hdr->next > (heap + HEAP_SIZE)) hdr->next = NULL; if ((uint8_t *)hdr->next > (heap + HEAP_SIZE)) hdr->next = NULL;
printf("set next\n\n");
printf("next ftr?: %s\n\n", (uint8_t*)next_ftr);
next_ftr->header = hdr; next_ftr->header = hdr;
ftr = next_ftr; ftr = next_ftr;
} }
} }
printf("pushing free header\n\n");
push_header(hdr); push_header(hdr);
} }