hachem.wtf
aboutsummaryrefslogtreecommitdiff
path: root/user/membrk.c
diff options
context:
space:
mode:
authorhachem <im@hachem.wtf>2026-10-10 08:53:20 +0200
committerhachem <im@hachem.wtf>2026-10-10 08:53:20 +0200
commit89abe49aad1ac7416844f3c5e95655ad2614392b (patch)
treeff9170aa0673b3db76e03ab80a5056e576a48e7b /user/membrk.c
parent7642b3819c90ec0c4686c32e5f89c59cc47cc2d3 (diff)
feat: brk/sbrk syscalls + shitty heap
Diffstat (limited to 'user/membrk.c')
-rw-r--r--user/membrk.c93
1 files changed, 93 insertions, 0 deletions
diff --git a/user/membrk.c b/user/membrk.c
new file mode 100644
index 0000000..f1949cc
--- /dev/null
+++ b/user/membrk.c
@@ -0,0 +1,93 @@
+#include "user.h"
+
+static void check(const char* name, int ok)
+{
+ put(ok ? "ok " : "FAIL ");
+ put(name);
+ put("\n");
+}
+
+void _start(const char* arg, unsigned long arglen)
+{
+ (void)arg;
+ (void)arglen;
+
+ long start = (long)sys_sbrk(0);
+ put("heap base: ");
+ put_int(start);
+ put("\n");
+
+ // obese alloc test
+ char* run[80];
+ for (int i = 0; i < 80; i++)
+ run[i] = (char*)malloc(4000);
+ long run_after = (long)sys_sbrk(0);
+ for (int i = 0; i < 80; i++)
+ free(run[i]);
+ char* merged = (char*)malloc(80 * 4000 - 8000);
+ long merge_after = (long)sys_sbrk(0);
+ check("freed neighbours coalesce", merged != 0 && merge_after <= run_after);
+ free(merged);
+
+ // a pile of small tagged allocations
+ char* blocks[16];
+ for (int i = 0; i < 16; i++)
+ {
+ blocks[i] = (char*)malloc(64);
+ for (int j = 0; j < 64; j++)
+ blocks[i][j] = (char)(i * 7 + j);
+ }
+ int small_ok = 1;
+ for (int i = 0; i < 16; i++)
+ for (int j = 0; j < 64; j++)
+ if (blocks[i][j] != (char)(i * 7 + j))
+ small_ok = 0;
+ check("small allocs keep their data", small_ok);
+
+ // a big block spanning several pages written edge to edge
+ unsigned long big = 20000;
+ unsigned char* buffer = (unsigned char*)malloc(big);
+ for (unsigned long k = 0; k < big; k++)
+ buffer[k] = (unsigned char)(k & 0xff);
+ int big_ok = 1;
+ for (unsigned long k = 0; k < big; k++)
+ if (buffer[k] != (unsigned char)(k & 0xff))
+ big_ok = 0;
+ check("big multi page alloc", big_ok);
+
+ // testing that the the heap must doesnt grow across the loop
+ long churn_before = (long)sys_sbrk(0);
+ for (int i = 0; i < 2000; i++)
+ {
+ void* pointer = malloc(500);
+ free(pointer);
+ }
+ long churn_after = (long)sys_sbrk(0);
+ check("alloc/free churn reclaims (no growth)", churn_before == churn_after);
+
+ // calloc dirty test
+ unsigned char* zeroed = (unsigned char*)calloc(200, 1);
+ int zero_ok = 1;
+ for (int i = 0; i < 200; i++)
+ if (zeroed[i] != 0)
+ zero_ok = 0;
+ check("calloc is zeroed", zero_ok);
+
+ // realloc test
+ char* grown = (char*)malloc(32);
+ for (int i = 0; i < 32; i++)
+ grown[i] = (char)(i + 1);
+ grown = (char*)realloc(grown, 500);
+ int grow_ok = 1;
+ for (int i = 0; i < 32; i++)
+ if (grown[i] != (char)(i + 1))
+ grow_ok = 0;
+ check("realloc grows and preserves data", grow_ok);
+
+ long end = (long)sys_sbrk(0);
+ put("heap high water: ");
+ put_int(end - start);
+ put(" bytes\n");
+
+ sys_exit(0);
+}