-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmem-alloc.c
More file actions
134 lines (105 loc) · 3.39 KB
/
Copy pathmem-alloc.c
File metadata and controls
134 lines (105 loc) · 3.39 KB
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
#include <unistd.h>
#include <thread_db.h>
#include <memory.h>
typedef char ALIGN[16];
union header { // We use Union to make sure that we align with memory block (16 bytes)
struct {
size_t size;
unsigned is_free;
union header* next;
} s; // declare struct
ALIGN stub;
};
typedef union header header_t;
header_t *head, *tail;
header_t* get_free_block(size_t size) {
header_t* curr = head;
while(curr) {
if (curr->s.is_free && curr->s.size >= size) {
return curr;
}
curr = curr->s.next;
}
return NULL; // No available memory block found
}
pthread_mutex_t global_malloc_lock;
void* malloc(size_t size) {
if (size == 0) return NULL; // Requested memmory is zero, exit
pthread_mutex_lock(&global_malloc_lock);
header_t* header = get_free_block(size);
if (header) { // Free memory block found within previously used pool, reuse it
header->s.is_free = 0;
pthread_mutex_unlock(&global_malloc_lock);
return (void*)(header+1); // Hide header by moving pointer by one byte to the right,
// this is incidentally also the first byte of the actual memory block.
}
// No available block found, extend heap
size_t total_size = sizeof(header_t) + size;
void* block = sbrk(total_size);
if (block == (void*)-1) { // Check if memory is successfully allocated, exit otherwise
pthread_mutex_unlock(&global_malloc_lock);
return NULL;
}
// Create new header object and add it to the list
header = block;
header->s.is_free = 0;
header->s.next = NULL;
header->s.size = size;
if (!head) head = header; // Assign head if list is empty
if (tail) tail->s.next = header;
tail = header;
pthread_mutex_unlock(&global_malloc_lock);
return (void*)(header+1);
}
void free(void* block) {
if (!block) return; // Block is already free, exit
pthread_mutex_lock(&global_malloc_lock);
void* heap_break = sbrk(0); // Get adress of heap break
header_t *header = (void*)(block - 1); // Assign pointer to header by moving it one byte to the left
if ((char*)block + header->s.size == heap_break) { // Check if given block is at the end of heap
if (head == tail) { // List consists only of one element
head = tail = NULL;
} else { // Delete tail
header_t *curr = head;
while(curr->s.next != tail) {
curr = curr->s.next;
}
curr->s.next = NULL;
tail = curr;
}
sbrk(-sizeof(header_t*) - header->s.size); // Shrink heap
} else {
header->s.is_free = 1; // Do not alter heap, mark block as free
}
pthread_mutex_unlock(&global_malloc_lock);
}
// Allocate memory for an array of num elements of nsize bytes each
void* calloc(size_t num, size_t nsize) {
if (!num || !nsize) return NULL;
pthread_mutex_lock(&global_malloc_lock);
size_t size = num * nsize;
if (nsize != size / num) return NULL; // Check for overflow
void *block = malloc(size);
if (!block) return NULL;
memset(block, 0, size); // Set memory to zero
pthread_mutex_unlock(&global_malloc_lock);
return block; // Return a pointer to the allocated memory
}
void* realloc(void* block, size_t size) {
if (!block || !size) return NULL;
pthread_mutex_lock(&global_malloc_lock);
header_t *header = block - 1;
if (header->s.size >= size) { // Block already has requested size
pthread_mutex_unlock(&global_malloc_lock);
return block;
}
void* ret = malloc(size);
if (ret) {
memcpy(ret, block, header->s.size); // Relocate contents to the new bigger block
free(block);
}
return ret;
}
int main() {
return 0;
}