4 * @brief Dynamic memory manager for heap. This design do not incorporate any\
5 * specific implementation of malloc family. The main purpose of this routines is to
6 * provide handy method to initialize & grow the heap as needed by upstream implementation.
8 * This is designed to be portable, so it can serve as syscalls to malloc/free in the c std lib.
13 * @copyright Copyright (c) Lunaixsky 2022
17 #include <lunaix/mm/dmm.h>
18 #include <lunaix/mm/vmm.h>
19 #include <lunaix/mm/page.h>
20 #include <lunaix/status.h>
22 #include <lunaix/spike.h>
23 #include <lunaix/syscall.h>
26 __DEFINE_LXSYSCALL1(int, sbrk, void*, addr) {
27 heap_context_t* uheap = &__current->mm.u_heap;
28 mutex_lock(&uheap->lock);
29 int r = lxsbrk(uheap, addr);
30 mutex_unlock(&uheap->lock);
34 __DEFINE_LXSYSCALL1(void*, brk, size_t, size) {
35 heap_context_t* uheap = &__current->mm.u_heap;
36 mutex_lock(&uheap->lock);
37 void* r = lxbrk(uheap, size);
38 mutex_unlock(&uheap->lock);
43 dmm_init(heap_context_t* heap)
45 assert((uintptr_t)heap->start % BOUNDARY == 0);
47 heap->brk = heap->start;
48 mutex_init(&heap->lock);
50 return vmm_alloc_page(__current->pid, heap->brk, NULL, PG_PREM_RW, 0) != NULL;
54 lxsbrk(heap_context_t* heap, void* addr)
56 return lxbrk(heap, addr - heap->brk) != NULL;
60 lxbrk(heap_context_t* heap, size_t size)
66 void* current_brk = heap->brk;
68 // The upper bound of our next brk of heap given the size.
69 // This will be used to calculate the page we need to allocate.
70 void* next = current_brk + ROUNDUP(size, BOUNDARY);
72 // any invalid situations
73 if (next >= heap->max_addr || next < current_brk) {
74 __current->k_status = LXINVLDPTR;
77 uintptr_t diff = PG_ALIGN(next) - PG_ALIGN(current_brk);
79 // if next do require new pages to be allocated
80 if (!vmm_alloc_pages(__current->pid, (void*)(PG_ALIGN(current_brk) + PG_SIZE),
83 __current->k_status = LXHEAPFULL;