-
Notifications
You must be signed in to change notification settings - Fork 43
/
mem.c
78 lines (66 loc) · 1.99 KB
/
mem.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
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#define HEAP_SIZE 1024 * 1024
typedef struct HeapSegmentHeader {
uint32_t allocated;
uint32_t size;
struct HeapSegmentHeader *prev;
struct HeapSegmentHeader *next;
} __attribute__((packed)) HeapSegmentHeader;
extern uint8_t __end[HEAP_SIZE];
static HeapSegmentHeader *heapSegmentsHead;
void mem_init(void)
{
heapSegmentsHead = (HeapSegmentHeader *) &__end;
heapSegmentsHead->allocated = false;
heapSegmentsHead->size = HEAP_SIZE;
heapSegmentsHead->prev = NULL;
heapSegmentsHead->next = NULL;
}
void *malloc(size_t size)
{
size += sizeof(HeapSegmentHeader);
size += size % 16 ? 16 - (size % 16) : 0;
HeapSegmentHeader *best = NULL;
size_t bestDiff = SIZE_MAX;
for (HeapSegmentHeader *curr = heapSegmentsHead; curr != NULL;
curr = curr->next) {
if (!curr->allocated && curr->size >= size) {
size_t diff = curr->size - size;
if (diff < bestDiff) {
best = curr;
bestDiff = diff;
}
}
}
if (best == NULL) {
return best;
}
if (bestDiff > sizeof(HeapSegmentHeader) * 2) {
HeapSegmentHeader *oldNext = best->next;
best->next = (void *) best + size;
best->next->allocated = false;
best->next->size = best->size - size;
best->next->next = oldNext;
best->next->prev = best;
best->size = size;
}
best->allocated = true;
return best + 1;
}
void free(void *ptr)
{
HeapSegmentHeader *segment = ptr - sizeof(HeapSegmentHeader);
segment->allocated = false;
while (segment->prev != NULL && !segment->prev->allocated) {
segment->prev->next = segment->next;
segment->prev->size += segment->size;
segment = segment->prev;
}
while (segment->next != NULL && !segment->next->allocated) {
segment->size += segment->next->size;
segment->next = segment->next->next;
}
}