summaryrefslogtreecommitdiff
path: root/src/kernel/malloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel/malloc.c')
-rw-r--r--src/kernel/malloc.c142
1 files changed, 95 insertions, 47 deletions
diff --git a/src/kernel/malloc.c b/src/kernel/malloc.c
index 7efd5a5..8ba00dc 100644
--- a/src/kernel/malloc.c
+++ b/src/kernel/malloc.c
@@ -6,23 +6,28 @@
#include <stdbool.h>
#include <stdint.h>
-#define MALLOC_MAGIC 0xA770C666
-
-struct malloc_hdr {
- uint32_t magic;
- uint32_t page_amt;
- struct malloc_hdr *next, *prev;
+#define MALLOC_MAGIC 0x616c6c6f63686472
+#define DESCLEN 8
+
+typedef struct Allocation Allocation;
+struct Allocation {
+ uint64_t magic;
+ uint64_t len;
+ Allocation *next, *prev;
void *stacktrace[4];
+ char desc[DESCLEN];
};
-struct malloc_hdr *malloc_last = NULL;
+Allocation *malloc_last = NULL;
extern uint8_t pbitmap[]; /* linker.ld */
static size_t pbitmap_len; /* in bytes */
static size_t pbitmap_firstfree = 0;
-static bool bitmap_get(long i) {
+static
+bool bitmap_get(long i)
+{
assert(i >= 0);
size_t b = i / 8;
uint8_t m = 1 << (i&7);
@@ -30,7 +35,9 @@ static bool bitmap_get(long i) {
return (pbitmap[b]&m) != 0;
}
-static bool bitmap_set(long i, bool v) {
+static
+bool bitmap_set(long i, bool v)
+{
assert(i >= 0);
size_t b = i / 8;
uint8_t m = 1 << (i&7);
@@ -41,18 +48,30 @@ static bool bitmap_set(long i, bool v) {
return prev;
}
-static long toindex(void *p) {
+static
+long toindex(void *p)
+{
return ((long)p - (long)pbitmap) / PAGE_SIZE;
}
-void mem_init(void *memtop) {
+static
+size_t page_amt(size_t bytes)
+{
+ return (bytes + PAGE_SIZE - 1) / PAGE_SIZE;
+}
+
+void
+mem_init(void *memtop)
+{
kprintf("memory %8x -> %8x\n", &_bss_end, memtop);
pbitmap_len = toindex(memtop) / 8;
memset(pbitmap, 0, pbitmap_len);
mem_reserve(pbitmap, pbitmap_len);
}
-void mem_reserve(void *addr, size_t len) {
+void
+mem_reserve(void *addr, size_t len)
+{
kprintf("reserved %8x -> %8x\n", addr, addr + len);
/* align to the previous page */
@@ -67,21 +86,36 @@ void mem_reserve(void *addr, size_t len) {
}
}
-void mem_debugprint(void) {
- size_t total = 0;
- kprintf("current kmallocs:\n");
- kprintf("addr pages\n");
- for (struct malloc_hdr *iter = malloc_last; iter; iter = iter->prev) {
- kprintf("%08x %05x", iter, iter->page_amt);
- for (size_t i = 0; i < 4; i++)
- kprintf(" k/%08x", iter->stacktrace[i]);
- kprintf("\n peek 0x%x\n", *(uint32_t*)(&iter[1]));
- total++;
+void
+mem_debugprint(void)
+{
+ size_t count = 0, bytes = 0, pages = 0;
+ kprintf("[kern] current allocations:\n");
+ for (Allocation *iter = malloc_last; iter; iter = iter->prev) {
+ kprintf(
+ "%08p %6dB %.8s ",
+ ((void*)iter) + sizeof(Allocation),
+ iter->len - sizeof(Allocation),
+ iter->desc
+ );
+ for (size_t i = 0; i < 4; i++) {
+ kprintf(" k/%08x", iter->stacktrace[i]);
+ }
+ kprintf("\n");
+
+ count++;
+ bytes += iter->len;
+ pages += page_amt(iter->len);
}
- kprintf(" total 0x%x\n", total);
+ kprintf(
+ "%d in total, %d bytes, %d pages = %dB used\n",
+ count, bytes, pages, pages*PAGE_SIZE
+ );
}
-void *page_alloc(size_t pages) {
+void
+*page_alloc(size_t pages)
+{
/* i do realize how painfully slow this is */
size_t streak = 0;
for (size_t i = pbitmap_firstfree; i < pbitmap_len * 8; i++) {
@@ -102,14 +136,18 @@ void *page_alloc(size_t pages) {
panic_unimplemented();
}
-void *page_zalloc(size_t pages) {
+void
+*page_zalloc(size_t pages)
+{
void *p = page_alloc(pages);
memset(p, 0, pages * PAGE_SIZE);
return p;
}
-// frees `pages` consecutive pages starting from *first
-void page_free(void *addr, size_t pages) {
+/* frees `pages` consecutive pages starting from *first */
+void
+page_free(void *addr, size_t pages)
+{
assert(addr >= (void*)pbitmap);
size_t first = toindex(addr);
for (size_t i = 0; i < pages; i++) {
@@ -122,27 +160,35 @@ void page_free(void *addr, size_t pages) {
}
}
-void kmalloc_sanity(const void *addr) {
+void
+kmalloc_sanity(const void *addr)
+{
assert(addr);
- const struct malloc_hdr *hdr = addr - sizeof(struct malloc_hdr);
+ const Allocation *hdr = addr - sizeof(Allocation);
assert(hdr->magic == MALLOC_MAGIC);
if (hdr->next) assert(hdr->next->prev == hdr);
if (hdr->prev) assert(hdr->prev->next == hdr);
}
-void *kmalloc(size_t len) {
- // TODO better kmalloc
-
- struct malloc_hdr *hdr;
+// TODO better kmalloc
+void
+*kmalloc(size_t len, const char *desc)
+{
+ Allocation *hdr;
void *addr;
- uint32_t pages;
-
- len += sizeof(struct malloc_hdr);
- pages = len / PAGE_SIZE + 1;
- hdr = page_alloc(pages);
+ len += sizeof(Allocation);
+ hdr = page_alloc(page_amt(len));
hdr->magic = MALLOC_MAGIC;
- hdr->page_amt = pages;
+ hdr->len = len;
+
+ memset(hdr->desc, ' ', DESCLEN);
+ if (desc) {
+ for (int i = 0; i < DESCLEN; i++) {
+ if (desc[i] == '\0') break;
+ hdr->desc[i] = desc[i];
+ }
+ }
hdr->next = NULL;
hdr->prev = malloc_last;
@@ -156,7 +202,7 @@ void *kmalloc(size_t len) {
malloc_last = hdr;
- addr = (void*)hdr + sizeof(struct malloc_hdr);
+ addr = (void*)hdr + sizeof(Allocation);
#ifndef NDEBUG
memset(addr, 0xCC, len);
#endif
@@ -164,13 +210,16 @@ void *kmalloc(size_t len) {
return addr;
}
-void kfree(void *ptr) {
- struct malloc_hdr *hdr;
- uint32_t page_amt;
+void
+kfree(void *ptr)
+{
+ Allocation *hdr;
+ size_t pages;
if (ptr == NULL) return;
- hdr = ptr - sizeof(struct malloc_hdr);
+ hdr = ptr - sizeof(Allocation);
kmalloc_sanity(ptr);
+ pages = page_amt(hdr->len);
hdr->magic = ~MALLOC_MAGIC; // (hopefully) detect double frees
if (hdr->next)
@@ -179,9 +228,8 @@ void kfree(void *ptr) {
hdr->prev->next = hdr->next;
if (malloc_last == hdr)
malloc_last = hdr->prev;
- page_amt = hdr->page_amt;
#ifndef NDEBUG
- memset(hdr, 0xC0, page_amt * PAGE_SIZE);
+ memset(hdr, 0xC0, pages * PAGE_SIZE);
#endif
- page_free(hdr, page_amt);
+ page_free(hdr, pages);
}