-
Notifications
You must be signed in to change notification settings - Fork 0
/
MemoryManager.cpp
160 lines (136 loc) · 3.66 KB
/
MemoryManager.cpp
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#include "MemoryManager.h"
void *base = 0x0;
//get block from given address
t_block get_block(void *p){
// t_block b;
// int offset = (int) (((char*)b->data) - ((char*) b));
return (t_block) (((char*) p) - OFFSET);
}
//valid address is allocated by malloc for free
bool valid_addr(void *p){
if(base){
if(p > base && p < sbrk(0)){
return (p == (get_block(p))->ptr);
}
}
return false;
}
//find block with needed size
t_block find_block(t_block *last, size_t size){
t_block block = (t_block) base;
while(block && !(block->block_free && block->size >= size)){
*last = block;
block = block->next;
}
return(block);
}
//extends the allocated memory for the program
t_block extend_heap(t_block last, size_t size){
int debug_block;
t_block block;
block = (t_block) sbrk(0);
debug_block = *((int*) sbrk(OFFSET + size));
//if(sbrk(OFFSET + size) == (void*)-1){
if(debug_block < 0){
return 0x0;
}
block->size = size;
block->next = 0x0;
block->prev = last;
block->ptr = block->data;
if(last){
last->next = block;
}
block->block_free = 0;
return block;
}
//splits block
void split_block(t_block block, size_t size){
t_block newBlock;
newBlock = (t_block) (block->data + size);
newBlock->size = block->size - size - OFFSET;
newBlock->next = block->next;
newBlock->prev = block;
newBlock->block_free = 1;
newBlock->ptr = newBlock->data;
block->size = size;
block->next = newBlock;
//if the block has allocated block next to him, restore the connection after splitting.
if(newBlock->next){
newBlock->next->prev = newBlock;
}
}
//allocate memory
void *malloc(size_t size){
t_block newBlock, last;
size_t newSize = align8(size);
if(base){
last = (t_block) base;
newBlock = find_block(&last, newSize);
if(newBlock){
//can we split
if((newBlock->size - newSize) >= (OFFSET + PTR_SIZE)){
split_block(newBlock, newSize);
}
newBlock->block_free = false;
} else {
//Can't find block, try extending the heap
newBlock = extend_heap(last, newSize);
if(!newBlock){
//cannot extend heap
return 0x0;
}
}
} else {
//first call
newBlock = extend_heap(0x0, newSize);
if(!newBlock){
//failed to extend
return 0x0;
}
base = newBlock;
}
return newBlock->data;
}
//merge 2 blocks into 1
t_block merge(t_block block){
if(block->next && block->next->block_free){
block->size += OFFSET + block->next->size;
block->next = block->next->next;
if(block->next){
block->next->prev = block;
}
return block;
}
}
//frees dynamic allocated memory
void free(void *p){
t_block block;
if(valid_addr(p)){
block = get_block(p);
block->block_free = 1;
//merge with previous if possible
if(block->prev && block->prev->block_free){
block = merge(block->prev);
}
//merge with next if possible
if(block->next){
if(block->next->block_free){
merge(block);
}
} else {
//free the end of the heap
if(block->prev){
//block->prev->next = 0x0;
} else {
// brk(block);
// base = 0x0;
}
}
//no more blocks
if(!block->next && !block->prev){
brk(block);
base = 0x0;
}
}
}