mirror of
https://github.com/tailix/libkernaux.git
synced 2024-11-13 11:04:27 -05:00
Main: src/malloc.c: Implement malloc
This commit is contained in:
parent
fcc6574d01
commit
de58477551
5 changed files with 107 additions and 12 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -127,6 +127,7 @@
|
|||
/tests/test_cmdline_gen
|
||||
/tests/test_cmdline_gen.c
|
||||
/tests/test_elf
|
||||
/tests/test_malloc
|
||||
/tests/test_mbr
|
||||
/tests/test_memmap
|
||||
/tests/test_multiboot2_common_packing
|
||||
|
|
|
@ -5,10 +5,18 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
typedef struct KernAux_Malloc_Node {
|
||||
struct KernAux_Malloc_Node *next;
|
||||
bool free;
|
||||
size_t actual_size, user_size;
|
||||
char *block;
|
||||
} *KernAux_Malloc_Node;
|
||||
|
||||
typedef struct KernAux_Malloc {
|
||||
int foobar;
|
||||
KernAux_Malloc_Node head;
|
||||
} *KernAux_Malloc;
|
||||
|
||||
struct KernAux_Malloc KernAux_Malloc_create();
|
||||
|
|
62
src/malloc.c
62
src/malloc.c
|
@ -12,11 +12,15 @@
|
|||
#include <kernaux/malloc.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define ALIGN_MASK(align) ((align) - 1) // align should be a power of 2
|
||||
#define ALIGN_UP(val, align) (((val) + ALIGN_MASK(align)) & ~ALIGN_MASK(align))
|
||||
|
||||
#define MIN_MALLOC_SIZE (32) // 2**5
|
||||
#define PTR_ALIGNMENT (sizeof(void*)) // TODO: align node to this value
|
||||
|
||||
#define ALLOC_HEADER_SIZE (offsetof(struct KernAux_Malloc_Node, block))
|
||||
#define MIN_ALLOC_SIZE (ALLOC_HEADER_SIZE + 16)
|
||||
|
||||
struct KernAux_Malloc KernAux_Malloc_create()
|
||||
{
|
||||
|
@ -29,7 +33,7 @@ void KernAux_Malloc_init(const KernAux_Malloc malloc)
|
|||
{
|
||||
KERNAUX_ASSERT(malloc);
|
||||
|
||||
(void)malloc;
|
||||
malloc->head = NULL;
|
||||
}
|
||||
|
||||
void KernAux_Malloc_add_memory_block(
|
||||
|
@ -39,11 +43,17 @@ void KernAux_Malloc_add_memory_block(
|
|||
) {
|
||||
KERNAUX_ASSERT(malloc);
|
||||
KERNAUX_ASSERT(ptr);
|
||||
KERNAUX_ASSERT(size);
|
||||
KERNAUX_ASSERT(size >= 2 * sizeof(struct KernAux_Malloc_Node));
|
||||
|
||||
(void)malloc;
|
||||
(void)ptr;
|
||||
(void)size;
|
||||
KernAux_Malloc_Node new_node = ptr;
|
||||
new_node->free = true;
|
||||
new_node->actual_size = size;
|
||||
new_node->user_size = size - sizeof(struct KernAux_Malloc_Node);
|
||||
|
||||
// TODO: lock
|
||||
new_node->next = malloc->head;
|
||||
malloc->head = new_node;
|
||||
// TODO: unlock
|
||||
}
|
||||
|
||||
void *KernAux_Malloc_malloc(const KernAux_Malloc malloc, const size_t size)
|
||||
|
@ -51,19 +61,49 @@ void *KernAux_Malloc_malloc(const KernAux_Malloc malloc, const size_t size)
|
|||
KERNAUX_ASSERT(malloc);
|
||||
if (size == 0) return NULL;
|
||||
|
||||
const size_t actual_size = ALIGN_UP(size, MIN_MALLOC_SIZE);
|
||||
// Too large, let's not care about the case.
|
||||
if (actual_size < size) return NULL;
|
||||
KernAux_Malloc_Node node = NULL;
|
||||
void *ptr = NULL;
|
||||
|
||||
(void)malloc;
|
||||
// TODO: lock
|
||||
|
||||
return NULL;
|
||||
for (
|
||||
KernAux_Malloc_Node item_node = malloc->head;
|
||||
item_node;
|
||||
item_node = item_node->next
|
||||
) {
|
||||
if (item_node->free && item_node->user_size >= size) {
|
||||
node = item_node;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (node) {
|
||||
// Can we split the block?
|
||||
if (node->actual_size - size >= MIN_ALLOC_SIZE) {
|
||||
KernAux_Malloc_Node new_node =
|
||||
(KernAux_Malloc_Node)(((uintptr_t)&node->block) + size);
|
||||
new_node->free = true;
|
||||
new_node->actual_size = node->actual_size - size - ALLOC_HEADER_SIZE;
|
||||
new_node->user_size = node->user_size - size - ALLOC_HEADER_SIZE;
|
||||
new_node->next = node->next;
|
||||
node->next = new_node;
|
||||
}
|
||||
|
||||
node->free = false;
|
||||
ptr = &node->block;
|
||||
}
|
||||
|
||||
// TODO: unlock
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void KernAux_Malloc_free(const KernAux_Malloc malloc, void *const ptr)
|
||||
{
|
||||
KERNAUX_ASSERT(malloc);
|
||||
|
||||
// TODO: implement this
|
||||
|
||||
(void)malloc;
|
||||
(void)ptr;
|
||||
}
|
||||
|
|
|
@ -93,6 +93,16 @@ test_elf_LDADD = $(top_builddir)/libkernaux.la
|
|||
test_elf_SOURCES = test_elf.c
|
||||
endif
|
||||
|
||||
###############
|
||||
# test_malloc #
|
||||
###############
|
||||
|
||||
if WITH_MALLOC
|
||||
TESTS += test_malloc
|
||||
test_malloc_LDADD = $(top_builddir)/libkernaux.la
|
||||
test_malloc_SOURCES = test_malloc.c
|
||||
endif
|
||||
|
||||
############
|
||||
# test_mbr #
|
||||
############
|
||||
|
|
36
tests/test_malloc.c
Normal file
36
tests/test_malloc.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <kernaux/malloc.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
char memory_block[1000];
|
||||
struct KernAux_Malloc alloc = KernAux_Malloc_create();
|
||||
KernAux_Malloc_add_memory_block(&alloc, memory_block, sizeof(memory_block));
|
||||
|
||||
char *const ptr1 = KernAux_Malloc_malloc(&alloc, 100);
|
||||
assert(ptr1);
|
||||
assert(ptr1 > memory_block);
|
||||
assert(ptr1 < &memory_block[1000]);
|
||||
|
||||
char *const ptr2 = KernAux_Malloc_malloc(&alloc, 100);
|
||||
assert(ptr2);
|
||||
assert(ptr2 > ptr1);
|
||||
assert(ptr2 < &memory_block[1000]);
|
||||
|
||||
char *const ptr3 = KernAux_Malloc_malloc(&alloc, 100);
|
||||
assert(ptr3);
|
||||
assert(ptr3 > ptr2);
|
||||
assert(ptr3 < &memory_block[1000]);
|
||||
|
||||
char *const ptr4 = KernAux_Malloc_malloc(&alloc, 100);
|
||||
assert(ptr4);
|
||||
assert(ptr4 > ptr3);
|
||||
assert(ptr4 < &memory_block[1000]);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in a new issue