Skip to content

Commit 0c9ea05

Browse files
authored
HW 4 Submission
1 parent 0a9c9e3 commit 0c9ea05

File tree

1 file changed

+238
-0
lines changed

1 file changed

+238
-0
lines changed

malloc_3.cpp

+238
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
//
2+
// Created by Alon on 06/06/2019.
3+
//
4+
5+
#include <unistd.h>
6+
#include <cstring>
7+
#include <cstdlib>
8+
9+
#define MAX_SIZE (100000000)
10+
#define SBRK_ERROR ((void*)(-1))
11+
#define ALIGNMENT_BYTES (4)
12+
#define NUM_OF_BYTES_TO_SPLIT (128)
13+
14+
typedef struct allocated_meta_data {
15+
size_t requested_size;
16+
void *first_byte_in_block;
17+
bool is_free;
18+
allocated_meta_data *prev;
19+
allocated_meta_data *next;
20+
} Meta_data
21+
__attribute__((aligned(ALIGNMENT_BYTES)));
22+
23+
static Meta_data list_head = {0, NULL, false, NULL, NULL};
24+
// list_head is a dummy node, wil never be freed true
25+
26+
size_t _size_meta_data();
27+
void free(void *p);
28+
29+
bool align_program_break() {
30+
/// Problem 4 fix
31+
void *current_prg_brk = sbrk(0);
32+
if (current_prg_brk == SBRK_ERROR) return false;
33+
int offset = ((long) current_prg_brk % ALIGNMENT_BYTES);
34+
if (offset) {
35+
return sbrk(offset);
36+
}
37+
return true;
38+
}
39+
40+
size_t align_number_upward(size_t size) {
41+
/// Problem 4 fix
42+
switch (size % 4) {
43+
case 0:
44+
return 0;
45+
case 1:
46+
return 3;
47+
case 2:
48+
return 2;
49+
case 3:
50+
return 1;
51+
}
52+
return 0; // shouldn't get here
53+
}
54+
55+
void *_helper_on_problem_one(Meta_data *node, size_t size) {
56+
/// Problem 1 fix
57+
//assert(node->requested_size >= size);
58+
59+
signed long remaining_free_space_temp =
60+
node->requested_size - size - _size_meta_data();
61+
size_t remaining_free_space = (remaining_free_space_temp >= 0) ?
62+
remaining_free_space_temp : 0;
63+
if (remaining_free_space < NUM_OF_BYTES_TO_SPLIT) {
64+
node->is_free = false;
65+
return node->first_byte_in_block;
66+
}
67+
68+
// else 128 or more >> split
69+
// case making 1 block into 2 blocks:
70+
void *new_p = (void *) (((char *) node->first_byte_in_block) + size);
71+
Meta_data *new_node = (Meta_data *) new_p;
72+
*new_node = (Meta_data) {remaining_free_space, new_node + 1, true, node,
73+
node->next};
74+
node->next = new_node;
75+
node->is_free = false;
76+
node->requested_size = size;
77+
if (new_node->next) new_node->next->prev = new_node;
78+
new_node->is_free = false; // preparing for free function
79+
free(new_node + 1); /// problem 2 fix
80+
return node->first_byte_in_block;
81+
}
82+
83+
void *_helper_on_problem_three(Meta_data *node, size_t size) {
84+
/// Problem 3 fix: "Wilderness"
85+
//assert(node && !node->next && size);
86+
87+
void *res = sbrk(size - node->requested_size); // resizing last node
88+
if (res == SBRK_ERROR) return NULL;
89+
node->requested_size = size;
90+
node->is_free = false;
91+
return node->first_byte_in_block;
92+
}
93+
94+
void *malloc(size_t size) {
95+
if (!size || size > MAX_SIZE) return NULL;
96+
//if (!align_program_break()) return NULL;
97+
/// this change canceled on 21.06.2019
98+
Meta_data *node = &list_head;
99+
size = size + align_number_upward(size); // fix for problem 4
100+
101+
102+
while (node) { // scan the list for freed space
103+
if (node->is_free && node->requested_size >= size) {
104+
return _helper_on_problem_one(node, size);
105+
}
106+
if (node->next)
107+
node = node->next;
108+
else break; // breaks only for last node in the list
109+
}
110+
111+
if (node && node->is_free && !node->next) { //Wilderness
112+
return _helper_on_problem_three(node, size);
113+
}
114+
115+
// not enough free space, allocating:
116+
void *res = sbrk(_size_meta_data() + size);
117+
if (res == SBRK_ERROR) return NULL;
118+
// writing the meta-data
119+
Meta_data *new_data = (Meta_data *) res;
120+
*new_data = (Meta_data) {size, new_data + 1, false, node, NULL};
121+
node->next = new_data;
122+
return new_data->first_byte_in_block; // returns the start of the data segment
123+
}
124+
125+
void *calloc(size_t num, size_t size) {
126+
if (!size || !num || size * num > MAX_SIZE) return NULL;
127+
size = size * num + align_number_upward(size * num); // fix for problem 4
128+
void *res = malloc(size);
129+
if (!res) return res;
130+
return std::memset(res, 0, size);
131+
}
132+
133+
void free(void *p) {
134+
if (!p) return;
135+
Meta_data *meta_data = ((Meta_data *) p) - 1;
136+
if (meta_data->is_free) return;
137+
meta_data->is_free = true;
138+
139+
/// Problem 2 fix
140+
if (meta_data->prev && meta_data->prev->is_free) {
141+
Meta_data *old_data = meta_data;
142+
meta_data = old_data->prev;
143+
meta_data->requested_size = meta_data->requested_size +
144+
old_data->requested_size +
145+
_size_meta_data();
146+
meta_data->next = old_data->next;
147+
if (meta_data->next) meta_data->next->prev = meta_data;
148+
149+
}
150+
if (meta_data->next && meta_data->next->is_free) {
151+
Meta_data *old_data = meta_data->next;
152+
meta_data->requested_size = meta_data->requested_size +
153+
old_data->requested_size +
154+
_size_meta_data();
155+
meta_data->next = old_data->next;
156+
if (meta_data->next) meta_data->next->prev = meta_data;
157+
}
158+
}
159+
160+
void *realloc(void *oldp, size_t size) {
161+
if (!size || size > MAX_SIZE) return NULL;
162+
if (!oldp) return malloc(size);
163+
size = size + align_number_upward(size); // fix for problem 4
164+
165+
Meta_data *node = ((Meta_data *) oldp) - 1;
166+
if (node->requested_size >= size) {
167+
return _helper_on_problem_one(node, size); // splits block if possible
168+
}
169+
// ELSE: case new_size > old_size:
170+
171+
if (node->next && node->next->is_free) {
172+
// merging with adjacant higher block
173+
node->requested_size += _size_meta_data() + node->next->requested_size;
174+
node->next = node->next->next;
175+
if (node->next) node->next->prev = node;
176+
return realloc(oldp, size);
177+
}
178+
179+
if (!node->next) { // "Wildereness"
180+
return _helper_on_problem_three(node, size); // enlarge last block
181+
}
182+
183+
void *res = malloc(size);
184+
if (!res) return res;
185+
res = memcpy(res, oldp, node->requested_size);
186+
free(oldp); /// problem 2 fix
187+
return res;
188+
}
189+
190+
size_t _num_free_blocks() {
191+
Meta_data *node = list_head.next;
192+
size_t free_blocks_counter = 0;
193+
while (node) { // scan the list for freed blocks
194+
free_blocks_counter += node->is_free;
195+
node = node->next;
196+
}
197+
return free_blocks_counter;
198+
}
199+
200+
size_t _num_free_bytes() {
201+
Meta_data *node = list_head.next;
202+
size_t free_bytes_counter = 0;
203+
while (node) { // scan the list for freed blocks
204+
free_bytes_counter += node->is_free ? node->requested_size : 0;
205+
node = node->next;
206+
}
207+
return free_bytes_counter;
208+
}
209+
210+
size_t _num_allocated_blocks() {
211+
Meta_data *node = list_head.next;
212+
size_t allocated_blocks_counter = 0;
213+
while (node) { // scan the list for freed blocks
214+
allocated_blocks_counter++;
215+
node = node->next;
216+
}
217+
return allocated_blocks_counter;
218+
}
219+
220+
size_t _num_allocated_bytes() {
221+
Meta_data *node = list_head.next;
222+
size_t allocated_bytes_counter = 0;
223+
while (node) { // scan the list for freed blocks
224+
allocated_bytes_counter += node->requested_size;
225+
node = node->next;
226+
}
227+
return allocated_bytes_counter;
228+
}
229+
230+
size_t _num_meta_data_bytes() {
231+
return _num_allocated_blocks() * _size_meta_data();
232+
}
233+
234+
size_t _size_meta_data() {
235+
return sizeof(struct allocated_meta_data);
236+
}
237+
238+

0 commit comments

Comments
 (0)