blob: 6468a8ad550a88b488a92d592932b28fc0a67a9a (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
#include <cstdint>
#include <generic/pmm.hpp>
#include <generic/heap.hpp>
#include <generic/lock/spinlock.hpp>
#include <generic/hhdm.hpp>
#include <klibc/stdio.hpp>
std::uint8_t* heap_pool;
heap_block* heap_end;
heap_block* current;
locks::spinlock heap_lock;
void kheap::init() {
heap_pool = (std::uint8_t*)(pmm::buddy::alloc(KHEAP_SIZE).phys + etc::hhdm());
heap_block* block = (heap_block*)heap_pool;
block->size = KHEAP_SIZE;
block->is_free = 1;
block->next = 0;
current = (heap_block*)heap_pool;
heap_end = block;
klibc::printf("KHeap: Available memory %lli bytes\r\n",KHEAP_SIZE);
}
int is_early = 0;
void kheap::opt_free(void* ptr) {
if(!is_early) {
kheap::free(ptr);
return;
}
if(!ptr) return;
heap_block* block = (heap_block*)((std::uint64_t)ptr - sizeof(heap_block));
block->is_free = 1;
if (block->next && block->next->is_free) {
block->size += block->next->size;
block->next = block->next->next;
}
}
void* kheap::opt_malloc(std::size_t size) {
if(!is_early) {
return kheap::malloc(size);
}
size = (size + sizeof(heap_block) + 7) & ~7;
if (1) {
heap_block* block = heap_end;
block->size = size;
block->is_free = 0;
block->next = nullptr;
heap_end = (heap_block*)((std::uint64_t)heap_end + size);
return (void*)((std::uint64_t)block + sizeof(heap_block));
}
return 0;
}
void kheap::free(void* ptr) {
if(ptr == 0)
return;
heap_lock.lock();
heap_block* block = (heap_block*)((std::uint64_t)ptr - sizeof(heap_block));
block->is_free = 1;
if (block->next && block->next->is_free) {
block->size += block->next->size;
block->next = block->next->next;
}
heap_lock.unlock();
}
void* kheap::malloc(std::size_t size) {
heap_lock.lock();
size = (size + sizeof(heap_block) + 7) & ~7;
if ((std::uint64_t)heap_end + size <= (std::uint64_t)heap_pool + KHEAP_SIZE) {
heap_block* block = heap_end;
block->size = size;
block->is_free = 0;
block->next = nullptr;
heap_end = (heap_block*)((std::uint64_t)heap_end + size);
heap_lock.unlock();
return (void*)((std::uint64_t)block + sizeof(heap_block));
}
heap_block* start = current;
do {
if (current->is_free && current->size >= size) {
if (current->size > size + sizeof(heap_block)) {
heap_block* new_block = (heap_block*)((char*)current + size);
new_block->size = current->size - size;
new_block->is_free = 1;
new_block->next = current->next;
current->size = size;
current->next = new_block;
}
current->is_free = 0;
void* allocated = (void*)((char*)current + sizeof(heap_block));
current = current->next ? current->next : (heap_block*)heap_pool;
heap_lock.unlock();
return allocated;
}
current = current->next ? current->next : (heap_block*)heap_pool;
} while (current != start);
heap_lock.unlock();
return 0;
}
|