-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathFuncs.c
199 lines (169 loc) · 4.92 KB
/
Funcs.c
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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
#include "Heap.h"
#include <ctime>
#define FREE 0
#define BUSY 1
#define HEAP_TRUE 1
#define HEAP_FALSE 0
//block states
typedef enum{
eBlockState__OK = 0,
eBlockState__Busy,
eBlockState__NoSize,
}BlockState;
//Service data
struct Heap
{
char status;
uint block_size;
};
//internal functions
/*initzialize service part*/
static void* serv_init(void* block, int size, char status);
/*check for unallocated block*/
static Heap* normalize_block_allocation(Heap* mem_block);
/*check for state of the block*/
static BlockState check_block(void* block, int size);
/*return next memory block*/
static void *get_next_block(Heap* mem_block);
/*internal alloc implementation*/
//static void* my_alloc_internal(uint size, Heap* block_start, char bExitOnBusy);
/*unite 2 memory blocks*/
static void *unite_blocks(Heap* mem_block1, Heap* mem_block2);
/*offsets block to service part*/
static Heap* normalizeRawBlock(void* mem_block);
static uint defaul_heap_mem;
static int heapSize;
static void* heapmem;
static void * heap_start;
static void* serv_init(void* block, int size, char status){
Heap * Serv_part = (Heap*)block;
Serv_part->block_size = size == 0 ? Serv_part->block_size : size;
Serv_part->status = status;
return (char*)block + sizeof(Heap);
}
void heap_alloc(uint size){
defaul_heap_mem = size + sizeof(Heap);
heapmem = heap_start= calloc(defaul_heap_mem, sizeof(char));
serv_init(heapmem, size, FREE);
}
static Heap* normalize_block_allocation(Heap* mem_block)
{
if (mem_block->block_size == 0){
uint size_new = defaul_heap_mem - ((char*)mem_block - (char*)heap_start) - sizeof(Heap);
mem_block->block_size = size_new;
}
return mem_block;
}
static BlockState check_block(void* block, uint size)
{
Heap* mem_block = (Heap*)block;
mem_block = normalize_block_allocation(mem_block);
if (FREE == mem_block->status){
if (mem_block->block_size >= size){
return eBlockState__OK;
}
return eBlockState__NoSize;
}
return eBlockState__Busy;
}
static void *get_next_block(Heap* mem_block){
char* out = (char*)mem_block;
out += sizeof(Heap) + mem_block->block_size;
if (defaul_heap_mem - (out - (char*)heap_start) <= sizeof(Heap)){
return NULL;
}
return out;
}
static void *unite_blocks(Heap* mem_block1, Heap* mem_block2){
mem_block1->block_size += mem_block2->block_size + sizeof(Heap);
return mem_block1;
}
static void* my_alloc_internal(uint size, Heap* block_start, char bExitOnBusy = HEAP_FALSE)
{
Heap* mem_block = (Heap*)block_start;
Heap* mem_end = (Heap*)((char*)heap_start + defaul_heap_mem);
//check for size overflowing defaul_heap_mem and free size
while (mem_block < mem_end){
char block_status = check_block(mem_block, size);
switch (block_status){
case eBlockState__OK:
//have memory return it, doesn’t handle situation when block is too big
return serv_init(mem_block , size, BUSY);
break;
case eBlockState__Busy:
//go to next block
if (bExitOnBusy) {
return NULL;
}
mem_block = (Heap*)get_next_block(mem_block);
if (mem_block == NULL){
return NULL;
}
break;
case eBlockState__NoSize:
{
uint sizeleft = size - mem_block->block_size;
Heap* next_blck = (Heap*)get_next_block(mem_block);
if (next_blck == NULL){
return NULL;
}
Heap* next = (Heap*)my_alloc_internal(sizeleft, next_blck, HEAP_TRUE);
if (next != NULL){
mem_block = (Heap*)unite_blocks(mem_block, next);
return serv_init(mem_block, 0, BUSY);
}
//no next, so we can’t alloc requested size
mem_block = (Heap*)get_next_block(mem_block);
if (mem_block == NULL){
return NULL;
}
break;
}
};
}
return NULL;
}
void* my_alloc(uint size)
{
//heap_start but prоper is first free block
return my_alloc_internal(size, (Heap*)heap_start);
}
static Heap* normalizeRawBlock(void* mem_block)
{
Heap* normalized_block = ((Heap*)((char*)mem_block - sizeof(Heap)));
if (normalized_block < heap_start){
//something went wrong do nothing here
return NULL;
}
return normalized_block;
}
void my_free(void* mem_block)
{
Heap* normalized_block = normalizeRawBlock(mem_block);
if (normalized_block) {
normalized_block->status = FREE;
}
}
void print_heap(){
Heap* mem_block = (Heap*)heap_start;
Heap* mem_end = (Heap*)heap_start + defaul_heap_mem;
//check for size overflowing defaul_heap_mem and free size
while (mem_block < mem_end){
mem_block = normalize_block_allocation(mem_block);
puts(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
printf("Block Address :: %p\n", mem_block);
printf("Block Status :: %u\n", (int)mem_block->status);
printf("Block Size :: %u\n", mem_block->block_size);
puts("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
mem_block = (Heap*)get_next_block(mem_block);
if (mem_block == NULL){
break;
}
}
}
void main(){
heap_alloc(100);
char* p1 = (char*)my_alloc(10);
char* p2 = (char*)my_alloc(10);
print_heap();
}