blob: fee5edb67684434a75e0c770c57b12f11a793610 [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{
54 struct heap_alloc_header *h = (struct heap_alloc_header *)malloc_base;
55 h->allocated = false;
56 h->magic = HEAP_MAGIC;
57 h->size = 0xC0400000 - malloc_base;
58
59 heap.size = 1;
60 heap.elements[0] = (struct heap_entry){
61 .key = 0xC0200000 - malloc_base,
62 .address = malloc_base,
63 };
64 memset((void *)malloc_base, 0, heap.elements[0].key);
65}
66
67void *malloc(size_t size)
68{
69 bool ok;
70 size_t full_size = size + HEADER_SIZE + FOOTER_SIZE;
71 int i;
72
73 struct heap_entry e = heap_lookup_min(&heap, full_size, &ok, false, &i);
74
75 if (ok)
76 {
77 // Found smallest hole
78 struct heap_alloc_header *h = (struct heap_alloc_header *)e.address;
79
80 kassert(!h->allocated,
81 "Gap already allocated (this should never happen)");
82
83 size_t old_size = h->size;
84
85 if (full_size == old_size)
86 {
87 // Completely used, no need to change anything!
88 heap_delete(&heap, i);
89 }
90 else
91 {
92 // If there isn't very much space left
93 size_t new_size = old_size - full_size;
94 if (new_size <= HEADER_SIZE + FOOTER_SIZE + 8)
95 {
96 full_size = old_size;
97 heap_delete(&heap, i);
98 }
99 else
100 {
101 struct heap_alloc_footer *old_f =
102 (struct heap_alloc_footer *)(e.address + old_size -
103 FOOTER_SIZE);
104
105 // Else create a new header
106 size_t new_header_addr = e.address + full_size;
107 struct heap_alloc_header *h =
108 (struct heap_alloc_header *)new_header_addr;
109
110 h->allocated = true;
111 h->magic = HEAP_MAGIC;
112 h->size = new_size;
113 old_f->size = new_size;
114
115 heap_decrease(&heap, i,
116 (struct heap_entry){
117 .key = new_size,
118 .address = new_header_addr,
119 });
120 }
121
122 struct heap_alloc_footer *f =
123 (struct heap_alloc_footer *)(e.address + full_size -
124 FOOTER_SIZE);
125
126 h->size = full_size;
127 f->size = h->size;
128 }
129
130 return (void *)(e.address + HEADER_SIZE);
131 }
132 else
133 {
134 // We need more memory :L
135 kpanic("Whoops, malloc ran out of memory");
136 }
137}
138
139void free(void *mem)
140{
141 // TODO: expand memory
142
143 if (!mem)
144 return; // freeing NULL ptr
145
146 struct heap_alloc_header *base =
147 (struct heap_alloc_header *)((size_t)mem - HEADER_SIZE);
148
149 if (base->magic != HEAP_MAGIC)
150 {
151 kpanic("Freeing memory not allocated with malloc()");
152 }
153
154 base->allocated = false;
155 // Add entry into heap
156
157 struct heap_entry entry =
158 {
159 .key = base->size,
160 .address = (size_t)base,
161 };
162
163 heap_insert(&heap, entry);
164}