-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfree.c
53 lines (41 loc) · 1.54 KB
/
free.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
#include "Heap.h"
//
// Release a chunk of memory from the heap
//
void free(void* ptr) {
//Test for nullptr
if (!ptr) {return;}
lock_heap();
//Make sure the block is valid and not already freed
pHeap_Block_t block = PTR_BLOCK(ptr);
if (!valid_block(block)) {return unlock_heap(); /* Bad Pointer */}
if (IS_FREE_BLOCK(block)) {return unlock_heap(); /* Double Free! */ }
//Indiate that this block is now free
block->size *= -1;
block->checksum = block_checksum(block);
//Merge blocks on the front and end of this block
// Start by finding the most previous free block
pHeap_Block_t start_merge = block;
while(start_merge->pre) {
if (!valid_block(start_merge->pre)) {return unlock_heap(); /* HEAP CORRUPTION */}
if (!IS_FREE_BLOCK(start_merge->pre)) {break;}
start_merge = start_merge->pre;
}
//Now find out the total number of consecutive free blocks, and the total length
pHeap_Block_t end_merge = start_merge;
size_t total_size = start_merge->size;
while (end_merge->next) {
if (!valid_block(end_merge->next)) {return unlock_heap(); /* HEAP CORRUPTION */}
if (!IS_FREE_BLOCK(end_merge->next)) {break;}
end_merge = end_merge->next;
total_size += (BLOCK_LENGTH + end_merge->size);
}
//Reconfigure the linked-list
start_merge->next = end_merge->next;
if (end_merge->next) {end_merge->next->pre = start_merge;}
start_merge->size = total_size;
//Update the list checksums
start_merge->checksum = block_checksum(start_merge);
if (end_merge->next) {end_merge->next->checksum = block_checksum(end_merge->next);}
unlock_heap();
}