basic process support and some syscalls
[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
24
25 int _syscall_sbrk(void* addr) {
26     heap_context_t* uheap = &__current->mm.u_heap;
27     mutex_lock(&uheap->lock);
28     int r = lxsbrk(uheap, addr);
29     mutex_unlock(&uheap->lock);
30     return r;
31 }
32
33 void* _syscall_brk(size_t size) {
34     heap_context_t* uheap = &__current->mm.u_heap;
35     mutex_lock(&uheap->lock);
36     void* r = lxbrk(uheap, size);
37     mutex_unlock(&uheap->lock);
38     return r;
39 }
40
41 int
42 dmm_init(heap_context_t* heap)
43 {
44     assert((uintptr_t)heap->start % BOUNDARY == 0);
45
46     heap->brk = heap->start;
47     mutex_init(&heap->lock);
48
49     return vmm_alloc_page(__current->pid, heap->brk, NULL, PG_PREM_RW, 0) != NULL;
50 }
51
52 int
53 lxsbrk(heap_context_t* heap, void* addr)
54 {
55     return lxbrk(heap, addr - heap->brk) != NULL;
56 }
57
58 void*
59 lxbrk(heap_context_t* heap, size_t size)
60 {
61     if (size == 0) {
62         return heap->brk;
63     }
64
65     void* current_brk = heap->brk;
66
67     // The upper bound of our next brk of heap given the size.
68     // This will be used to calculate the page we need to allocate.
69     void* next = current_brk + ROUNDUP(size, BOUNDARY);
70
71     // any invalid situations
72     if (next >= heap->max_addr || next < current_brk) {
73         __current->k_status = LXINVLDPTR;
74     }
75
76     uintptr_t diff = PG_ALIGN(next) - PG_ALIGN(current_brk);
77     if (diff) {
78         // if next do require new pages to be allocated
79         if (!vmm_alloc_pages(__current->pid, (void*)(PG_ALIGN(current_brk) + PG_SIZE),
80                              diff,
81                              PG_PREM_RW, 0)) {
82             __current->k_status = LXHEAPFULL;
83             return NULL;
84         }
85     }
86
87     heap->brk += size;
88     return current_brk;
89 }