diff options
| author | Kacper <kacper@mail.openlinux.dev> | 2025-12-07 20:10:31 +0100 |
|---|---|---|
| committer | Kacper <kacper@mail.openlinux.dev> | 2025-12-07 20:10:31 +0100 |
| commit | fc00c656c96528112d05cf0edf8631bd5eaea446 (patch) | |
| tree | a6e0e6c588191a8bd1c64afc3b7a258e3e66c236 /lib/libc/stdlib/free.c | |
Add build system scaffolding and libc headers
Diffstat (limited to 'lib/libc/stdlib/free.c')
| -rw-r--r-- | lib/libc/stdlib/free.c | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/lib/libc/stdlib/free.c b/lib/libc/stdlib/free.c new file mode 100644 index 00000000..40320dc7 --- /dev/null +++ b/lib/libc/stdlib/free.c @@ -0,0 +1,101 @@ +#include <libc.h> +#include <sys/mman.h> +#include <atomic.h> +#include <malloc.h> +#include <stdint.h> +#include <stdbool.h> + +void free(void *ptr) +{ + if (ptr == NULL) { + return; + } + + LIBC_LOCK(libc.lock.malloc); + + struct page *p = __malloc_pvec; + int found_in_pages = 0; + + while (p) { + if ((uintptr_t)ptr >= (uintptr_t)p->heap && + (uintptr_t)ptr < (uintptr_t)(p->heap + (p->block.size * + p->block.count))) { + size_t offset = (uintptr_t)ptr - (uintptr_t)p->heap; + size_t index = offset / p->block.size; + size_t byte_index = index / 8; + size_t bit_index = index % 8; + + LIBC_LOCK(p->lock); + if (p->bitmap[byte_index] & (1 << bit_index)) { + p->bitmap[byte_index] &= ~(1 << bit_index); + p->block.used--; + found_in_pages = 1; + } + LIBC_UNLOCK(p->lock); + + if (found_in_pages && p->block.used == 0) { + if (p->prev) + p->prev->next = p->next; + if (p->next) + p->next->prev = p->prev; + if (p == __malloc_pvec) + __malloc_pvec = p->next; + + munmap(p, (p->flags == PAGE_SMALL) ? + SMALL_PAGE_SIZE : + (p->flags == PAGE_MEDIUM) ? + MEDIUM_PAGE_SIZE : + LARGE_PAGE_SIZE); + } + + LIBC_UNLOCK(libc.lock.malloc); + return; + } + p = p->next; + } + + void **orig_ptr_slot = (void **)((uintptr_t)ptr - sizeof(void *)); + void *potential_orig = *orig_ptr_slot; + + p = __malloc_pvec; + while (p) { + if ((uintptr_t)potential_orig >= (uintptr_t)p->heap && + (uintptr_t)potential_orig < + (uintptr_t)(p->heap + + (p->block.size * p->block.count))) { + size_t offset = + (uintptr_t)potential_orig - (uintptr_t)p->heap; + size_t index = offset / p->block.size; + size_t byte_index = index / 8; + size_t bit_index = index % 8; + + LIBC_LOCK(p->lock); + if (p->bitmap[byte_index] & (1 << bit_index)) { + p->bitmap[byte_index] &= ~(1 << bit_index); + p->block.used--; + } + LIBC_UNLOCK(p->lock); + + if (p->block.used == 0) { + if (p->prev) + p->prev->next = p->next; + if (p->next) + p->next->prev = p->prev; + if (p == __malloc_pvec) + __malloc_pvec = p->next; + + munmap(p, (p->flags == PAGE_SMALL) ? + SMALL_PAGE_SIZE : + (p->flags == PAGE_MEDIUM) ? + MEDIUM_PAGE_SIZE : + LARGE_PAGE_SIZE); + } + + LIBC_UNLOCK(libc.lock.malloc); + return; + } + p = p->next; + } + + LIBC_UNLOCK(libc.lock.malloc); +} |
