24
|
1 #include "kernel.h"
|
|
2
|
28
|
3 // ================= Placement malloc:
|
29
|
4 // Assume here that nothing gets ever kfree'd. This makes it simple!
|
|
5
|
|
6 uint64_t placement_address = (uint64_t)&kernel_end;
|
28
|
7
|
|
8 // ================= Other malloc
|
|
9 // TODO: move this to user space?
|
|
10
|
24
|
11 #define HEAP_MAGIC 0xc0ffee
|
|
12 #define HEAP_INUSE 1
|
|
13 #define HEAP_FREE 0
|
|
14
|
|
15 /*
|
|
16 malloc and free divide the chunks of memory present at the heap
|
|
17 of the kernel into smaller parts.
|
|
18 The heap is located at: 0x
|
|
19 */
|
28
|
20
|
40
|
21 static heap_t* kernel_heap = 0;
|
|
22
|
|
23 void expand_heap(heap_t *heap, uint64_t newsize);
|
|
24
|
24
|
25 /* Allocates 'size' bytes and returns the pointer if succesfull.
|
40
|
26 Before the kernel is initialized, placement malloc is used.
|
24
|
27 Kernelpanic in case of failure..
|
|
28 */
|
40
|
29 static void* kmalloc_int(uint64_t size, uint64_t aligned)
|
26
|
30 {
|
40
|
31 // Check if there exists a kernel heap. If not, use placement malloc for now.
|
|
32 if (kernel_heap == 0)
|
24
|
33 {
|
40
|
34 // Before that the heap is initialized, use placement malloc
|
|
35 if (aligned == 1)
|
24
|
36 {
|
40
|
37 // Align placement address
|
|
38 if ( (placement_address | 0xFFF) != 0 )
|
|
39 {
|
|
40 placement_address &= ~(0xFFF);
|
|
41 placement_address += 0x1000;
|
|
42 }
|
|
43 }
|
|
44 uint64_t tmp = placement_address;
|
|
45 placement_address += size;
|
|
46 return (void*)tmp;
|
|
47 }
|
|
48 else
|
|
49 {
|
|
50 // We have a kernel heap, search the heap for a block of suitable size.
|
24
|
51
|
40
|
52 // Start at the beginning of our heap and search a free block:
|
|
53 heap_header_t *current = kernel_heap->first_block;
|
|
54 while (current->magic == HEAP_MAGIC)
|
|
55 {
|
|
56 if ((current->state == HEAP_FREE) && (current->size >= size))
|
24
|
57 {
|
40
|
58 // We found a hole with suitable size. Determine if split is of any use.
|
|
59
|
|
60 // Insert a heap header if required:
|
|
61 if (current->size > size + sizeof(heap_t) + 1)
|
|
62 {
|
|
63 // Calculate location of the inserted header:
|
|
64 heap_header_t *newheader = (heap_header_t*) (((uint64_t)current)+size+sizeof(heap_header_t));
|
24
|
65
|
40
|
66 // Set the new header fields:
|
|
67 newheader->size = current->size - size - sizeof(heap_header_t);
|
|
68 newheader->state = HEAP_FREE;
|
|
69 newheader->magic = HEAP_MAGIC;
|
24
|
70
|
40
|
71 // Set the size of this block
|
|
72 current->size = size;
|
|
73 }
|
|
74 else
|
|
75 {
|
|
76 // We allocate this whole block
|
|
77 // Mark block as used:
|
|
78 current->state = HEAP_INUSE;
|
|
79 }
|
|
80 // Calculate the size of the block:
|
|
81 char *address = ((char*)current)+sizeof(heap_header_t);
|
|
82 return address;
|
|
83
|
24
|
84 }
|
40
|
85 // Goto next heap block:
|
|
86 current = (heap_header_t*)(((uint64_t) current) + current->size + sizeof(heap_header_t));
|
24
|
87 }
|
40
|
88
|
|
89 // We did not find a block large enough. Expand the heap and try again.
|
|
90 expand_heap(kernel_heap, 0x10000000);
|
|
91 return kmalloc_int(size, aligned);
|
24
|
92 }
|
40
|
93 }
|
|
94
|
|
95 // Convenient wrappers:
|
|
96 void* kmalloc(uint64_t size)
|
|
97 {
|
|
98 return kmalloc_int(size, 0);
|
|
99 }
|
|
100
|
|
101 void* kmalloc_a(uint64_t size)
|
|
102 {
|
|
103 return kmalloc_int(size, 1);
|
24
|
104 }
|
|
105
|
26
|
106 void kfree(void* ptr)
|
|
107 {
|
40
|
108 printf("Free address %x\n", ptr);
|
|
109 if (kernel_heap == 0)
|
|
110 {
|
|
111 return;
|
|
112 }
|
|
113 else
|
|
114 {
|
|
115 // TODO
|
|
116 }
|
|
117 // TODO: free blocks:
|
24
|
118 }
|
|
119
|
40
|
120 heap_t* create_heap(uint64_t location, uint64_t size)
|
24
|
121 {
|
40
|
122 // Make sure that the new heap location is mapped into the address space:
|
|
123 uint64_t i = 0;
|
|
124 while (i < size)
|
|
125 {
|
|
126 alloc_frame( get_page(location + i, kernel_map));
|
|
127 i += 0x1000;
|
|
128 }
|
|
129
|
|
130 // create new heap structure:
|
|
131 heap_t* h = (heap_t*)kmalloc(sizeof(heap_t));
|
|
132
|
|
133 // Create one big hole:
|
|
134 h->first_block = (heap_header_t*)location; // Place header at beginning of heap
|
|
135 h->first_block->magic = HEAP_MAGIC;
|
|
136 h->first_block->state = HEAP_FREE;
|
|
137 h->first_block->size = size - sizeof(heap_header_t);
|
|
138 return h;
|
24
|
139 }
|
25
|
140
|
40
|
141 // Make the total heap bigger:
|
|
142 void expand_heap(heap_t *heap, uint64_t newsize)
|
|
143 {
|
|
144 uint64_t oldsize = heap->end_address - heap->start_address;
|
|
145 if (newsize < oldsize)
|
|
146 {
|
|
147 panic("Cannot expand heap to a smaller size\n");
|
|
148 }
|
|
149
|
|
150 uint64_t i = oldsize;
|
|
151 while (i < newsize)
|
|
152 {
|
|
153 alloc_frame( get_page(heap->start_address + i, kernel_map));
|
|
154 i += 0x1000;
|
|
155 }
|
|
156 }
|
|
157
|