forked from ReKernel/ReKernel
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmemory.c
More file actions
executable file
·106 lines (94 loc) · 3.35 KB
/
Copy pathmemory.c
File metadata and controls
executable file
·106 lines (94 loc) · 3.35 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
#include "memory.h"
#include "vga.h"
/* ── Block header ────────────────────────────────────────────────────────────
Every allocation is preceded by this header.
'size' is the usable payload size (not including the header).
'free' is 1 if the block is available, 0 if in use.
'next' chains all blocks in address order for O(n) coalescing.
───────────────────────────────────────────────────────────────────────────── */
typedef struct block_header {
size_t size;
uint8_t free;
struct block_header *next;
} block_header_t;
#define HEADER_SZ sizeof(block_header_t)
#define ALIGN8(n) (((n) + 7) & ~7u) /* round up to 8-byte boundary */
/* Static 1 MB heap */
static uint8_t heap[HEAP_SIZE] __attribute__((aligned(16)));
static block_header_t *heap_start = NULL;
void memory_init(void) {
heap_start = (block_header_t *)heap;
heap_start->size = HEAP_SIZE - HEADER_SZ;
heap_start->free = 1;
heap_start->next = NULL;
}
/* Split a free block if it is large enough to hold the requested size plus
a new header and at least 8 bytes of payload. */
static void split(block_header_t *b, size_t size) {
if (b->size >= size + HEADER_SZ + 8) {
block_header_t *new = (block_header_t *)((uint8_t *)b + HEADER_SZ + size);
new->size = b->size - size - HEADER_SZ;
new->free = 1;
new->next = b->next;
b->size = size;
b->next = new;
}
}
/* Merge adjacent free blocks (coalescing) */
static void coalesce(void) {
block_header_t *cur = heap_start;
while (cur && cur->next) {
if (cur->free && cur->next->free) {
cur->size += HEADER_SZ + cur->next->size;
cur->next = cur->next->next;
} else {
cur = cur->next;
}
}
}
void *kmalloc(size_t size) {
if (!size) return NULL;
size = ALIGN8(size);
block_header_t *cur = heap_start;
while (cur) {
if (cur->free && cur->size >= size) {
split(cur, size);
cur->free = 0;
return (void *)((uint8_t *)cur + HEADER_SZ);
}
cur = cur->next;
}
/* Out of memory */
vga_set_colour(VGA_WHITE, VGA_RED);
vga_puts("\n[KMALLOC] Out of heap memory!\n");
return NULL;
}
void kfree(void *ptr) {
if (!ptr) return;
block_header_t *b = (block_header_t *)((uint8_t *)ptr - HEADER_SZ);
b->free = 1;
coalesce();
}
void *kmemset(void *ptr, int val, size_t n) {
uint8_t *p = (uint8_t *)ptr;
while (n--) *p++ = (uint8_t)val;
return ptr;
}
void *kmemcpy(void *dst, const void *src, size_t n) {
uint8_t *d = (uint8_t *)dst;
const uint8_t *s = (const uint8_t *)src;
while (n--) *d++ = *s++;
return dst;
}
void memory_dump_stats(void) {
size_t free_bytes = 0, used_bytes = 0, blocks = 0;
block_header_t *cur = heap_start;
while (cur) {
blocks++;
if (cur->free) free_bytes += cur->size;
else used_bytes += cur->size;
cur = cur->next;
}
vga_printf(" Heap: %u used, %u free, %u blocks\n",
used_bytes, free_bytes, blocks);
}