1
0
Fork 0
mirror of https://github.com/tailix/libclayer.git synced 2024-11-20 11:06:24 -05:00

Remove generic types, free list, memmap

This commit is contained in:
Alex Kotov 2022-12-25 13:34:21 +04:00
parent 2a5b57aaac
commit 9f3fa6497a
Signed by: kotovalexarian
GPG key ID: 553C0EBBEB5D5F08
19 changed files with 1 additions and 1236 deletions

View file

@ -93,7 +93,6 @@ jobs:
- without: 'io'
- without: 'ntoa'
dependencies: '--without-units'
- without: 'memmap'
steps:
- uses: actions/checkout@v2
- name: autogen

View file

@ -35,11 +35,7 @@ endif
libkernaux_la_LDFLAGS = -version-info @PACKAGE_VERSION_SO@
libkernaux_la_LIBADD =
libkernaux_la_SOURCES = \
src/generic/display.c \
src/generic/malloc.c \
src/generic/mutex.c \
src/runtime.c
libkernaux_la_SOURCES = src/runtime.c
########
# libc #
@ -80,15 +76,9 @@ endif
if WITH_ELF
libkernaux_la_SOURCES += src/elf.c
endif
if WITH_FREE_LIST
libkernaux_la_SOURCES += src/free_list.c
endif
if WITH_MBR
libkernaux_la_SOURCES += src/mbr.c
endif
if WITH_MEMMAP
libkernaux_la_SOURCES += src/memmap.c
endif
if WITH_NTOA
libkernaux_la_SOURCES += src/ntoa.c
endif

View file

@ -43,19 +43,13 @@ zero). Work-in-progress APIs can change at any time.
* [Runtime environment](/include/kernaux/runtime.h) (*non-breaking since* **0.7.0**)
* [Macros](/include/kernaux/macro.h) (*non-breaking since* **0.6.0**)
* Stack trace *(planned)*
* Generic types
* [Display](/include/kernaux/generic/display.h) (*non-breaking since* **0.7.0**)
* [Memory allocator](/include/kernaux/generic/malloc.h) (*non-breaking since* **0.5.0**)
* [Mutex](/include/kernaux/generic/mutex.h) (*non-breaking since* **0.5.0**)
* Algorithms
* [Free list memory allocator](/include/kernaux/free_list.h) (*non-breaking since* **0.5.0**)
* [Page Frame Allocator](/include/kernaux/pfa.h) (*work in progress*)
* Data formats
* [ELF](/include/kernaux/elf.h) (*work in progress*)
* [MBR](/include/kernaux/mbr.h) (*work in progress*)
* Utilities
* [Measurement units utils](/include/kernaux/units.h) (*work in progress*)
* [Memory map](/include/kernaux/memmap.h) (*non-breaking since* **0.7.0**)
* Usual functions
* [itoa/ftoa replacement](/include/kernaux/ntoa.h) (*non-breaking since* **0.4.0**)
* libc replacement (*work in progress*)
@ -140,8 +134,6 @@ explicitly included, use `--without-all`.
* `--with[out]-arch-riscv64` - architecture riscv64
* `--with[out]-arch-x86-64` - architecture x86-64
* `--with[out]-asm` - kernel assembler helpers
* `--with[out]-free-list` - free list memory allocator
* `--with[out]-memmap` - memory map
* `--with[out]-ntoa` - itoa/ftoa

View file

@ -67,9 +67,7 @@ AC_ARG_WITH( [arch-riscv64], AS_HELP_STRING([--without-arch-riscv64], [wit
AC_ARG_WITH( [arch-x86-64], AS_HELP_STRING([--without-arch-x86-64], [without architecture x86-64]))
AC_ARG_WITH( [asm], AS_HELP_STRING([--without-asm], [without kernel assembler helpers]))
AC_ARG_WITH( [elf], AS_HELP_STRING([--without-elf], [without ELF utils]))
AC_ARG_WITH( [free-list], AS_HELP_STRING([--without-free-list], [without free list memory allocator]))
AC_ARG_WITH( [mbr], AS_HELP_STRING([--without-mbr], [without MBR utils]))
AC_ARG_WITH( [memmap], AS_HELP_STRING([--without-memmap], [without memory map]))
AC_ARG_WITH( [ntoa], AS_HELP_STRING([--without-ntoa], [without itoa/ftoa]))
AC_ARG_WITH( [pfa], AS_HELP_STRING([--without-pfa], [without Page Frame Allocator]))
AC_ARG_WITH( [units], AS_HELP_STRING([--without-units], [without measurement units utils]))
@ -105,9 +103,7 @@ if test -z "$with_arch_riscv64"; then with_arch_riscv64=no; fi
if test -z "$with_arch_x86_64"; then with_arch_x86_64=no; fi
if test -z "$with_asm"; then with_asm=no; fi
if test -z "$with_elf"; then with_elf=no; fi
if test -z "$with_free_list"; then with_free_list=no; fi
if test -z "$with_mbr"; then with_mbr=no; fi
if test -z "$with_memmap"; then with_memmap=no; fi
if test -z "$with_ntoa"; then with_ntoa=no; fi
if test -z "$with_pfa"; then with_pfa=no; fi
if test -z "$with_units"; then with_units=no; fi
@ -144,9 +140,7 @@ AS_IF([test "$with_arch_riscv64" = no ], [with_arch_riscv64=no], [wit
AS_IF([test "$with_arch_x86_64" = no ], [with_arch_x86_64=no], [with_arch_x86_64=yes])
AS_IF([test "$with_asm" = no ], [with_asm=no], [with_asm=yes])
AS_IF([test "$with_elf" = no ], [with_elf=no], [with_elf=yes])
AS_IF([test "$with_free_list" = no ], [with_free_list=no], [with_free_list=yes])
AS_IF([test "$with_mbr" = no ], [with_mbr=no], [with_mbr=yes])
AS_IF([test "$with_memmap" = no ], [with_memmap=no], [with_memmap=yes])
AS_IF([test "$with_ntoa" = no ], [with_ntoa=no], [with_ntoa=yes])
AS_IF([test "$with_pfa" = no ], [with_pfa=no], [with_pfa=yes])
AS_IF([test "$with_units" = no ], [with_units=no], [with_units=yes])
@ -199,9 +193,7 @@ AM_CONDITIONAL([WITH_ARCH_RISCV64], [test "$with_arch_riscv64" = yes])
AM_CONDITIONAL([WITH_ARCH_X86_64], [test "$with_arch_x86_64" = yes])
AM_CONDITIONAL([WITH_ASM], [test "$with_asm" = yes])
AM_CONDITIONAL([WITH_ELF], [test "$with_elf" = yes])
AM_CONDITIONAL([WITH_FREE_LIST], [test "$with_free_list" = yes])
AM_CONDITIONAL([WITH_MBR], [test "$with_mbr" = yes])
AM_CONDITIONAL([WITH_MEMMAP], [test "$with_memmap" = yes])
AM_CONDITIONAL([WITH_NTOA], [test "$with_ntoa" = yes])
AM_CONDITIONAL([WITH_PFA], [test "$with_pfa" = yes])
AM_CONDITIONAL([WITH_UNITS], [test "$with_units" = yes])
@ -244,9 +236,7 @@ AS_IF([test "$with_arch_riscv64" = yes], [AC_DEFINE([WITH_ARCH_RISCV64],
AS_IF([test "$with_arch_x86_64" = yes], [AC_DEFINE([WITH_ARCH_X86_64], [1], [with architecture x86_64])])
AS_IF([test "$with_asm" = yes], [AC_DEFINE([WITH_ASM], [1], [with kernel assembler helpers])])
AS_IF([test "$with_elf" = yes], [AC_DEFINE([WITH_ELF], [1], [with ELF utils])])
AS_IF([test "$with_free_list" = yes], [AC_DEFINE([WITH_FREE_LIST], [1], [with free list memory allocator])])
AS_IF([test "$with_mbr" = yes], [AC_DEFINE([WITH_MBR], [1], [with MBR utils])])
AS_IF([test "$with_memmap" = yes], [AC_DEFINE([WITH_MEMMAP], [1], [with memory map])])
AS_IF([test "$with_ntoa" = yes], [AC_DEFINE([WITH_NTOA], [1], [with ntoa])])
AS_IF([test "$with_pfa" = yes], [AC_DEFINE([WITH_PFA], [1], [with Page Frame Allocator])])
AS_IF([test "$with_units", = yes], [AC_DEFINE([WITH_UNITS], [1], [with measurement units utils])])
@ -272,9 +262,7 @@ AS_IF([test "$with_arch_i386" = no], [AC_SUBST([comment_line_arch_i386], [
AS_IF([test "$with_arch_riscv64" = no], [AC_SUBST([comment_line_arch_riscv64], [//])])
AS_IF([test "$with_arch_x86_64" = no], [AC_SUBST([comment_line_arch_x86_64], [//])])
AS_IF([test "$with_elf" = no], [AC_SUBST([comment_line_elf], [//])])
AS_IF([test "$with_free_list" = no], [AC_SUBST([comment_line_free_list], [//])])
AS_IF([test "$with_mbr" = no], [AC_SUBST([comment_line_mbr], [//])])
AS_IF([test "$with_memmap" = no], [AC_SUBST([comment_line_memmap], [//])])
AS_IF([test "$with_ntoa" = no], [AC_SUBST([comment_line_ntoa], [//])])
AS_IF([test "$with_pfa" = no], [AC_SUBST([comment_line_pfa], [//])])
AS_IF([test "$with_units" = no], [AC_SUBST([comment_line_units], [//])])

View file

@ -10,15 +10,10 @@ nobase_include_HEADERS = \
kernaux/asm/x86_64.h \
kernaux/asm/x86.h \
kernaux/elf.h \
kernaux/free_list.h \
kernaux/generic/display.h \
kernaux/generic/malloc.h \
kernaux/generic/mutex.h \
kernaux/macro.h \
kernaux/macro/packing_end.run \
kernaux/macro/packing_start.run \
kernaux/mbr.h \
kernaux/memmap.h \
kernaux/ntoa.h \
kernaux/pfa.h \
kernaux/runtime.h \

View file

@ -7,13 +7,8 @@
#include <kernaux/arch/riscv64.h>
#include <kernaux/arch/x86_64.h>
#include <kernaux/elf.h>
#include <kernaux/free_list.h>
#include <kernaux/generic/display.h>
#include <kernaux/generic/malloc.h>
#include <kernaux/generic/mutex.h>
#include <kernaux/macro.h>
#include <kernaux/mbr.h>
#include <kernaux/memmap.h>
#include <kernaux/ntoa.h>
#include <kernaux/pfa.h>
#include <kernaux/runtime.h>

View file

@ -1,38 +0,0 @@
#ifndef KERNAUX_INCLUDED_FREE_LIST
#define KERNAUX_INCLUDED_FREE_LIST
#ifdef __cplusplus
extern "C" {
#endif
#include <kernaux/macro.h>
#include <kernaux/generic/malloc.h>
#include <kernaux/generic/mutex.h>
#include <stddef.h>
typedef struct KernAux_FreeList_Node {
void *KERNAUX_PRIVATE_FIELD(orig_ptr);
struct KernAux_FreeList_Node *KERNAUX_PRIVATE_FIELD(next);
struct KernAux_FreeList_Node *KERNAUX_PRIVATE_FIELD(prev);
size_t KERNAUX_PRIVATE_FIELD(size);
char *KERNAUX_PRIVATE_FIELD(block);
} *KernAux_FreeList_Node;
typedef struct KernAux_FreeList {
struct KernAux_Malloc malloc;
KernAux_Mutex KERNAUX_PRIVATE_FIELD(mutex);
KernAux_FreeList_Node KERNAUX_PRIVATE_FIELD(head);
} *KernAux_FreeList;
struct KernAux_FreeList KernAux_FreeList_create(KernAux_Mutex mutex);
void KernAux_FreeList_init(KernAux_FreeList free_list, KernAux_Mutex mutex);
void
KernAux_FreeList_add_zone(KernAux_FreeList free_list, void *ptr, size_t size);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -1,33 +0,0 @@
#ifndef KERNAUX_INCLUDED_MALLOC
#define KERNAUX_INCLUDED_MALLOC
#ifdef __cplusplus
extern "C" {
#endif
#include <kernaux/macro.h>
#include <stddef.h>
typedef void *(*KernAux_Malloc_Calloc) (void *malloc, size_t nmemb, size_t size);
typedef void (*KernAux_Malloc_Free) (void *malloc, void *ptr);
typedef void *(*KernAux_Malloc_Malloc) (void *malloc, size_t size);
typedef void *(*KernAux_Malloc_Realloc)(void *malloc, void *ptr, size_t size);
typedef const struct KernAux_Malloc {
KernAux_Malloc_Calloc KERNAUX_PROTECTED_FIELD(calloc);
KernAux_Malloc_Free KERNAUX_PROTECTED_FIELD(free);
KernAux_Malloc_Malloc KERNAUX_PROTECTED_FIELD(malloc);
KernAux_Malloc_Realloc KERNAUX_PROTECTED_FIELD(realloc);
} *KernAux_Malloc;
void *KernAux_Malloc_malloc (KernAux_Malloc malloc, size_t size);
void KernAux_Malloc_free (KernAux_Malloc malloc, void *ptr);
void *KernAux_Malloc_calloc (KernAux_Malloc malloc, size_t nmemb, size_t size);
void *KernAux_Malloc_realloc(KernAux_Malloc malloc, void *ptr, size_t size);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -1,25 +0,0 @@
#ifndef KERNAUX_INCLUDED_MUTEX
#define KERNAUX_INCLUDED_MUTEX
#ifdef __cplusplus
extern "C" {
#endif
#include <kernaux/macro.h>
typedef void (*KernAux_Mutex_Lock )(void *mutex);
typedef void (*KernAux_Mutex_Unlock)(void *mutex);
typedef const struct KernAux_Mutex {
KernAux_Mutex_Lock KERNAUX_PROTECTED_FIELD(lock);
KernAux_Mutex_Unlock KERNAUX_PROTECTED_FIELD(unlock);
} *KernAux_Mutex;
void KernAux_Mutex_lock (KernAux_Mutex mutex);
void KernAux_Mutex_unlock(KernAux_Mutex mutex);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -1,67 +0,0 @@
#ifndef KERNAUX_INCLUDED_MEMMAP
#define KERNAUX_INCLUDED_MEMMAP
#ifdef __cplusplus
extern "C" {
#endif
#include <kernaux/generic/display.h>
#include <kernaux/generic/malloc.h>
#include <kernaux/macro.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#define KERNAUX_MEMMAP_FREE(memmap) do { \
KernAux_Memmap_free(memmap); \
memmap = NULL; \
} while (0)
/*********
* Types *
*********/
typedef const struct KernAux_Memmap_Node {
uint64_t mem_start, mem_end, mem_size;
const char *tag;
const struct KernAux_Memmap_Node *next, *children;
} *KernAux_Memmap_Node;
typedef const struct KernAux_Memmap {
KernAux_Memmap_Node root_node;
KernAux_Malloc KERNAUX_PRIVATE_FIELD(malloc);
} *KernAux_Memmap;
typedef struct KernAux_Memmap_Builder {
KernAux_Memmap KERNAUX_PRIVATE_FIELD(memmap);
} *KernAux_Memmap_Builder;
/*************
* Functions *
*************/
KernAux_Memmap_Builder
KernAux_Memmap_Builder_new(KernAux_Malloc malloc);
KernAux_Memmap_Node
KernAux_Memmap_Builder_add(
KernAux_Memmap_Builder builder,
KernAux_Memmap_Node parent_node,
uint64_t mem_start,
uint64_t mem_size,
const char *tag
);
KernAux_Memmap
KernAux_Memmap_Builder_finish_and_free(KernAux_Memmap_Builder builder);
void KernAux_Memmap_free(KernAux_Memmap memmap);
void KernAux_Memmap_print(KernAux_Memmap memmap, KernAux_Display display);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -2,9 +2,7 @@
#define KERNAUX_INCLUDED_VERSION
@comment_line_elf@#define KERNAUX_VERSION_WITH_ELF
@comment_line_free_list@#define KERNAUX_VERSION_WITH_FREE_LIST
@comment_line_mbr@#define KERNAUX_VERSION_WITH_MBR
@comment_line_memmap@#define KERNAUX_VERSION_WITH_MEMMAP
@comment_line_ntoa@#define KERNAUX_VERSION_WITH_NTOA
@comment_line_pfa@#define KERNAUX_VERSION_WITH_PFA
@comment_line_units@#define KERNAUX_VERSION_WITH_UNITS

View file

@ -9,15 +9,10 @@ include/kernaux/asm/riscv64.h
include/kernaux/asm/x86.h
include/kernaux/asm/x86_64.h
include/kernaux/elf.h
include/kernaux/free_list.h
include/kernaux/generic/display.h
include/kernaux/generic/malloc.h
include/kernaux/generic/mutex.h
include/kernaux/macro.h
include/kernaux/macro/packing_end.run
include/kernaux/macro/packing_start.run
include/kernaux/mbr.h
include/kernaux/memmap.h
include/kernaux/ntoa.h
include/kernaux/pfa.h
include/kernaux/runtime.h

View file

@ -1,297 +0,0 @@
/**
* The code was inspired by the Embedded Artistry's libmemory.
*
* Copyright (c) 2017-2022 Embedded Artistry LLC
* Copyright (c) 2022 Alex Kotov
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "assert.h"
#include <kernaux/free_list.h>
#include <kernaux/generic/malloc.h>
#include <kernaux/generic/mutex.h>
#include <kernaux/macro.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#define NODE_HEADER_SIZE (offsetof(struct KernAux_FreeList_Node, block))
#define MIN_ZONE_SIZE (2 * NODE_HEADER_SIZE)
#define MIN_SPLIT_SIZE (NODE_HEADER_SIZE + 16)
#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 PTR_ALIGNMENT (sizeof(void*))
#define LOCK(free_list) \
do { \
if ((free_list)->mutex) { \
KernAux_Mutex_lock((free_list)->mutex); \
} \
} while (0)
#define UNLOCK(free_list) \
do { \
if ((free_list)->mutex) { \
KernAux_Mutex_unlock((free_list)->mutex); \
} \
} while (0)
static void KernAux_FreeList_free (void *malloc, void *ptr);
static void *KernAux_FreeList_malloc (void *malloc, size_t size);
static void *KernAux_FreeList_realloc(void *malloc, void *ptr, size_t size);
static void KernAux_FreeList_defrag(KernAux_FreeList free_list);
static void KernAux_FreeList_insert(
KernAux_FreeList free_list,
KernAux_FreeList_Node node,
KernAux_FreeList_Node prev,
KernAux_FreeList_Node next
);
static void KernAux_FreeList_remove(
KernAux_FreeList free_list,
KernAux_FreeList_Node node
);
struct KernAux_FreeList KernAux_FreeList_create(const KernAux_Mutex mutex)
{
struct KernAux_FreeList free_list;
KernAux_FreeList_init(&free_list, mutex);
return free_list;
}
void KernAux_FreeList_init(
const KernAux_FreeList free_list,
const KernAux_Mutex mutex
) {
KERNAUX_NOTNULL(free_list);
free_list->malloc.calloc = NULL;
free_list->malloc.free = KernAux_FreeList_free;
free_list->malloc.malloc = KernAux_FreeList_malloc;
free_list->malloc.realloc = KernAux_FreeList_realloc;
free_list->mutex = mutex;
free_list->head = NULL;
}
void KernAux_FreeList_add_zone(
const KernAux_FreeList free_list,
void *const ptr,
const size_t size
) {
KERNAUX_NOTNULL(free_list);
KERNAUX_NOTNULL(ptr);
KERNAUX_ASSERT(size >= MIN_ZONE_SIZE);
LOCK(free_list);
KernAux_FreeList_Node new_node =
(KernAux_FreeList_Node)ALIGN_UP((uintptr_t)ptr, PTR_ALIGNMENT);
new_node->orig_ptr = ptr;
new_node->size = size;
KernAux_FreeList_Node prev_node = NULL;
KernAux_FreeList_Node next_node;
KernAux_FreeList_Node last_node = NULL;
for (
KernAux_FreeList_Node item_node = free_list->head;
item_node;
item_node = item_node->next
) {
last_node = item_node;
if (item_node > new_node) {
next_node = item_node;
if (item_node->prev) prev_node = item_node->prev;
goto block_found;
}
}
prev_node = last_node;
next_node = NULL;
block_found:
KernAux_FreeList_insert(free_list, new_node, prev_node, next_node);
KernAux_FreeList_defrag(free_list);
UNLOCK(free_list);
}
void KernAux_FreeList_free(void *const malloc, void *const ptr)
{
const KernAux_FreeList free_list = malloc;
KERNAUX_NOTNULL(free_list);
KERNAUX_NOTNULL(ptr);
LOCK(free_list);
KernAux_FreeList_Node node =
KERNAUX_CONTAINER_OF(ptr, struct KernAux_FreeList_Node, block);
KernAux_FreeList_Node last_node = NULL;
for (
KernAux_FreeList_Node item_node = free_list->head;
item_node;
item_node = item_node->next
) {
last_node = item_node;
if (item_node > node) {
KernAux_FreeList_insert(
free_list,
node,
item_node->prev,
item_node
);
goto block_added;
}
}
KernAux_FreeList_insert(free_list, node, last_node, NULL);
block_added:
KernAux_FreeList_defrag(free_list);
UNLOCK(free_list);
}
void *KernAux_FreeList_malloc(void *const malloc, size_t size)
{
const KernAux_FreeList free_list = malloc;
KERNAUX_NOTNULL(free_list);
KERNAUX_ASSERT(size);
LOCK(free_list);
size = ALIGN_UP(size, PTR_ALIGNMENT);
KernAux_FreeList_Node node = NULL;
for (
KernAux_FreeList_Node item_node = free_list->head;
item_node;
item_node = item_node->next
) {
if (item_node->size - NODE_HEADER_SIZE >= size) {
node = item_node;
break;
}
}
if (node) {
// Can we split the block?
if (node->size - size >= MIN_SPLIT_SIZE) {
KernAux_FreeList_Node new_node =
(KernAux_FreeList_Node)(((uintptr_t)&node->block) + size);
KERNAUX_ASSERT(
((uintptr_t)new_node)
==
ALIGN_UP((uintptr_t)new_node, PTR_ALIGNMENT)
);
new_node->orig_ptr = new_node;
new_node->size = node->size - size - NODE_HEADER_SIZE;
node->size = NODE_HEADER_SIZE + size;
KernAux_FreeList_insert(free_list, new_node, node, node->next);
}
KernAux_FreeList_remove(free_list, node);
}
UNLOCK(free_list);
if (node) {
return &node->block;
} else {
return NULL;
}
}
void *KernAux_FreeList_realloc(
void *const malloc,
void *const old_ptr,
const size_t new_size
) {
const KernAux_FreeList free_list = malloc;
KERNAUX_NOTNULL(free_list);
KERNAUX_NOTNULL(old_ptr);
KERNAUX_ASSERT(new_size);
LOCK(free_list);
KernAux_FreeList_Node node =
KERNAUX_CONTAINER_OF(old_ptr, struct KernAux_FreeList_Node, block);
const size_t old_size = node->size - NODE_HEADER_SIZE;
void *new_ptr = KernAux_FreeList_malloc(free_list, new_size);
if (new_ptr) {
const size_t min_size = old_size < new_size ? old_size : new_size;
memcpy(new_ptr, old_ptr, min_size);
}
UNLOCK(free_list);
return new_ptr;
}
void KernAux_FreeList_defrag(const KernAux_FreeList free_list)
{
KERNAUX_NOTNULL(free_list);
for (
KernAux_FreeList_Node item_node = free_list->head;
item_node;
item_node = item_node->next
) {
const KernAux_FreeList_Node node = item_node->prev;
if (!node) continue;
if (((uintptr_t)node) + node->size != (uintptr_t)item_node->orig_ptr) {
continue;
}
node->size += item_node->size;
KernAux_FreeList_remove(free_list, item_node);
}
}
void KernAux_FreeList_insert(
const KernAux_FreeList free_list,
const KernAux_FreeList_Node node,
const KernAux_FreeList_Node prev,
const KernAux_FreeList_Node next
) {
KERNAUX_NOTNULL(free_list);
KERNAUX_NOTNULL(node);
KERNAUX_ASSERT(node != prev);
KERNAUX_ASSERT(node != next);
KERNAUX_ASSERT(!prev || prev->next == next);
KERNAUX_ASSERT(!next || next->prev == prev);
if (!prev) free_list->head = node;
node->next = next;
node->prev = prev;
if (node->next) node->next->prev = node;
if (node->prev) node->prev->next = node;
}
void KernAux_FreeList_remove(
const KernAux_FreeList free_list,
const KernAux_FreeList_Node node
) {
KERNAUX_NOTNULL(free_list);
KERNAUX_NOTNULL(node);
KERNAUX_ASSERT(!node->next || node->next->prev == node);
KERNAUX_ASSERT(!node->prev || node->prev->next == node);
if (free_list->head == node) free_list->head = node->next;
if (node->next) node->next->prev = node->prev;
if (node->prev) node->prev->next = node->next;
}

View file

@ -1,68 +0,0 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "../assert.h"
#include <kernaux/generic/malloc.h>
#include <stddef.h>
#include <string.h>
void *KernAux_Malloc_calloc(KernAux_Malloc malloc, size_t nmemb, size_t size)
{
KERNAUX_NOTNULL(malloc);
// Common implementation
const size_t total_size = nmemb * size;
if (!total_size) return NULL;
if (total_size / nmemb != size) return NULL;
// Inherited implementation
if (malloc->calloc) return malloc->calloc((void*)malloc, nmemb, size);
// Default implementation
void *const ptr = KernAux_Malloc_malloc(malloc, total_size);
if (ptr) memset(ptr, 0, total_size);
return ptr;
}
void KernAux_Malloc_free(KernAux_Malloc malloc, void *ptr)
{
KERNAUX_NOTNULL(malloc);
KERNAUX_ASSERT(malloc->free);
// Common implementation
if (!ptr) return;
// Inherited implementation
malloc->free((void*)malloc, ptr);
}
void *KernAux_Malloc_malloc(KernAux_Malloc malloc, size_t size)
{
KERNAUX_NOTNULL(malloc);
KERNAUX_ASSERT(malloc->malloc);
// Common implementation
if (!size) return NULL;
// Inherited implementation
return malloc->malloc((void*)malloc, size);
}
void *KernAux_Malloc_realloc(KernAux_Malloc malloc, void *ptr, size_t size)
{
KERNAUX_NOTNULL(malloc);
KERNAUX_ASSERT(malloc->realloc);
// Common implementation
if (!ptr) return KernAux_Malloc_malloc(malloc, size);
if (!size) {
KernAux_Malloc_free(malloc, ptr);
return NULL;
}
// Inherited implementation
return malloc->realloc((void*)malloc, ptr, size);
}

View file

@ -1,23 +0,0 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "../assert.h"
#include <kernaux/generic/mutex.h>
void KernAux_Mutex_lock(const KernAux_Mutex mutex)
{
KERNAUX_NOTNULL(mutex);
KERNAUX_ASSERT(mutex->lock);
mutex->lock((void*)mutex);
}
void KernAux_Mutex_unlock(const KernAux_Mutex mutex)
{
KERNAUX_NOTNULL(mutex);
KERNAUX_ASSERT(mutex->unlock);
mutex->unlock((void*)mutex);
}

View file

@ -1,258 +0,0 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "assert.h"
#include <kernaux/generic/display.h>
#include <kernaux/generic/malloc.h>
#include <kernaux/macro.h>
#include <kernaux/memmap.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
static void free_node(KernAux_Malloc malloc, struct KernAux_Memmap_Node *node);
static void print_nodes(
KernAux_Memmap_Node node,
KernAux_Display display,
unsigned indentation
);
KernAux_Memmap_Builder
KernAux_Memmap_Builder_new(const KernAux_Malloc malloc)
{
KERNAUX_NOTNULL(malloc);
struct KernAux_Memmap_Builder *const builder =
KernAux_Malloc_malloc(malloc, sizeof(*builder));
if (!builder) {
return NULL;
}
struct KernAux_Memmap *const memmap =
KernAux_Malloc_malloc(malloc, sizeof(*memmap));
if (!memmap) {
KernAux_Malloc_free(malloc, builder);
return NULL;
}
struct KernAux_Memmap_Node *const root_node =
KernAux_Malloc_malloc(malloc, sizeof(*root_node));
if (!root_node) {
KernAux_Malloc_free(malloc, memmap);
KernAux_Malloc_free(malloc, builder);
return NULL;
}
*root_node = (struct KernAux_Memmap_Node){
.mem_start = 0x0,
.mem_end = 0xffffffffffffffff, // 2**64 - 1
.mem_size = 0xffffffffffffffff, // 2**64 - 1
.tag = NULL,
.next = NULL,
.children = NULL,
};
*memmap = (struct KernAux_Memmap){
.malloc = malloc,
.root_node = root_node,
};
*builder = (struct KernAux_Memmap_Builder){
.memmap = memmap,
};
return builder;
}
KernAux_Memmap_Node KernAux_Memmap_Builder_add(
const KernAux_Memmap_Builder builder,
KernAux_Memmap_Node parent_node,
const uint64_t mem_start,
const uint64_t mem_size,
const char *tag
) {
KERNAUX_NOTNULL(builder);
KERNAUX_ASSERT(builder->memmap);
KERNAUX_ASSERT(builder->memmap->root_node);
KERNAUX_ASSERT(builder->memmap->malloc);
if (mem_size == 0) goto fail;
char *tag_copy = NULL;
if (tag) {
tag_copy =
KernAux_Malloc_malloc(builder->memmap->malloc, strlen(tag) + 1);
if (!tag_copy) goto fail;
strcpy(tag_copy, tag);
}
struct KernAux_Memmap_Node *const new_node =
KernAux_Malloc_malloc(builder->memmap->malloc, sizeof(*new_node));
if (!new_node) goto fail_after_tag;
new_node->mem_start = mem_start;
new_node->mem_size = mem_size;
new_node->mem_end = mem_start + mem_size - 1;
new_node->tag = tag_copy;
if (!parent_node) {
parent_node = (struct KernAux_Memmap_Node*)builder->memmap->root_node;
}
if (new_node->mem_start < parent_node->mem_start ||
new_node->mem_end > parent_node->mem_end)
{
goto fail_after_new_node;
}
if (parent_node->children) {
for (
struct KernAux_Memmap_Node *curr_node =
(struct KernAux_Memmap_Node*)parent_node->children;
curr_node;
curr_node = (struct KernAux_Memmap_Node*)curr_node->next
) {
if (!curr_node->next ||
curr_node->next->mem_start > new_node->mem_start)
{
if (new_node->next &&
new_node->mem_end >= new_node->next->mem_start)
{
goto fail_after_new_node;
}
new_node->next = curr_node->next;
curr_node->next = new_node;
break;
}
}
} else {
new_node->next = NULL;
((struct KernAux_Memmap_Node*)parent_node)->children = new_node;
}
return new_node;
fail_after_new_node:
KernAux_Malloc_free(builder->memmap->malloc, new_node);
fail_after_tag:
if (tag_copy) KernAux_Malloc_free(builder->memmap->malloc, tag_copy);
fail:
return NULL;
}
KernAux_Memmap
KernAux_Memmap_Builder_finish_and_free(const KernAux_Memmap_Builder builder)
{
KERNAUX_NOTNULL(builder);
KERNAUX_ASSERT(builder->memmap);
KERNAUX_ASSERT(builder->memmap->root_node);
KERNAUX_ASSERT(builder->memmap->malloc);
KernAux_Memmap memmap = builder->memmap;
builder->memmap = NULL;
KernAux_Malloc_free(memmap->malloc, builder);
return memmap;
}
void KernAux_Memmap_free(const KernAux_Memmap memmap)
{
KERNAUX_NOTNULL(memmap);
KERNAUX_ASSERT(memmap->root_node);
KERNAUX_ASSERT(memmap->malloc);
KERNAUX_ASSERT(memmap->root_node->next == NULL);
free_node(memmap->malloc, (struct KernAux_Memmap_Node*)memmap->root_node);
KernAux_Malloc malloc = memmap->malloc;
((struct KernAux_Memmap*)memmap)->root_node = NULL;
((struct KernAux_Memmap*)memmap)->malloc = NULL;
KernAux_Malloc_free(malloc, (void*)memmap);
}
void KernAux_Memmap_print(
const KernAux_Memmap memmap,
const KernAux_Display display
) {
KERNAUX_NOTNULL(memmap);
KERNAUX_ASSERT(memmap->root_node);
KERNAUX_ASSERT(memmap->malloc);
KERNAUX_ASSERT(memmap->root_node->next == NULL);
print_nodes(memmap->root_node, display, 0);
}
void free_node(
const KernAux_Malloc malloc,
struct KernAux_Memmap_Node *const node
) {
KERNAUX_NOTNULL(malloc);
KERNAUX_NOTNULL(node);
for (
struct KernAux_Memmap_Node *child_node =
(struct KernAux_Memmap_Node*)node->children;
child_node;
child_node = (struct KernAux_Memmap_Node*)child_node->next
) {
free_node(malloc, child_node);
}
if (node->tag) KernAux_Malloc_free(malloc, (void*)node->tag);
KernAux_Malloc_free(malloc, node);
}
#define PRINT(s) do { KernAux_Display_print (display, s); } while (0)
#define PRINTLN(s) do { KernAux_Display_println(display, s); } while (0)
#define PRINTLNF(format, ...) \
do { KernAux_Display_printlnf(display, format, __VA_ARGS__); } while (0)
#define INDENT do { \
for (unsigned index = 0; index < indentation; ++index) PRINT(" "); \
} while (0)
void print_nodes(
KernAux_Memmap_Node node,
const KernAux_Display display,
const unsigned indentation
) {
for (; node; node = node->next) {
INDENT;
PRINTLN("{");
KERNAUX_CAST_CONST(unsigned long long, mem_start, node->mem_start);
KERNAUX_CAST_CONST(unsigned long long, mem_size, node->mem_size);
KERNAUX_CAST_CONST(unsigned long long, mem_end, node->mem_end);
INDENT;
PRINTLNF(" u64 mem_start: 0x%llx", mem_start);
INDENT;
PRINTLNF(" u64 mem_size: %llu", mem_size);
INDENT;
PRINTLNF(" u64 mem_end: 0x%llx", mem_end);
INDENT;
if (node->tag) {
PRINTLNF(" char* tag: \"%s\"", node->tag);
} else {
PRINTLN(" char* tag: NULL");
}
if (node->children) {
INDENT;
PRINTLN(" struct* children: [");
print_nodes(node->children, display, indentation + 2);
INDENT;
PRINTLN(" ]");
} else {
INDENT;
PRINTLN(" struct* children: []");
}
INDENT;
PRINTLN("}");
}
}

1
tests/.gitignore vendored
View file

@ -1,6 +1,5 @@
/test_arch_i386
/test_elf
/test_free_list
/test_mbr
/test_ntoa
/test_ntoa_assert

View file

@ -28,18 +28,6 @@ test_elf_SOURCES = \
test_elf.c
endif
##################
# test_free_list #
##################
if WITH_FREE_LIST
TESTS += test_free_list
test_free_list_LDADD = $(top_builddir)/libkernaux.la
test_free_list_SOURCES = \
main.c \
test_free_list.c
endif
############
# test_mbr #
############

View file

@ -1,365 +0,0 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#define KERNAUX_ACCESS_PRIVATE
#include <kernaux/free_list.h>
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void test_default();
static void test_cross_zone_defrag();
static void test_hello_and_mrb_state();
static void test_calloc();
static void test_calloc_nomem();
static void test_calloc_overflow();
static void test_calloc_zero();
static void test_realloc_alloc();
static void test_realloc_free();
static void test_realloc_memcpy();
static void test_realloc_increase();
static void test_realloc_decrease();
static size_t nodes_count(KernAux_FreeList free_list);
static void print_nodes(KernAux_FreeList free_list);
static const char *const hello = "Hello, World!";
void test_main()
{
test_default();
test_cross_zone_defrag();
test_hello_and_mrb_state();
test_calloc();
test_calloc_nomem();
test_calloc_overflow();
test_calloc_zero();
test_realloc_alloc();
test_realloc_free();
test_realloc_memcpy();
test_realloc_increase();
test_realloc_decrease();
}
size_t nodes_count(const KernAux_FreeList free_list)
{
size_t nodes_count = 0;
for (
KernAux_FreeList_Node item_node = free_list->head;
item_node;
item_node = item_node->next
) {
++nodes_count;
}
return nodes_count;
}
void print_nodes(const KernAux_FreeList free_list)
{
printf("\n\n\n");
printf("========================================\n");
printf("free_list: %p\n", (void*)free_list);
printf("free_list->head: %p\n", (void*)free_list->head);
for (
KernAux_FreeList_Node item_node = free_list->head;
item_node;
item_node = item_node->next
) {
printf("----------------------------------------\n");
printf("item_node: %p\n", (void*)item_node);
printf("item_node->orig_ptr: %p\n", (void*)item_node->orig_ptr);
printf("item_node->next: %p\n", (void*)item_node->next);
printf("item_node->prev: %p\n", (void*)item_node->prev);
printf("&item_node->block: %p\n", (void*)&item_node->block);
printf("item_node->size: %lu\n", (unsigned long)item_node->size);
}
printf("========================================\n");
printf("\n\n\n");
}
void test_default()
{
char memory_block[1000];
struct KernAux_FreeList free_list = KernAux_FreeList_create(NULL);
KernAux_FreeList_add_zone(&free_list, memory_block, sizeof(memory_block));
char *const ptr1 = KernAux_Malloc_malloc(&free_list.malloc, 100);
assert(ptr1);
assert(ptr1 > memory_block);
assert(ptr1 < &memory_block[1000]);
char *const ptr2 = KernAux_Malloc_calloc(&free_list.malloc, 100, 1);
assert(ptr2);
assert(ptr2 > ptr1);
assert(ptr2 < &memory_block[1000]);
char *const ptr3 = KernAux_Malloc_calloc(&free_list.malloc, 1, 100);
assert(ptr3);
assert(ptr3 > ptr2);
assert(ptr3 < &memory_block[1000]);
char *const ptr4 = KernAux_Malloc_malloc(&free_list.malloc, 100);
assert(ptr4);
assert(ptr4 > ptr3);
assert(ptr4 < &memory_block[1000]);
KernAux_Malloc_free(&free_list.malloc, ptr2);
KernAux_Malloc_free(&free_list.malloc, ptr3);
char *const ptr5 = KernAux_Malloc_malloc(&free_list.malloc, 100);
assert(ptr5 == ptr2);
char *const ptr6 = KernAux_Malloc_calloc(&free_list.malloc, 10, 10);
assert(ptr6 == ptr3);
KernAux_Malloc_free(&free_list.malloc, ptr2);
KernAux_Malloc_free(&free_list.malloc, ptr3);
char *const ptr7 = KernAux_Malloc_malloc(&free_list.malloc, 200);
assert(ptr7 == ptr2);
}
void test_cross_zone_defrag()
{
char zone[1000];
struct KernAux_FreeList free_list = KernAux_FreeList_create(NULL);
KernAux_FreeList_add_zone(&free_list, &zone[0], 500);
KernAux_FreeList_add_zone(&free_list, &zone[500], 500);
assert(nodes_count(&free_list) == 1);
}
void test_hello_and_mrb_state()
{
char *const zone = malloc(1024 * 128); // 128 KiB
assert(zone);
struct KernAux_FreeList free_list = KernAux_FreeList_create(NULL);
printf("KernAux_FreeList_create(NULL) = %p\n", (void*)&free_list);
print_nodes(&free_list);
KernAux_FreeList_add_zone(&free_list, zone, 1024 * 128);
printf(
"KernAux_FreeList_add_zone(&free_list, zone = %p, 1024 * 128 = %i)\n",
(void*)zone,
1024 * 128
);
print_nodes(&free_list);
{
char *const str = KernAux_Malloc_malloc(&free_list.malloc, 100);
printf(
"KernAux_Malloc_malloc(&free_list.malloc, 100) = %p\n",
(void*)str
);
print_nodes(&free_list);
assert(str);
KernAux_Malloc_free(&free_list.malloc, str);
printf(
"KernAux_Malloc_free(&free_list.malloc, str = %p)\n",
(void*)str
);
print_nodes(&free_list);
}
{
char *const str =
KernAux_Malloc_realloc(&free_list.malloc, NULL, 100);
printf(
"KernAux_Malloc_realloc(&free_list.malloc, NULL, 100) = %p\n",
(void*)str
);
print_nodes(&free_list);
assert(str);
KernAux_Malloc_free(&free_list.malloc, str);
printf(
"KernAux_Malloc_free(&free_list.malloc, str = %p)\n",
(void*)str
);
print_nodes(&free_list);
}
{
char *const mrb = KernAux_Malloc_malloc(&free_list.malloc, 6356);
printf(
"KernAux_Malloc_malloc(&free_list.malloc, 6356) = %p\n",
(void*)mrb
);
print_nodes(&free_list);
assert(mrb);
KernAux_Malloc_free(&free_list.malloc, mrb);
printf(
"KernAux_Malloc_free(&free_list.malloc, mrb = %p)\n",
(void*)mrb
);
print_nodes(&free_list);
}
{
char *const mrb = KernAux_Malloc_realloc(&free_list.malloc, NULL, 6356);
printf(
"KernAux_Malloc_realloc(&free_list.malloc, NULL, 6356) = %p\n",
(void*)mrb
);
print_nodes(&free_list);
assert(mrb);
KernAux_Malloc_free(&free_list.malloc, mrb);
printf(
"KernAux_Malloc_free(&free_list.malloc, mrb = %p)\n",
(void*)mrb
);
print_nodes(&free_list);
}
free(zone);
}
void test_calloc()
{
char zone[1000];
struct KernAux_FreeList free_list = KernAux_FreeList_create(NULL);
KernAux_FreeList_add_zone(&free_list, zone, 1000);
char *const ptr = KernAux_Malloc_calloc(&free_list.malloc, 1, 900);
for (size_t index = 0; index < 900; ++index) {
assert(ptr[index] == 0);
}
KernAux_Malloc_free(&free_list.malloc, ptr);
}
void test_calloc_nomem()
{
char zone[1000];
struct KernAux_FreeList free_list = KernAux_FreeList_create(NULL);
KernAux_FreeList_add_zone(&free_list, zone, sizeof(zone));
void *const ptr = KernAux_Malloc_calloc(&free_list.malloc, 1, sizeof(zone));
assert(ptr == NULL);
}
void test_calloc_overflow()
{
char zone[1000];
struct KernAux_FreeList free_list = KernAux_FreeList_create(NULL);
KernAux_FreeList_add_zone(&free_list, zone, SIZE_MAX);
{
void *const ptr = KernAux_Malloc_calloc(&free_list.malloc, 2, SIZE_MAX);
assert(ptr == NULL);
}
{
void *const ptr = KernAux_Malloc_calloc(&free_list.malloc, SIZE_MAX, 2);
assert(ptr == NULL);
}
}
void test_calloc_zero()
{
char zone[1000];
struct KernAux_FreeList free_list = KernAux_FreeList_create(NULL);
KernAux_FreeList_add_zone(&free_list, zone, sizeof(zone));
void *const ptr1 = KernAux_Malloc_calloc(&free_list.malloc, 0, 900);
assert(ptr1 == NULL);
void *const ptr2 = KernAux_Malloc_calloc(&free_list.malloc, 900, 0);
assert(ptr2 == NULL);
}
void test_realloc_alloc()
{
char zone[1000];
struct KernAux_FreeList free_list = KernAux_FreeList_create(NULL);
KernAux_FreeList_add_zone(&free_list, zone, sizeof(zone));
void *const ptr = KernAux_Malloc_realloc(&free_list.malloc, NULL, 900);
assert(ptr != NULL);
}
void test_realloc_free()
{
char zone[1000];
struct KernAux_FreeList free_list = KernAux_FreeList_create(NULL);
KernAux_FreeList_add_zone(&free_list, zone, sizeof(zone));
void *const ptr1 = KernAux_Malloc_malloc(&free_list.malloc, 900);
assert(ptr1 != NULL);
void *const ptr2 = KernAux_Malloc_realloc(&free_list.malloc, ptr1, 0);
assert(ptr2 == NULL);
void *const ptr3 = KernAux_Malloc_malloc(&free_list.malloc, 900);
assert(ptr3 != NULL);
}
void test_realloc_memcpy()
{
char zone[1000];
struct KernAux_FreeList free_list = KernAux_FreeList_create(NULL);
KernAux_FreeList_add_zone(&free_list, zone, sizeof(zone));
char *const ptr1 = KernAux_Malloc_malloc(&free_list.malloc, 400);
assert(ptr1 != NULL);
memset(ptr1, 0, 400);
strcpy(ptr1, hello);
strcpy(&ptr1[400 - strlen(hello) - 1], hello);
char *const ptr2 = KernAux_Malloc_realloc(&free_list.malloc, ptr1, 400);
assert(ptr2 != NULL);
assert(strcmp(ptr2, hello) == 0);
assert(strcmp(&ptr2[400 - strlen(hello) - 1], hello) == 0);
}
void test_realloc_increase()
{
char zone[1000];
struct KernAux_FreeList free_list = KernAux_FreeList_create(NULL);
KernAux_FreeList_add_zone(&free_list, zone, sizeof(zone));
char *const ptr1 = KernAux_Malloc_malloc(&free_list.malloc, 300);
assert(ptr1 != NULL);
memset(ptr1, 0, 300);
strcpy(ptr1, hello);
strcpy(&ptr1[300 - strlen(hello) - 1], hello);
char *const ptr2 = KernAux_Malloc_realloc(&free_list.malloc, ptr1, 500);
assert(ptr2 != NULL);
assert(strcmp(ptr2, hello) == 0);
assert(strcmp(&ptr2[300 - strlen(hello) - 1], hello) == 0);
}
void test_realloc_decrease()
{
char zone[1000];
struct KernAux_FreeList free_list = KernAux_FreeList_create(NULL);
KernAux_FreeList_add_zone(&free_list, zone, sizeof(zone));
char *const ptr1 = KernAux_Malloc_malloc(&free_list.malloc, 500);
assert(ptr1 != NULL);
memset(ptr1, 0, 300);
strcpy(ptr1, hello);
strcpy(&ptr1[300 - strlen(hello) - 1], hello);
char *const ptr2 = KernAux_Malloc_realloc(&free_list.malloc, ptr1, 300);
assert(ptr2 != NULL);
assert(strcmp(ptr2, hello) == 0);
assert(strcmp(&ptr2[300 - strlen(hello) - 1], hello) == 0);
}