feat: kmalloc + slab allocator
This commit is contained in:
parent
167c99c215
commit
01773cb062
41 changed files with 454 additions and 32 deletions
meta/targets
src
kernel
core
hal
kmalloc
manifest.jsonmanifest.sync-conflict-20250504-125402-L4Z4EYX.jsonmod.cmod.hmod.sync-conflict-20250504-125402-L4Z4EYX.h
libs/libc
pmm
sched
task
libs
allocators
handover/dtb
helpers
traits
|
@ -34,9 +34,7 @@ SECTIONS {
|
|||
|
||||
. += CONSTANT(MAXPAGESIZE);
|
||||
|
||||
stack_start_addr = .;
|
||||
. = ALIGN(4);
|
||||
. += 128 * 1024; /* 128KB */
|
||||
__stack_top = .;
|
||||
stack_end_addr = .;
|
||||
}
|
||||
|
|
|
@ -1,9 +1,20 @@
|
|||
#include <allocators/slab.h>
|
||||
#include <fmt>
|
||||
#include <hal>
|
||||
#include <kmalloc>
|
||||
#include <logger>
|
||||
#include <string.h>
|
||||
|
||||
void kmain(void) {
|
||||
info$("Hello, World!");
|
||||
kmalloc_init();
|
||||
|
||||
Allocator kmalloc = kmalloc_allocator();
|
||||
char* hello = (char*)kmalloc.alloc(&kmalloc, 14);
|
||||
memset(hello, 0, 14);
|
||||
strncpy(hello, "Hello, World!", 13);
|
||||
info$("%s", hello);
|
||||
kmalloc.free(&kmalloc, hello, 14);
|
||||
|
||||
for (;;)
|
||||
;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,6 @@
|
|||
"id": "hal",
|
||||
"requires": [
|
||||
"hal-impl",
|
||||
"heap"
|
||||
"allocators"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <dtb>
|
||||
#include <helpers/errors.h>
|
||||
#include <io>
|
||||
|
||||
void hal_setup(void);
|
||||
|
@ -16,15 +17,17 @@ typedef enum {
|
|||
HAL_MAP_HUGE = 1 << 4,
|
||||
} HalMapFlags;
|
||||
|
||||
typedef enum {
|
||||
HAL_MAP_OK,
|
||||
HAL_MAP_PHYS_UNALIGNED,
|
||||
HAL_MAP_VIRT_UNALIGNED,
|
||||
HAL_MAP_COULDNT_ALLOCATE,
|
||||
HAL_MAP_ALREADY_MAPPED,
|
||||
} HalMappingError;
|
||||
#define MAPPING_ERRORS(ERR) \
|
||||
ERR(HAL_MAP_OK, "Operation completed successfully") \
|
||||
ERR(HAL_MAP_PHYS_UNALIGNED, "Physical address is unaligned") \
|
||||
ERR(HAL_MAP_VIRT_UNALIGNED, "Virtual address is unaligned") \
|
||||
ERR(HAL_MAP_COULDNT_ALLOCATE, "Couldn't allocate memory") \
|
||||
ERR(HAL_MAP_ALREADY_MAPPED, "Page is already mapped")
|
||||
|
||||
typedef struct _page HalPage;
|
||||
DECLARE_ERROR_ENUM(HalMapping, MAPPING_ERRORS)
|
||||
DECLARE_ERROR_STRING(HalMapping, MAPPING_ERRORS)
|
||||
|
||||
typedef struct _hal_page HalPage;
|
||||
|
||||
HalMappingError hal_map_page(HalPage page, uintptr_t virt, uintptr_t phys, size_t length, uint8_t flags);
|
||||
|
||||
|
@ -32,6 +35,16 @@ void hal_switch_space(HalPage space);
|
|||
|
||||
size_t page_size(void);
|
||||
|
||||
void* hal_mmap_l2h(uintptr_t addr);
|
||||
|
||||
void* hal_mmap_h2l(uintptr_t addr);
|
||||
|
||||
/* === TASKS & SCHEDULING === */
|
||||
|
||||
typedef struct _hal_context HalContext;
|
||||
|
||||
HalContext* hal_create_context(void);
|
||||
|
||||
/* === I/O === */
|
||||
|
||||
void hal_putc(int ch);
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
#include <allocators/bump.h>
|
||||
#include <allocators/slab.h>
|
||||
#include <dtb>
|
||||
#include <hal>
|
||||
#include <handover-dtb>
|
||||
#include <heap/bump.h>
|
||||
#include <helpers/mem.h>
|
||||
#include <logger>
|
||||
#include <pmm>
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
.section .text.boot
|
||||
|
||||
.global rv32_start
|
||||
.type rv32_start, @function
|
||||
|
||||
|
||||
.global _start
|
||||
_start:
|
||||
mv ra, zero
|
||||
|
|
8
src/kernel/hal/rv32/context.c
Normal file
8
src/kernel/hal/rv32/context.c
Normal file
|
@ -0,0 +1,8 @@
|
|||
#include <hal>
|
||||
#include <string.h>
|
||||
|
||||
#include "context.h"
|
||||
|
||||
HalContext* hal_context_create(void) {
|
||||
return NULL;
|
||||
}
|
9
src/kernel/hal/rv32/context.h
Normal file
9
src/kernel/hal/rv32/context.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#include <hal>
|
||||
|
||||
#include "regs.h"
|
||||
|
||||
struct _hal_context {
|
||||
Stackframe frame;
|
||||
};
|
|
@ -42,7 +42,7 @@ static void panic_handler(Stackframe* frame, uint32_t scause, uint32_t stval, ui
|
|||
}
|
||||
}
|
||||
|
||||
void exception_handler(Stackframe* frame) {
|
||||
Stackframe* exception_handler(Stackframe* frame) {
|
||||
uint32_t scause = read_csr$(scause);
|
||||
uint32_t stval = read_csr$(stval);
|
||||
uint32_t user_pc = read_csr$(sepc);
|
||||
|
@ -52,4 +52,6 @@ void exception_handler(Stackframe* frame) {
|
|||
} else {
|
||||
panic_handler(frame, scause, stval, user_pc);
|
||||
}
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
|
|
@ -4,4 +4,4 @@
|
|||
|
||||
extern void interrupt_kernel(void);
|
||||
|
||||
void exception_handler(Stackframe* frame);
|
||||
Stackframe* exception_handler(Stackframe* frame);
|
||||
|
|
|
@ -40,6 +40,7 @@ interrupt_kernel:
|
|||
|
||||
mv a0, sp
|
||||
call exception_handler
|
||||
mv sp, a0
|
||||
|
||||
lw ra, 4 * 0(sp)
|
||||
lw gp, 4 * 1(sp)
|
||||
|
|
|
@ -13,3 +13,11 @@ void hal_brkpoint(void) {
|
|||
size_t page_size(void) {
|
||||
return 4096;
|
||||
}
|
||||
|
||||
void* hal_mmap_l2h(uintptr_t addr) {
|
||||
return (void*)addr;
|
||||
}
|
||||
|
||||
void* hal_mmap_h2l(uintptr_t addr) {
|
||||
return (void*)addr;
|
||||
}
|
||||
|
|
|
@ -7,5 +7,5 @@
|
|||
"sys": ["kernel"]
|
||||
},
|
||||
"provides": ["hal-impl"],
|
||||
"requires": ["dtb", "pmm", "handover-dtb"]
|
||||
"requires": ["dtb", "pmm", "handover-dtb", "kmalloc"]
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <pmm>
|
||||
#include <string.h>
|
||||
|
||||
#include "base/mod.h"
|
||||
#include "paging.h"
|
||||
#include "regs.h"
|
||||
|
||||
|
@ -13,8 +14,7 @@ extern uint8_t rodata_start_addr[];
|
|||
extern uint8_t rodata_end_addr[];
|
||||
extern uint8_t data_start_addr[];
|
||||
extern uint8_t data_end_addr[];
|
||||
extern uint8_t stack_start_addr[];
|
||||
extern uint8_t stack_end_addr[];
|
||||
extern uint8_t __stack_top[];
|
||||
|
||||
static uint32_t* kernel_page_table = NULL;
|
||||
|
||||
|
@ -93,6 +93,7 @@ void hal_switch_space(HalPage space) {
|
|||
__asm__ volatile("sfence.vma");
|
||||
}
|
||||
|
||||
// TODO: Use new error from <helpers/errors.h>
|
||||
void paging_init(void) {
|
||||
PhysObj page_phys = pmm_alloc(page_size());
|
||||
if (page_phys.base == 0) {
|
||||
|
@ -107,7 +108,7 @@ void paging_init(void) {
|
|||
size_t text_end = align_up$((uintptr_t)text_end_addr, page_size());
|
||||
HalMappingError err = hal_map_page((HalPage){kernel_page_table}, text_start, text_start, text_end - text_start, HAL_MAP_READ | HAL_MAP_EXEC);
|
||||
if (err != HAL_MAP_OK) {
|
||||
error$("Couldn't map kernel text, cause: %d", err);
|
||||
error$("Couldn't map kernel text, cause: %s", HalMappingErrorString(err));
|
||||
hal_brkpoint();
|
||||
}
|
||||
|
||||
|
@ -115,7 +116,7 @@ void paging_init(void) {
|
|||
size_t rodata_end = align_up$((uintptr_t)rodata_end_addr, page_size());
|
||||
err = hal_map_page((HalPage){kernel_page_table}, rodata_start, rodata_start, rodata_end - rodata_start, HAL_MAP_READ);
|
||||
if (err != HAL_MAP_OK) {
|
||||
error$("Couldn't map kernel rodata, cause: %d", err);
|
||||
error$("Couldn't map kernel rodata, cause: %s", HalMappingErrorString(err));
|
||||
hal_brkpoint();
|
||||
}
|
||||
|
||||
|
@ -123,18 +124,23 @@ void paging_init(void) {
|
|||
size_t data_end = align_up$((uintptr_t)data_end_addr, page_size());
|
||||
err = hal_map_page((HalPage){kernel_page_table}, data_start, data_start, data_end - data_start, HAL_MAP_READ | HAL_MAP_WRITE);
|
||||
if (err != HAL_MAP_OK) {
|
||||
error$("Couldn't map kernel data, cause: %d", err);
|
||||
error$("Couldn't map kernel data, cause: %s", HalMappingErrorString(err));
|
||||
hal_brkpoint();
|
||||
}
|
||||
|
||||
size_t stack_start = align_down$((uintptr_t)stack_start_addr, page_size());
|
||||
size_t stack_end = align_up$((uintptr_t)stack_end_addr, page_size());
|
||||
size_t stack_start = align_down$((uintptr_t)__stack_top - kib$(128), page_size());
|
||||
size_t stack_end = align_up$((uintptr_t)__stack_top, page_size());
|
||||
err = hal_map_page((HalPage){kernel_page_table}, stack_start, stack_start, stack_end - stack_start, HAL_MAP_READ | HAL_MAP_WRITE);
|
||||
if (err != HAL_MAP_OK) {
|
||||
error$("Couldn't map kernel stack, cause: %d", err);
|
||||
error$("Couldn't map kernel stack, cause: %s", HalMappingErrorString(err));
|
||||
hal_brkpoint();
|
||||
}
|
||||
|
||||
HandoverRecord rec;
|
||||
handover_foreach_record(handover(), rec) {
|
||||
hal_map_page((HalPage){kernel_page_table}, rec.start, rec.start, rec.size, HAL_MAP_READ | HAL_MAP_WRITE);
|
||||
}
|
||||
|
||||
debug$("Switching to page table %p", kernel_page_table);
|
||||
hal_switch_space((HalPage){kernel_page_table});
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ enum mapping_flags {
|
|||
MAPPING_USER = 1 << 4,
|
||||
};
|
||||
|
||||
struct _page {
|
||||
struct _hal_page {
|
||||
uint32_t* ptr;
|
||||
} __attribute__((packed));
|
||||
|
||||
|
|
9
src/kernel/kmalloc/manifest.json
Normal file
9
src/kernel/kmalloc/manifest.json
Normal file
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1",
|
||||
"type": "lib",
|
||||
"id": "kmalloc",
|
||||
"requires": [
|
||||
"allocators",
|
||||
"traits"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1",
|
||||
"id": "kmalloc",
|
||||
"type": "lib",
|
||||
"requires": [
|
||||
"allocators",
|
||||
"traits"
|
||||
]
|
||||
}
|
70
src/kernel/kmalloc/mod.c
Normal file
70
src/kernel/kmalloc/mod.c
Normal file
|
@ -0,0 +1,70 @@
|
|||
#include <allocators/slab.h>
|
||||
#include <logger>
|
||||
#include <pmm>
|
||||
|
||||
static SlabAllocator slabs[6] = {0};
|
||||
|
||||
void kmalloc_init(void) {
|
||||
Allocator pmm = pmm_allocator();
|
||||
|
||||
slabs[0] = slab_create(8, &pmm);
|
||||
slabs[1] = slab_create(16, &pmm);
|
||||
slabs[2] = slab_create(32, &pmm);
|
||||
slabs[3] = slab_create(64, &pmm);
|
||||
slabs[4] = slab_create(128, &pmm);
|
||||
slabs[5] = slab_create(256, &pmm);
|
||||
}
|
||||
|
||||
static void* _alloc(__attribute__((unused)) void* ctx, size_t len) {
|
||||
Allocator* alloc = NULL;
|
||||
|
||||
if (len <= 8) {
|
||||
alloc = &slabs[0].base;
|
||||
} else if (len <= 16) {
|
||||
alloc = &slabs[1].base;
|
||||
} else if (len <= 32) {
|
||||
alloc = &slabs[2].base;
|
||||
} else if (len <= 64) {
|
||||
alloc = &slabs[3].base;
|
||||
} else if (len <= 128) {
|
||||
alloc = &slabs[4].base;
|
||||
} else if (len <= 256) {
|
||||
alloc = &slabs[5].base;
|
||||
} else {
|
||||
Allocator pmm = pmm_allocator();
|
||||
alloc = &pmm;
|
||||
}
|
||||
|
||||
return alloc->alloc(alloc, len);
|
||||
}
|
||||
|
||||
static void _free(__attribute__((unused)) void* ctx, void* ptr, size_t len) {
|
||||
Allocator* alloc = NULL;
|
||||
|
||||
if (len <= 8) {
|
||||
alloc = &slabs[0].base;
|
||||
} else if (len <= 16) {
|
||||
alloc = &slabs[1].base;
|
||||
} else if (len <= 32) {
|
||||
alloc = &slabs[2].base;
|
||||
} else if (len <= 64) {
|
||||
alloc = &slabs[3].base;
|
||||
} else if (len <= 128) {
|
||||
alloc = &slabs[4].base;
|
||||
} else if (len <= 256) {
|
||||
alloc = &slabs[5].base;
|
||||
} else {
|
||||
Allocator pmm = pmm_allocator();
|
||||
alloc = &pmm;
|
||||
}
|
||||
|
||||
alloc->free(alloc, ptr, len);
|
||||
}
|
||||
|
||||
Allocator kmalloc_allocator(void) {
|
||||
return (Allocator){
|
||||
.alloc = _alloc,
|
||||
.free = _free,
|
||||
.realloc = NULL,
|
||||
};
|
||||
}
|
7
src/kernel/kmalloc/mod.h
Normal file
7
src/kernel/kmalloc/mod.h
Normal file
|
@ -0,0 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <traits/allocator.h>
|
||||
|
||||
void kmalloc_init(void);
|
||||
|
||||
Allocator kmalloc_allocator(void);
|
|
@ -0,0 +1 @@
|
|||
#pragma once
|
|
@ -48,3 +48,14 @@ void* memcpy(void* s1, void const* s2, size_t n) {
|
|||
|
||||
return s1;
|
||||
}
|
||||
|
||||
char* strncpy(char* s1, char const* s2, size_t n) {
|
||||
size_t i = 0;
|
||||
|
||||
while (s2[i] != 0 && i < n) {
|
||||
s1[i] = s2[i];
|
||||
i++;
|
||||
}
|
||||
|
||||
return s1;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,11 @@
|
|||
#include <stddef.h>
|
||||
|
||||
size_t strlen(char const* s);
|
||||
|
||||
void* memset(void* s, int c, size_t n);
|
||||
|
||||
int strncmp(char const* s1, char const* s2, size_t n);
|
||||
|
||||
char* strncpy(char* s1, char const* s2, size_t n);
|
||||
|
||||
void* memcpy(void* s1, void const* s2, size_t n);
|
||||
|
|
7
src/kernel/libs/libc/unistd.c
Normal file
7
src/kernel/libs/libc/unistd.c
Normal file
|
@ -0,0 +1,7 @@
|
|||
#include <hal>
|
||||
|
||||
#include "unistd.h"
|
||||
|
||||
int getpagesize(void) {
|
||||
return page_size();
|
||||
}
|
3
src/kernel/libs/libc/unistd.h
Normal file
3
src/kernel/libs/libc/unistd.h
Normal file
|
@ -0,0 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
int getpagesize(void);
|
|
@ -4,6 +4,7 @@
|
|||
#include <logger>
|
||||
#include <string.h>
|
||||
|
||||
#include "base/mod.h"
|
||||
#include "mod.h"
|
||||
|
||||
static PmmBitmap bitmap = {0};
|
||||
|
@ -50,6 +51,13 @@ void pmm_init(void) {
|
|||
if (record.tag == HANDOVER_FREE && record.size >= bitmap.len) {
|
||||
debug$("Bitmap base: %p", record.start);
|
||||
bitmap.bitmap = (uint8_t*)record.start;
|
||||
|
||||
handover_append(handover(), (HandoverRecord){
|
||||
.tag = HANDOVER_RESERVED,
|
||||
.start = record.start,
|
||||
.size = bitmap.len,
|
||||
});
|
||||
|
||||
record.start += bitmap.len;
|
||||
record.size -= bitmap.len;
|
||||
break;
|
||||
|
@ -109,3 +117,27 @@ PhysObj pmm_alloc(size_t len) {
|
|||
void pmm_free(PhysObj obj) {
|
||||
pmm_mark_free(obj.base, obj.len);
|
||||
}
|
||||
|
||||
// === ALLOCATOR ===
|
||||
|
||||
static void* _alloc(__attribute__((unused)) void* ctx, size_t len) {
|
||||
PhysObj obj = pmm_alloc(len);
|
||||
if (obj.len == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return hal_mmap_l2h(obj.base);
|
||||
}
|
||||
|
||||
static void _free(__attribute__((unused)) void* ctx, void* ptr, size_t len) {
|
||||
PhysObj obj = {.base = (uintptr_t)hal_mmap_h2l((uintptr_t)ptr), .len = len};
|
||||
pmm_free(obj);
|
||||
}
|
||||
|
||||
Allocator pmm_allocator(void) {
|
||||
return (Allocator){
|
||||
.alloc = _alloc,
|
||||
.free = _free,
|
||||
.realloc = NULL,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <traits/allocator.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
@ -25,3 +26,7 @@ struct pmm_alloc_param {
|
|||
PhysObj pmm_alloc(size_t pages);
|
||||
|
||||
void pmm_init(void);
|
||||
|
||||
void pmm_free(PhysObj obj);
|
||||
|
||||
Allocator pmm_allocator(void);
|
||||
|
|
6
src/kernel/sched/manifest.json
Normal file
6
src/kernel/sched/manifest.json
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1",
|
||||
"type": "lib",
|
||||
"id": "sched",
|
||||
"requires": []
|
||||
}
|
7
src/kernel/sched/mod.c
Normal file
7
src/kernel/sched/mod.c
Normal file
|
@ -0,0 +1,7 @@
|
|||
#include "mod.h"
|
||||
|
||||
static size_t pid = 0;
|
||||
|
||||
size_t sched_next_pid(void) {
|
||||
return pid++;
|
||||
}
|
7
src/kernel/sched/mod.h
Normal file
7
src/kernel/sched/mod.h
Normal file
|
@ -0,0 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
void sched_init(void);
|
||||
|
||||
size_t sched_next_pid(void);
|
6
src/kernel/task/manifest.json
Normal file
6
src/kernel/task/manifest.json
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1",
|
||||
"type": "lib",
|
||||
"id": "task",
|
||||
"requires": ["sched"]
|
||||
}
|
23
src/kernel/task/mod.c
Normal file
23
src/kernel/task/mod.c
Normal file
|
@ -0,0 +1,23 @@
|
|||
#include <helpers/math.h>
|
||||
#include <sched>
|
||||
#include <string.h>
|
||||
|
||||
#include "mod.h"
|
||||
|
||||
TaskError task_new(char const* name, HalPage* page_table, uintptr_t ip, Allocator* alloc) {
|
||||
Task* task = alloc->alloc(alloc, sizeof(Task));
|
||||
|
||||
if (task == NULL) {
|
||||
return TASK_COULDNT_ALLOC;
|
||||
}
|
||||
|
||||
if (page_table == NULL) {
|
||||
return TASK_PAGE_TABLE_NULL;
|
||||
}
|
||||
|
||||
task->pid = sched_next_pid();
|
||||
task->page_table = page_table;
|
||||
strncpy(task->name, name, min$(strlen(name), TASK_NAME_LIMIT - 1));
|
||||
|
||||
return TASK_OK;
|
||||
}
|
25
src/kernel/task/mod.h
Normal file
25
src/kernel/task/mod.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
#pragma once
|
||||
|
||||
#include <hal>
|
||||
#include <helpers/errors.h>
|
||||
#include <stddef.h>
|
||||
#include <traits/allocator.h>
|
||||
|
||||
#define TASK_NAME_LIMIT (256)
|
||||
|
||||
typedef struct {
|
||||
char name[TASK_NAME_LIMIT];
|
||||
size_t pid;
|
||||
HalPage* page_table;
|
||||
HalContext* context;
|
||||
} Task;
|
||||
|
||||
#define TASK_ERRORS(ERR) \
|
||||
ERR(TASK_OK, "Operation completed successfully") \
|
||||
ERR(TASK_COULDNT_ALLOC, "Couldn't allocate memory") \
|
||||
ERR(TASK_PAGE_TABLE_NULL, "The provided page table is NULL")
|
||||
|
||||
DECLARE_ERROR_ENUM(Task, TASK_ERRORS)
|
||||
DECLARE_ERROR_STRING(Task, TASK_ERRORS)
|
||||
|
||||
TaskError task_new(char const* name, HalPage* page_table, uintptr_t ip, Allocator* alloc);
|
|
@ -1,7 +1,8 @@
|
|||
#include "bump.h"
|
||||
#include <helpers/mem.h>
|
||||
#include <logger>
|
||||
|
||||
#include "bump.h"
|
||||
|
||||
static void* alloc(void* ctx, size_t len) {
|
||||
size_t aligned_len = len & 7 ? align_up$(len, 8) : len;
|
||||
|
||||
|
@ -17,7 +18,7 @@ static void* alloc(void* ctx, size_t len) {
|
|||
return (void*)ptr;
|
||||
}
|
||||
|
||||
static void free(void* ctx, __attribute__((unused)) void* ptr) {
|
||||
static void free(void* ctx, __attribute__((unused)) void* ptr, __attribute__((unused)) size_t len) {
|
||||
BumpAllocator* self = (BumpAllocator*)ctx;
|
||||
self->allocations--;
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1",
|
||||
"id": "heap",
|
||||
"id": "allocators",
|
||||
"type": "lib"
|
||||
}
|
91
src/libs/allocators/slab.c
Normal file
91
src/libs/allocators/slab.c
Normal file
|
@ -0,0 +1,91 @@
|
|||
#include <allocators/bump.h>
|
||||
#include <helpers/mem.h>
|
||||
#include <logger>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "slab.h"
|
||||
|
||||
static size_t page_amount(size_t size) {
|
||||
if (size <= 64) {
|
||||
return 64;
|
||||
} else if (size <= 128) {
|
||||
return 32;
|
||||
} else if (size <= 512) {
|
||||
return 16;
|
||||
} else if (size <= 1024) {
|
||||
return 8;
|
||||
} else {
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
static void* _alloc(void* ctx, __attribute__((unused)) size_t len) {
|
||||
SlabAllocator* alloc = (SlabAllocator*)ctx;
|
||||
if (alloc->root == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* ptr = (void*)(alloc->root->ptr + sizeof(Slab));
|
||||
alloc->root = alloc->root->next;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static void _free(void* ctx, void* ptr, __attribute__((unused)) size_t len) {
|
||||
SlabAllocator* alloc = (SlabAllocator*)ctx;
|
||||
Slab* free = (Slab*)((uintptr_t)ptr - sizeof(Slab));
|
||||
|
||||
if (free->ptr + sizeof(Slab) != (uintptr_t)ptr) {
|
||||
error$("Invalid free %p != %p", free->ptr, ptr);
|
||||
return;
|
||||
}
|
||||
|
||||
Slab* slab = alloc->root;
|
||||
|
||||
while (1) {
|
||||
if (slab->next == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
slab = slab->next;
|
||||
}
|
||||
|
||||
slab->next = free;
|
||||
}
|
||||
|
||||
SlabAllocator slab_create(uintptr_t size, Allocator* page_alloc) {
|
||||
size_t n_page = page_amount(size + sizeof(Slab));
|
||||
void* page = page_alloc->alloc(page_alloc, n_page * getpagesize());
|
||||
|
||||
if (page == NULL) {
|
||||
return (SlabAllocator){0};
|
||||
}
|
||||
|
||||
size_t sz = align_up$(sizeof(Slab) + size, sizeof(void*));
|
||||
BumpAllocator bump = bump_allocator_create(page, n_page * getpagesize());
|
||||
Slab* root = bump.base.alloc(&bump, sz);
|
||||
root->ptr = (uintptr_t)root;
|
||||
|
||||
Slab* slab = root;
|
||||
|
||||
while (1) {
|
||||
void* ptr = bump.base.alloc(&bump, sz);
|
||||
|
||||
if (ptr == NULL) {
|
||||
slab->next = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
slab->next = ptr;
|
||||
slab->next->ptr = (uintptr_t)ptr;
|
||||
slab = slab->next;
|
||||
}
|
||||
|
||||
return (SlabAllocator){
|
||||
.base = {
|
||||
.alloc = _alloc,
|
||||
.free = _free,
|
||||
.realloc = 0,
|
||||
},
|
||||
.root = root,
|
||||
};
|
||||
}
|
18
src/libs/allocators/slab.h
Normal file
18
src/libs/allocators/slab.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <traits/allocator.h>
|
||||
|
||||
#define PAGE_SIZE 4096
|
||||
|
||||
typedef struct _slab {
|
||||
uintptr_t ptr;
|
||||
struct _slab* next;
|
||||
} Slab;
|
||||
|
||||
typedef struct {
|
||||
Allocator base;
|
||||
Slab* root;
|
||||
} SlabAllocator;
|
||||
|
||||
SlabAllocator slab_create(uintptr_t size, Allocator* page_alloc);
|
|
@ -1,10 +1,7 @@
|
|||
#include <helpers/mem.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "handover/base/mod.h"
|
||||
#include "logger/mod.h"
|
||||
#include "mod.h"
|
||||
|
||||
static DTBNode* dtb_root = NULL;
|
||||
|
|
18
src/libs/helpers/errors.h
Normal file
18
src/libs/helpers/errors.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
#pragma once
|
||||
|
||||
#define ENUM_ITEM(name, msg) name,
|
||||
#define STRINGIFY(name, msg) #msg,
|
||||
|
||||
#define DECLARE_ERROR_ENUM(PREFIX, LIST) \
|
||||
typedef enum { \
|
||||
LIST(ENUM_ITEM) \
|
||||
} PREFIX##Error;
|
||||
|
||||
#define DECLARE_ERROR_STRING(PREFIX, LIST) \
|
||||
__attribute__((used)) static const char* PREFIX##ErrorStrings[] = { \
|
||||
LIST(STRINGIFY) \
|
||||
}; \
|
||||
\
|
||||
inline static char const* PREFIX##ErrorString(PREFIX##Error err) { \
|
||||
return PREFIX##ErrorStrings[err]; \
|
||||
}
|
5
src/libs/helpers/math.h
Normal file
5
src/libs/helpers/math.h
Normal file
|
@ -0,0 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#define min$(x, y) ((x) < (y) ? (x) : (y))
|
||||
|
||||
#define max$(x, y) ((x) > (y) ? (x) : (y))
|
|
@ -5,5 +5,5 @@
|
|||
typedef struct {
|
||||
void* (*alloc)(void* ctx, size_t len);
|
||||
void* (*realloc)(void* ctx, void* ptr, size_t len);
|
||||
void (*free)(void* ctx, void* ptr);
|
||||
void (*free)(void* ctx, void* ptr, size_t len);
|
||||
} Allocator;
|
||||
|
|
Loading…
Add table
Reference in a new issue