-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathallocator.cpp
150 lines (95 loc) · 3.88 KB
/
allocator.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
#include <cstdio> /* for fprintf */
#include "allocator.h"
#include "mymalloc.h"
// initialization of Allocator (static) instance (Singleton design pattern is used)
Allocator * Allocator::instance = 0;
extern "C" void *mymalloc(size_t cbytes){
Allocator *allocator = Allocator::getInstance();
return allocator->allocateFor(cbytes);
}
extern "C" void myfree(void *ptr){
Allocator *allocator = Allocator::getInstance();
allocator->freePtr(ptr);
}
extern "C" void *myrelocate(void *ptr){
Allocator *allocator = Allocator::getInstance();
return allocator->relocatePtr(ptr);
}
extern "C" size_t mysize(void *ptr){
Allocator *allocator = Allocator::getInstance();
return allocator->findSize(ptr);
}
Address Allocator::shiftToClosestMultipleOf4096(Address address){
return address - (address % 4096);
}
void * Allocator::allocateFor(size_t cbytes){
if (cbytes > 4096 || cbytes <= 0){ // delegate memory allocation to system's malloc
return malloc(cbytes);
}else{ // it is our job
PageList* pageList = sizeIndex.getPageList(cbytes); // get the list of nodes of pages for that class of sizes
PageListNode* pageListNode = pageList->searchForSpace(); // traverse to find a node with free space
if (pageListNode == nullptr){ // no space found, create a new node
Address address = pagePool.requestNewPage();
if (address == 0){ // system's malloc failed
return NULL;
}
pageListNode = pageList->addPageNode(address, 4096);
// store new node into hashTable
Address key = shiftToClosestMultipleOf4096(address);
hashTable.store(key, pageListNode);
}
Address address = pageListNode->occupySpace(); // this is the actual allocation
return (void*)address;
}
}
void Allocator::freePtr(void *ptr) {
Address key = shiftToClosestMultipleOf4096((Address)ptr);
PageListNode *pageListNode = hashTable.get(key);
if (pageListNode == nullptr){ // not our object, call original free
free(ptr);
return;
}
if (! pageListNode->isValidObjectAddress((Address) ptr)){
if (! _MUTE_PARAM_) fprintf(stderr, "***mymalloc: Invalid pointer %p at `myfree()'.***\n", ptr);
return;
}
bool success = pageListNode->markFree((Address)ptr); // actual freeing (attempting)
if (! success){
if (! _MUTE_PARAM_) fprintf(stderr, "***mymalloc: Double free of pointer %p at `myfree()'.***\n", ptr);
return;
}
// check if node is completely free and if so, move it to the beginning of the list for easy access
PageList *pageList = pageListNode->getPageListBelonging();
if (pageListNode->isCompletelyFree()) {
pageList->movePageNodeToBeginning(pageListNode);
}
}
Allocator::Allocator() {
this->pagePool = PagePool();
this->hashTable = HashTable();
this->sizeIndex = SizeIndex();
}
Allocator *Allocator::getInstance() {
// the implemantation of the singleton pattern. Always returns the same instance
if (! instance){
instance = new Allocator;
}
return instance;
}
void *Allocator::relocatePtr(void *ptr){
Address key = shiftToClosestMultipleOf4096((Address)ptr);
PageListNode *pageListNode = hashTable.get(key);
if (pageListNode == nullptr){ // not our object
return nullptr;
}
int index = pageListNode->findpositionOfObjectInPage((Address) ptr);
return (void *)(pageListNode->getStartOfPage() + index*pageListNode->getPageListBelonging()->getObjectsSize());
}
size_t Allocator::findSize(void *ptr) {
Address key = shiftToClosestMultipleOf4096((Address)ptr);
PageListNode *pageListNode = hashTable.get(key);
if (pageListNode == nullptr){ // not our object
return 0;
}
return (size_t)pageListNode->getPageListBelonging()->getObjectsSize();
}