From 97ffab0a8472981b927d0f4e81bb72f6ecd69b86 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Wed, 21 Aug 2024 23:31:48 +0300 Subject: add malloc test --- include/kmi/attrs.h | 2 ++ src/pmem.c | 15 ++++++++++++--- src/regions.c | 5 +++-- src/sp_tree.c | 14 +++++++------- src/uapi/dispatch.c | 1 + src/uapi/ipc.c | 2 +- tests/malloc/check.mk | 4 ++++ tests/malloc/init.c | 42 ++++++++++++++++++++++++++++++++++++++++++ tests/malloc/source.mk | 2 ++ tests/scripts/makefile | 1 + 10 files changed, 75 insertions(+), 13 deletions(-) create mode 100644 tests/malloc/check.mk create mode 100644 tests/malloc/init.c create mode 100644 tests/malloc/source.mk diff --git a/include/kmi/attrs.h b/include/kmi/attrs.h index f789310..56aca34 100644 --- a/include/kmi/attrs.h +++ b/include/kmi/attrs.h @@ -50,6 +50,8 @@ /** Don't inline function. */ #define __noinline __attribute__((noinline)) +#define __inline inline __attribute__((always_inline)) + /** Function should not return. */ #define __noreturn __attribute__((noreturn)) diff --git a/src/pmem.c b/src/pmem.c index 47bb319..e2177ea 100644 --- a/src/pmem.c +++ b/src/pmem.c @@ -111,7 +111,9 @@ static pm_t __zero_if(bool populate, pm_t cont, size_t size) */ static size_t __get_set_size(struct mm_bucket *bucket) { - return sizeof(bucket->bmap[0]) + bucket->bits / 8; + return align_up(sizeof(bucket->bmap[0]) + + (bucket->bits + 1) / sizeof(void *), + sizeof(void *)); } /** @@ -149,7 +151,7 @@ static size_t __get_set_index(struct mm_bucket *bucket, struct mm_bmap *bmap) static void __attach_set(struct mm_bucket *bucket, struct mm_bmap *bmap) { /* already attached */ - if (bmap->next) + if (bmap->next || bucket->head == bmap) return; bmap->next = bucket->head; @@ -174,6 +176,9 @@ static void __detach_set(struct mm_bucket *bucket, struct mm_bmap *bmap) if (bmap->prev) bmap->prev->next = bmap->next; + + bmap->next = NULL; + bmap->prev = NULL; } /** @@ -271,6 +276,8 @@ static pm_t __alloc_page(enum mm_order order) __get_bit(bucket, a, &set, &bit); bmap = __get_set(bucket, set); + bmap->next = NULL; + bmap->prev = NULL; bmap->used = 0; bitmap_clear_all(bmap->bits, bmap->size); __attach_set(bucket, bmap); @@ -376,7 +383,9 @@ static pm_t __maybe_populate_bucket(size_t n, pm_t cont, enum mm_order order, bucket->head = NULL; } - size_t set_size = sizeof(struct mm_bmap) + bits / 8; + size_t set_size = align_up(sizeof(struct mm_bmap) + + (bits + 1) / sizeof(void *), + sizeof(void *)); cont += sizeof(struct mm_bucket); diff --git a/src/regions.c b/src/regions.c index 9849ba8..fcfa0cc 100644 --- a/src/regions.c +++ b/src/regions.c @@ -85,8 +85,9 @@ static void free_mem_node(struct mem_region *m) * @param m Free memory region to insert. * @return \c m. */ -static struct mem_region *__insert_free_region(struct mem_region_root *r, - struct mem_region *m) +static __inline struct mem_region *__insert_free_region( + struct mem_region_root *r, + struct mem_region *m) { /* this could be simplified by using my gsptrees in kmx, but at least * this ensures 'inlining' of the condition checking so I'll let it stay diff --git a/src/sp_tree.c b/src/sp_tree.c index 5166cc3..0c5b3c4 100644 --- a/src/sp_tree.c +++ b/src/sp_tree.c @@ -21,7 +21,7 @@ * * @param n Node to turn left. */ -static void __sp_turn_left(struct sp_node *n) +static __inline void __sp_turn_left(struct sp_node *n) { struct sp_node *l = sp_left(n); struct sp_node *p = sp_paren(n); @@ -51,7 +51,7 @@ static void __sp_turn_left(struct sp_node *n) * * @param n Node to turn right. */ -static void __sp_turn_right(struct sp_node *n) +static __inline void __sp_turn_right(struct sp_node *n) { struct sp_node *r = sp_right(n); struct sp_node *p = sp_paren(n); @@ -78,7 +78,7 @@ static void __sp_turn_right(struct sp_node *n) * @param n Node to calculate balance for. * @return Balance of node. */ -static int_fast16_t __sp_balance(struct sp_node *n) +static __inline int_fast16_t __sp_balance(struct sp_node *n) { int_fast16_t l = 0; int_fast16_t r = 0; @@ -98,7 +98,7 @@ static int_fast16_t __sp_balance(struct sp_node *n) * @param n Node to calculate highest hint for. * @return Highest hint. */ -static int_fast16_t __sp_max_hint(struct sp_node *n) +static __inline int_fast16_t __sp_max_hint(struct sp_node *n) { int_fast16_t l = 0; int_fast16_t r = 0; @@ -121,7 +121,7 @@ static int_fast16_t __sp_max_hint(struct sp_node *n) * @param root Root of tree. * @param n Node to start balancing operation from. */ -static void __sp_update(struct sp_node **root, struct sp_node *n) +static __inline void __sp_update(struct sp_node **root, struct sp_node *n) { while (n) { int b = __sp_balance(n); @@ -175,7 +175,7 @@ void sp_insert(struct sp_node **root, struct sp_node *p, struct sp_node *n, * @param n Node to replace. * @param r Node to replace with. */ -static void __sp_replace_right(struct sp_node *n, struct sp_node *r) +static __inline void __sp_replace_right(struct sp_node *n, struct sp_node *r) { struct sp_node *p = sp_paren(n); struct sp_node *rp = sp_paren(r); @@ -212,7 +212,7 @@ static void __sp_replace_right(struct sp_node *n, struct sp_node *r) * @param n Node to replace. * @param l Node to replace with. */ -static void __sp_replace_left(struct sp_node *n, struct sp_node *l) +static __inline void __sp_replace_left(struct sp_node *n, struct sp_node *l) { struct sp_node *p = sp_paren(n); struct sp_node *lp = sp_paren(l); diff --git a/src/uapi/dispatch.c b/src/uapi/dispatch.c index 5e29922..ad53536 100644 --- a/src/uapi/dispatch.c +++ b/src/uapi/dispatch.c @@ -93,5 +93,6 @@ void handle_syscall(sys_arg_t syscall, sys_arg_t a, sys_arg_t b, if (check_canary(t)) { bug("Syscall %zu overwrote stack canary\n", syscall); + set_canary(t); } } diff --git a/src/uapi/ipc.c b/src/uapi/ipc.c index 71dae83..4a5a6d9 100644 --- a/src/uapi/ipc.c +++ b/src/uapi/ipc.c @@ -85,7 +85,7 @@ static inline void finalize_rpc(struct tcb *t, struct tcb *r, vm_t s) * @return RPC stack difference that should be passed to finalize_rpc(). */ static inline vm_t enter_rpc(struct tcb *t, struct sys_ret a, - enum ipc_flags flags) + enum ipc_flags flags) { /* reuse current rpc stack location if we're being kicked */ vm_t rpc_stack = (is_set(flags, IPC_TAIL) && diff --git a/tests/malloc/check.mk b/tests/malloc/check.mk new file mode 100644 index 0000000..3a178cb --- /dev/null +++ b/tests/malloc/check.mk @@ -0,0 +1,4 @@ +malloc: do-malloc + @grep 'BUG' reports/malloc/log \ + && echo 'BUG' > reports/malloc/OK \ + || tail -n1 reports/malloc/log | tr -d '\r' > reports/malloc/OK diff --git a/tests/malloc/init.c b/tests/malloc/init.c new file mode 100644 index 0000000..5048e82 --- /dev/null +++ b/tests/malloc/init.c @@ -0,0 +1,42 @@ +#include + +START(pid, tid, d0, d1, d2, d3) +{ + UNUSED(pid); + UNUSED(tid); + UNUSED(d0); + UNUSED(d1); + UNUSED(d2); + UNUSED(d3); + + printf("allocating space for pointers...\n"); + /* 12 MiB / 4K */ + void **allocs = sys_req_mem(200 * sizeof(void *), VM_W | VM_R); + check(allocs, "initial allocation failed\n"); + + printf("allocating memory until we run out...\n"); + + long i = 0; + while (1) { + char *p = sys_req_mem(1, VM_W | VM_R); + if (!p) + break; + + /* check that we actually got a page */ + *p = 'a'; + allocs[i++] = p; + } + + printf("ran out of memory, freeing...\n"); + for (; i >= 0; --i) + sys_free_mem((uintptr_t)allocs[i]); + + printf("freed all memory, doing one last allocation to check we're good...\n"); + /* not super exhaustive but would hopefully go haywire if the page + * allocator got corrupted or something */ + char *p = sys_req_mem(1, VM_W | VM_R); + *p = 'b'; + sys_free_mem((uintptr_t)p); + sys_free_mem((uintptr_t)allocs); + ok(); +} diff --git a/tests/malloc/source.mk b/tests/malloc/source.mk new file mode 100644 index 0000000..9498682 --- /dev/null +++ b/tests/malloc/source.mk @@ -0,0 +1,2 @@ +DO != ./scripts/gen-prog -n malloc -p init init.c +DO != ./scripts/gen-simple -n malloc -p init diff --git a/tests/scripts/makefile b/tests/scripts/makefile index 8079c3c..530e0bb 100644 --- a/tests/scripts/makefile +++ b/tests/scripts/makefile @@ -20,6 +20,7 @@ QEMU := qemu-system-$(ARCH) -machine virt -kernel ../kmi.bin \ -monitor none \ -nographic \ -no-reboot \ + -m 128M \ -initrd KMI := ../kmi.bin -- cgit v1.3