-
Notifications
You must be signed in to change notification settings - Fork 0
/
heap_globals.c
131 lines (95 loc) · 2.69 KB
/
heap_globals.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
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
#include "Heap.h"
#include <pthread.h> /* For thread functions */
#include <unistd.h> /* For sbrk */
//Global Heap Variables
static pthread_mutex_t heap_lock = PTHREAD_MUTEX_INITIALIZER;
static pHeap_Block_t heap_start = 0;
//
// Initialize the heap variables (do this once)
//
static bool init_heap(void) {
//Start of the heap
heap_start = (pHeap_Block_t) sbrk(0);
if (!IS_VALID_SBRK(heap_start)) {
heap_start = 0;
return false;
}
//Increase the heap size to the starting size
// Size = START_SIZE + BLOCK_LENGTH
if (!IS_VALID_SBRK(
sbrk(HEAP_START_SIZE + BLOCK_LENGTH)
)) {return false;}
//Configure values inside starting block
heap_start->pre = heap_start->next = NULL;
heap_start->size = HEAP_START_SIZE;
heap_start->checksum = block_checksum(heap_start);
return true;
}
//
// Lock the heap and return a pointer to do heap operations
//
pHeap_Block_t lock_heap(void) {
//Lock the heap
pthread_mutex_lock(&heap_lock);
//Allocate the heap default stuff once
if (!heap_start) {
if (!init_heap()) {
pthread_mutex_unlock(&heap_lock);
return NULL;
}
}
return heap_start;
}
//
// Unlock the heap
//
void unlock_heap(void) {
pthread_mutex_unlock(&heap_lock);
}
//
// Validate a given block
//
bool valid_block(pHeap_Block_t block) {
if (!block) {return false;}
if (block->checksum != block_checksum(block)) {return false;}
return true;
}
//
// Add more bytes to the end of the heap (return bytes added)
//
size_t increase_heap(size_t bytes_needed) {
//Round up bytes_needed to the next heap increment
bytes_needed = NEXT_HEAP_INC(bytes_needed);
if (!IS_VALID_SBRK(sbrk(bytes_needed))) {return 0;}
return bytes_needed;
}
//
// Create a new block in the heap
// Assumes that prev, next, offset and size are legit
//
pHeap_Block_t create_block(pHeap_Block_t prev, pHeap_Block_t next, size_t offset, size_t size) {
//Configure the linked-list
pHeap_Block_t new_block = NEXT_BLOCK(prev,offset);
new_block->pre = prev;
new_block->next = next;
if (prev) {prev->next = new_block;}
if (next) {next->pre = new_block;}
//Update the size
new_block->size = size;
//Recompute checksums
if (prev) {prev->checksum = block_checksum(prev);}
if (next) {next->checksum = block_checksum(next);}
new_block->checksum = block_checksum(new_block);
return new_block;
}
//
// Split one free block into two free blocks
// Assumes new_size < block->size, and everything is aligned
//
void split_block(pHeap_Block_t block, size_t new_size) {
create_block(block, block->next, new_size, BLOCK_SIZE(block) - (new_size + BLOCK_LENGTH));
//Test for a negative size
if (block->size < 0) {block->size = -new_size;}
else {block->size = new_size;}
block->checksum = block_checksum(block);
}