-
Notifications
You must be signed in to change notification settings - Fork 0
/
realloc.c
80 lines (58 loc) · 2.05 KB
/
realloc.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
#include "Heap.h"
#include <string.h> /* For memcpy */
//
// Reallocate the size of something stored in the heap
//
void* realloc(void* ptr, size_t size) {
if (!ptr) {return malloc(size);}
lock_heap();
pHeap_Block_t block = PTR_BLOCK(ptr);
if (!valid_block) {return (unlock_heap(), NULL); /* HEAP Corruption */ }
//Size of 0 frees the block
if (size == 0) {free(ptr); return NULL;}
//Figure out the size alignment (should be 8 bytes)
size = NEXT_HEAP_ALIGN(size);
//See if the realloc is smaller (We might need to split it!)
// Figure out if it is worth the space to split it
if ((size + BLOCK_LENGTH) < BLOCK_SIZE(block)) {
split_block(block,size);
return (unlock_heap(), ptr);
}
//See if this block is already large enough
if (BLOCK_SIZE(block) >= size) {return (unlock_heap(), ptr);}
//See if I can merge with possible free blocks in front of me
pHeap_Block_t end_block = block;
size_t total_size = BLOCK_SIZE(block);
while((end_block->next) && (total_size < size)) {
if (!valid_block(end_block->next)) {return (unlock_heap(), NULL); /* Heap Corruption */}
if (!IS_FREE_BLOCK(end_block->next)) {break;}
end_block = end_block->next;
total_size += (BLOCK_LENGTH + end_block->size);
}
//Yes, merge those blocks
if (total_size >= size) {
//Sew up the linked-list
block->next = end_block->next;
if (end_block->next) {end_block->next->pre = block;}
//Resize the array
block->size = -total_size;
//Update the checksums
block->checksum = block_checksum(block);
if (end_block->next) {end_block->next->checksum = block_checksum(end_block->next);}
//The combined block might be too big
// Figure out if it is worth the space to split it
if ((size + BLOCK_LENGTH) < BLOCK_SIZE(block)) {
split_block(block,size);
}
return (unlock_heap(), ptr);
}
//No, we need to completely reallocate the buffer
unlock_heap();
void* new_buffer = malloc(size);
if (!new_buffer) {return NULL;}
//Copy the data into the new buffer
memcpy(new_buffer,ptr,BLOCK_SIZE(block));
//Release the old buffer
free(ptr);
return new_buffer;
}