-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmem.c
More file actions
119 lines (94 loc) · 3.03 KB
/
mem.c
File metadata and controls
119 lines (94 loc) · 3.03 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
/* OneOS-ARM Heap Memory Allocator */
#include "mem.h"
/* Free list head */
static mem_block_t *free_list = NULL;
/* Statistics */
static size_t total_allocated = 0;
static size_t total_free = 0;
/* Align size to 8-byte boundary */
#define ALIGN_SIZE(size) (((size) + 7) & ~7)
/* Get block from pointer */
#define BLOCK_FROM_PTR(ptr) ((mem_block_t *)((uint8_t *)(ptr) - sizeof(mem_block_t)))
/* Get pointer from block */
#define PTR_FROM_BLOCK(block) ((void *)((uint8_t *)(block) + sizeof(mem_block_t)))
void mem_init(void *start, size_t size)
{
/* Initialize heap with one large free block */
mem_block_t *initial_block = (mem_block_t *)start;
initial_block->size = size - sizeof(mem_block_t);
initial_block->next = NULL;
initial_block->prev = NULL;
initial_block->free = 1;
free_list = initial_block;
total_allocated = 0;
total_free = size;
}
void *kmalloc(size_t size)
{
if (size == 0) return NULL;
/* Align size */
size = ALIGN_SIZE(size);
/* Find first fit in free list */
mem_block_t *current = free_list;
while (current) {
if (current->free && current->size >= size) {
/* Found suitable block */
if (current->size > size + sizeof(mem_block_t) + 8) {
/* Split block */
mem_block_t *new_block = (mem_block_t *)((uint8_t *)current + sizeof(mem_block_t) + size);
new_block->size = current->size - size - sizeof(mem_block_t);
new_block->next = current->next;
new_block->prev = current;
new_block->free = 1;
if (current->next) {
current->next->prev = new_block;
}
current->next = new_block;
current->size = size;
}
/* Mark as allocated */
current->free = 0;
/* Update statistics */
total_allocated += current->size;
total_free -= current->size + sizeof(mem_block_t);
return PTR_FROM_BLOCK(current);
}
current = current->next;
}
/* No suitable block found */
return NULL;
}
void kfree(void *ptr)
{
if (!ptr) return;
mem_block_t *block = BLOCK_FROM_PTR(ptr);
/* Mark as free */
block->free = 1;
/* Update statistics */
total_allocated -= block->size;
total_free += block->size + sizeof(mem_block_t);
/* Coalesce with next block if free */
if (block->next && block->next->free) {
block->size += sizeof(mem_block_t) + block->next->size;
block->next = block->next->next;
if (block->next) {
block->next->prev = block;
}
}
/* Coalesce with previous block if free */
if (block->prev && block->prev->free) {
block->prev->size += sizeof(mem_block_t) + block->size;
block->prev->next = block->next;
if (block->next) {
block->next->prev = block->prev;
}
}
}
size_t mem_get_used(void)
{
return total_allocated;
}
size_t mem_get_free(void)
{
return total_free;
}