feat: added ability to identify process vm regions
[lunaix-os.git] / lunaix-os / kernel / mm / dmm.c
1 /**
2  * @file dmm.c
3  * @author Lunaixsky
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.
7  * 
8  * This is designed to be portable, so it can serve as syscalls to malloc/free in the c std lib. 
9  * 
10  * @version 0.2
11  * @date 2022-03-3
12  *
13  * @copyright Copyright (c) Lunaixsky 2022
14  *
15  */
16
17 #include <lunaix/mm/dmm.h>
18 #include <lunaix/mm/vmm.h>
19 #include <lunaix/mm/page.h>
20 #include <lunaix/status.h>
21
22 #include <lunaix/spike.h>
23 #include <lunaix/syscall.h>
24
25
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);
31     return r;
32 }
33
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);
39     return r;
40 }
41
42 int
43 dmm_init(heap_context_t* heap)
44 {
45     assert((uintptr_t)heap->start % BOUNDARY == 0);
46
47     heap->brk = heap->start;
48     mutex_init(&heap->lock);
49
50     return vmm_alloc_page(__current->pid, heap->brk, NULL, PG_PREM_RW, 0) != NULL;
51 }
52
53 int
54 lxsbrk(heap_context_t* heap, void* addr)
55 {
56     return lxbrk(heap, addr - heap->brk) != NULL;
57 }
58
59 void*
60 lxbrk(heap_context_t* heap, size_t size)
61 {
62     if (size == 0) {
63         return heap->brk;
64     }
65
66     void* current_brk = heap->brk;
67
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);
71
72     // any invalid situations
73     if (next >= heap->max_addr || next < current_brk) {
74         __current->k_status = LXINVLDPTR;
75     }
76
77     uintptr_t diff = PG_ALIGN(next) - PG_ALIGN(current_brk);
78     if (diff) {
79         // if next do require new pages to be allocated
80         if (!vmm_alloc_pages(__current->pid, (void*)(PG_ALIGN(current_brk) + PG_SIZE),
81                              diff,
82                              PG_PREM_RW, 0)) {
83             __current->k_status = LXHEAPFULL;
84             return NULL;
85         }
86     }
87
88     heap->brk += size;
89     return current_brk;
90 }