diff options
author | dweller <dweller@cabin.digital> | 2025-04-04 00:00:52 +0300 |
---|---|---|
committer | dweller <dweller@cabin.digital> | 2025-04-04 00:00:52 +0300 |
commit | 0533b005901b976e3e6d11d7ec5078118bbe5a2f (patch) | |
tree | a74846c72ca4f30bff5a3bae03bfffcac7bbac29 /sources/mem.c | |
parent | 9c2842629f2e5f17c6949b5ff37c972f7dd62d4a (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.c | 139 |
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; +} + |