blob: d08e54326bd1e9cf07969aa26d195ce21c8395be [file] [log] [blame]
swissChilie4f01992021-02-25 15:38:12 -08001#include "alloc.h"
2#include "kheap.h"
3#include "kint.h"
4#include "log.h"
5#include "paging.h"
6#include "io.h"
7
8extern uint end;
9static size_t palloc_base = (size_t)&end;
10static size_t malloc_base = (size_t)&end + 0x2000;
11
12#define HEADER_SIZE sizeof(struct heap_alloc_header)
13#define FOOTER_SIZE sizeof(struct heap_alloc_footer)
14
15static struct min_heap heap = {0};
16
17void *_kmalloc(size_t size, bool align, void **phys)
18{
19 if (align && (palloc_base & 0xfff)) // if not yet aligned
20 {
21 palloc_base &= ~0xfff;
22 palloc_base += 0x1000;
23 }
24
25 if (phys)
26 {
27 *phys = (void *)palloc_base;
28 }
29
30 size_t addr = palloc_base;
31 palloc_base += size;
32 return (void *)addr;
33}
34
35void *kmalloc(size_t size)
36{
37 return _kmalloc(size, false, NULL);
38}
39
40void *kmalloc_a(size_t size)
41{
42 return _kmalloc(size, true, NULL);
43}
44
45void *kmalloc_ap(size_t size, void **p)
46{
47 return _kmalloc(size, true, p);
48}
49
50// Proper allocators
51
52void init_allocator()
53{
swissChilie4f01992021-02-25 15:38:12 -080054 heap.size = 1;
swissChilif238c222021-02-25 15:47:50 -080055 int size = 0xC0400000 - malloc_base;
swissChilie4f01992021-02-25 15:38:12 -080056 heap.elements[0] = (struct heap_entry){
swissChilif238c222021-02-25 15:47:50 -080057 .key = size,
swissChilie4f01992021-02-25 15:38:12 -080058 .address = malloc_base,
59 };
swissChilif238c222021-02-25 15:47:50 -080060 memset((void *)malloc_base, 0, size);
61
62 struct heap_alloc_header *h = (struct heap_alloc_header *)malloc_base;
63 h->magic = HEAP_MAGIC;
64 h->size = size;
65 h->allocated = false;
swissChilie4f01992021-02-25 15:38:12 -080066}
67
68void *malloc(size_t size)
69{
70 bool ok;
71 size_t full_size = size + HEADER_SIZE + FOOTER_SIZE;
72 int i;
73
74 struct heap_entry e = heap_lookup_min(&heap, full_size, &ok, false, &i);
75
76 if (ok)
77 {
78 // Found smallest hole
79 struct heap_alloc_header *h = (struct heap_alloc_header *)e.address;
80
81 kassert(!h->allocated,
82 "Gap already allocated (this should never happen)");
83
84 size_t old_size = h->size;
85
86 if (full_size == old_size)
87 {
88 // Completely used, no need to change anything!
89 heap_delete(&heap, i);
90 }
91 else
92 {
93 // If there isn't very much space left
94 size_t new_size = old_size - full_size;
95 if (new_size <= HEADER_SIZE + FOOTER_SIZE + 8)
96 {
97 full_size = old_size;
98 heap_delete(&heap, i);
99 }
100 else
101 {
102 struct heap_alloc_footer *old_f =
103 (struct heap_alloc_footer *)(e.address + old_size -
104 FOOTER_SIZE);
105
106 // Else create a new header
107 size_t new_header_addr = e.address + full_size;
108 struct heap_alloc_header *h =
109 (struct heap_alloc_header *)new_header_addr;
110
swissChilie4f01992021-02-25 15:38:12 -0800111 h->size = new_size;
112 old_f->size = new_size;
113
114 heap_decrease(&heap, i,
115 (struct heap_entry){
116 .key = new_size,
117 .address = new_header_addr,
118 });
119 }
120
121 struct heap_alloc_footer *f =
122 (struct heap_alloc_footer *)(e.address + full_size -
123 FOOTER_SIZE);
124
swissChilif238c222021-02-25 15:47:50 -0800125 h->allocated = true;
126 h->magic = HEAP_MAGIC;
swissChilie4f01992021-02-25 15:38:12 -0800127 h->size = full_size;
128 f->size = h->size;
129 }
130
131 return (void *)(e.address + HEADER_SIZE);
132 }
133 else
134 {
135 // We need more memory :L
136 kpanic("Whoops, malloc ran out of memory");
137 }
138}
139
140void free(void *mem)
141{
142 // TODO: expand memory
143
144 if (!mem)
145 return; // freeing NULL ptr
146
147 struct heap_alloc_header *base =
148 (struct heap_alloc_header *)((size_t)mem - HEADER_SIZE);
149
150 if (base->magic != HEAP_MAGIC)
151 {
152 kpanic("Freeing memory not allocated with malloc()");
153 }
154
155 base->allocated = false;
156 // Add entry into heap
157
158 struct heap_entry entry =
159 {
160 .key = base->size,
161 .address = (size_t)base,
162 };
163
164 heap_insert(&heap, entry);
165}