summaryrefslogtreecommitdiff
path: root/sources/mem.c
diff options
context:
space:
mode:
authordweller <dweller@cabin.digital>2025-04-04 00:00:52 +0300
committerdweller <dweller@cabin.digital>2025-04-04 00:00:52 +0300
commit0533b005901b976e3e6d11d7ec5078118bbe5a2f (patch)
treea74846c72ca4f30bff5a3bae03bfffcac7bbac29 /sources/mem.c
parent9c2842629f2e5f17c6949b5ff37c972f7dd62d4a (diff)
fix DRW instruction, add arena to iui so I don't need to manage label buffers
Diffstat (limited to 'sources/mem.c')
-rw-r--r--sources/mem.c139
1 files changed, 139 insertions, 0 deletions
diff --git a/sources/mem.c b/sources/mem.c
new file mode 100644
index 0000000..3b111f7
--- /dev/null
+++ b/sources/mem.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2025 dwlr <dweller@cabin.digital>
+ *
+ * BSD 3-Clause License (BSD-3-Clause)
+ * See LICENSE for details
+ */
+
+
+typedef struct
+{
+ u8* base;
+ u8* cursor;
+ usize size;
+
+} arena;
+
+
+typedef struct
+{
+ u8* base;
+ ssize pages;
+
+} do_pagefault_args;
+void* do_pagefault(void* arg)
+{
+ ssize i = 0;
+ ssize p = mm_pagesize();
+ do_pagefault_args* args = (do_pagefault_args*)arg;
+ if(!args)
+ {
+ report(ERR, "do_pagefault() with NULL args!\n");
+ return NULL;
+ }
+
+ for(i = 0; i < args->pages; i++) args->base[p * i] = 0;
+
+ return NULL;
+}
+
+bool ar_create(usize size, bool prefault, arena* ar)
+{
+ ssize p = mm_pagesize();
+
+ if(!ar) return false;
+ if(size <= 0) return false;
+
+ size += (size % p) ? (p - (size % p)) : 0;
+
+ ar->base = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
+ if(ar->base == MAP_FAILED) return false;
+ ar->size = size;
+ ar->cursor = ar->base;
+
+ if(prefault)
+ {
+ ssize i = 0;
+ ssize cpus = cpu_count();
+ pthread_t* t = NULL;
+ do_pagefault_args* args = NULL;
+
+ t = calloc(cpus, sizeof(t[0]));
+ if(!t) report(FATAL, "ar_create()/prefault/calloc(t) failed!\n");
+ else
+ {
+ args = calloc(cpus, sizeof(args[0]));
+ if(!args)
+ {
+ free(t);
+ report(FATAL, "ar_create()/prefault/calloc(args) failed!\n");
+ }
+ }
+
+ for(i = 1; i < cpus; i++)
+ {
+ args[i].base = ar->base + ((size / cpus) * i);
+ args[i].pages = ((size / p) / cpus);
+ pthread_create(&t[i], NULL, do_pagefault, &args[i]);
+ }
+
+ args[0].base = ar->base;
+ args[0].pages = ((size / p) / cpus);
+ do_pagefault(&args[0]);
+
+ for(i = 1; i < cpus; i++) pthread_join(t[i], NULL);
+
+ free(args);
+ free(t);
+ }
+
+ return true;
+}
+
+#define ar_push(ar, sz) ar_pusha((ar), (sz), sizeof(int), true)
+void* ar_pusha(arena* ar, usize size, usize alignment, bool zero)
+{
+ usize cur, ovfl;
+
+ if(!ar) return NULL;
+ else
+ {
+ cur = align((usize)ar->cursor, alignment);
+ ovfl = (cur + size);
+ if(ovfl < cur) return NULL;
+
+ if(ovfl <= (usize)(ar->base + ar->size))
+ {
+ ar->cursor = (u8*)ovfl;
+
+ if(zero) memset((u8*)cur, 0, size);
+ return (u8*)cur;
+ }
+ else
+ {
+ report(ERR, "arena(%P): overflow @ %P x %llu\n", ar, cur, size);
+ return NULL;
+ }
+ }
+}
+
+void ar_pop(arena* ar, usize size)
+{
+ if(!ar) return;
+ else ar->cursor = min(ar->base, ar->cursor - size);
+}
+
+void ar_clear(arena* ar)
+{
+ if(ar) ar->cursor = ar->base;
+}
+
+void ar_destroy(arena* ar)
+{
+ if(!ar) return;
+
+ munmap(ar->base, ar->size);
+ ar->base = ar->cursor = NULL;
+ ar->size = 0;
+}
+