-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmem.cpp
318 lines (254 loc) · 6.95 KB
/
mem.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
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
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
#include <bits/stdc++.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdint.h>
#include "mem.h"
//error showing
#define handle_error(msg) \
do { perror(msg); } while (0)
using namespace std;
void *ptr=NULL;
//structure for free and allocated nodes
struct node
{
void *dataptr;
int size;
};
//freelist nodes start and end ptrs
node *freelist_start = NULL;
node *freelist_end=NULL;
//allocatedlist nodes start and end ptrs
node *allocatedlist_start = NULL;
node *allocatedlist_end=NULL; // point to last header in alloc list
int freenode_count=1; //number of free nodes in freelist
int allocatednode_count=0; //number of nodes in allocatedlist
int current_space; //current space
int sizegarbage=0; //for collecting garbage
//function to request memory using mmap
int Mem_Init(int sizeOfRegion)
{
if(sizeOfRegion<=0)
{
handle_error("Invalid size...!");
return -1;
}
sizegarbage=sizeOfRegion;
int fd = open("/dev/zero", O_RDWR); // size (in bytes) needs to be evenly divisible by the page size
ptr = mmap(NULL, 7*sizeOfRegion, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); // getting memory from OS
if (ptr == MAP_FAILED)
{
handle_error("MMAP Error...!");
return -1;
}
current_space=sizeOfRegion;
freelist_start=(node*)(ptr + 7*sizeOfRegion - sizeof(node));
allocatedlist_start=(node*)(ptr + sizeOfRegion);
allocatedlist_start->size=0;
freelist_start->dataptr=ptr;
freelist_start->size=sizeOfRegion;
freelist_end=freelist_start;
allocatedlist_end=allocatedlist_start;
close(fd);
return 1;
}
int Mem_GetSize(void *ptr1)
{
node *currentnode=allocatedlist_start;
unsigned long long int low,high;
//traverse the allocated list to find the particular allocated node
for(int i=0;i<allocatednode_count;i++)
{
low=(uintptr_t)currentnode->dataptr;
high=low + currentnode->size;
if((uintptr_t)low<=(uintptr_t)ptr1 && (uintptr_t)ptr1 < (uintptr_t)high)
{
return currentnode->size;
}
currentnode++;
}
return -1;
}
//traverse the allocated list to find the particular allocated node
int Mem_IsValid(void *user_ptr)
{
node *currentnode=allocatedlist_start;
unsigned long long int low,high;
for(int i=0;i<allocatednode_count;i++)
{
low=(uintptr_t)currentnode->dataptr;
high=low + currentnode->size;
if((uintptr_t)low<=(uintptr_t)user_ptr && (uintptr_t)user_ptr<(uintptr_t)high)
return 1;
currentnode++;
}
return 0;
}
void *Mem_Alloc(int size)
{
// if free space is less than required
if(size>current_space)
{
handle_error("Not enough space available...!\n");
return NULL;
}
//find first large enough node to satisfy user request
node *firstlarge_node=freelist_start;
node *currentnode=firstlarge_node;
// pointer to be returned to user
void *result_ptr=firstlarge_node->dataptr;
int largenode_size=firstlarge_node->size;
// first fit to search free node
for(int i=1;i<=freenode_count;i++)
{
if(size < currentnode->size && firstlarge_node->dataptr > currentnode->dataptr)
firstlarge_node=currentnode;
currentnode--;
}
result_ptr=firstlarge_node->dataptr;
node *newallocated_node;
// if space is partially allocated from a free node
if(size<firstlarge_node->size)
{
firstlarge_node->size-=size;
firstlarge_node->dataptr+=size;
if(allocatedlist_start->size != 0)
newallocated_node=allocatedlist_end +1;
else
newallocated_node=allocatedlist_start;
newallocated_node->size=size;
newallocated_node->dataptr=result_ptr;
// increase num of allocated nodes
allocatednode_count++;
allocatedlist_end=newallocated_node;
// update current space
current_space-=size;
}
// if space is completely allocated of a free node
else if(size==firstlarge_node->size)
{
if(allocatedlist_start->size != 0)
newallocated_node=allocatedlist_end + 1;
else
newallocated_node=allocatedlist_start;
newallocated_node->size=size;
newallocated_node->dataptr=result_ptr;
allocatednode_count++;
allocatedlist_end=newallocated_node;
current_space-=size;
if(firstlarge_node!=freelist_end)
{
firstlarge_node->dataptr=freelist_end->dataptr;
firstlarge_node->size=freelist_end->size;
}
// increase num of free nodes
freelist_end++;
if(freenode_count>1)
freenode_count--;
else if(freenode_count==1)
{
freelist_start->dataptr=NULL;
freelist_start->size=0;
}
}
// if biggest node is less than size required
else
{
handle_error("Not enough space available...!\n");
return NULL;
}
return result_ptr;
}
int Mem_Free(void *ptr1)
{
if(ptr1==NULL)
return -1;
//checking whether ptr provided by user is within the valid range
if(!Mem_IsValid(ptr1))
{
handle_error("Invalid Pointer...!\n");
return -1;
}
node *currentnode=allocatedlist_start;
unsigned long long int low,high;
//traversing the allocated list to find the particular allocated node
for(int i=0;i<allocatednode_count;i++)
{
low=(uintptr_t)currentnode->dataptr;
high=low + currentnode->size;
if((uintptr_t)low<=(uintptr_t)ptr1 && (uintptr_t)ptr1<(uintptr_t)high)
break;
currentnode++;
}
int actual_size=currentnode->size;
currentnode->size=(uintptr_t)ptr1 - (uintptr_t)low;
node *newfree_node;
//partially freeing a node
if(currentnode->size!=1)
{
newfree_node=freelist_end;
newfree_node--;
newfree_node->size = actual_size - currentnode->size;
}
//fully freeing a node
else
{
newfree_node=freelist_end - 1;
newfree_node->size = actual_size;
currentnode->size=allocatedlist_end->size;
currentnode->dataptr=allocatedlist_end->dataptr;
allocatedlist_end--;
allocatednode_count--;
}
newfree_node->dataptr=ptr1;
freenode_count++;
freelist_end=newfree_node;
current_space+=newfree_node->size;
//merging the adjacent free nodes
node *ptr=(node*)newfree_node;
int low22=(uintptr_t)ptr->dataptr;
int high22=low22 + ptr->size;
currentnode=freelist_start;
int low1;
for (int i = 0; i < freenode_count; ++i)
{
low1=(uintptr_t)currentnode->dataptr;
if(high22==low1)
{
ptr->size+=currentnode->size;
currentnode->size=freelist_end->size;
currentnode->dataptr=freelist_end->dataptr;
freelist_end++;
freenode_count--;
break;
}
currentnode--;
}
ptr=(node*)newfree_node;
low22=(uintptr_t)ptr->dataptr;
high22=low22 + ptr->size;
currentnode=freelist_start;
int high1;
for (int i = 0; i < freenode_count; ++i)
{
high1=(uintptr_t)currentnode->dataptr + currentnode->size;
if(high1 == low22)
{
currentnode->size+=ptr->size;
freelist_end++;
freenode_count--;
break;
}
currentnode--;
}
return 1;
}
void garbage_collector()
{
sbrk(-sizegarbage);
cout<<"Memory allocated is cleared...!"<<endl;
}