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:
parent
2a5b57aaac
commit
9f3fa6497a
19 changed files with 1 additions and 1236 deletions
1
.github/workflows/main.yml
vendored
1
.github/workflows/main.yml
vendored
|
@ -93,7 +93,6 @@ jobs:
|
|||
- without: 'io'
|
||||
- without: 'ntoa'
|
||||
dependencies: '--without-units'
|
||||
- without: 'memmap'
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: autogen
|
||||
|
|
12
Makefile.am
12
Makefile.am
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
12
configure.ac
12
configure.ac
|
@ -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], [//])])
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
297
src/free_list.c
297
src/free_list.c
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
258
src/memmap.c
258
src/memmap.c
|
@ -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
1
tests/.gitignore
vendored
|
@ -1,6 +1,5 @@
|
|||
/test_arch_i386
|
||||
/test_elf
|
||||
/test_free_list
|
||||
/test_mbr
|
||||
/test_ntoa
|
||||
/test_ntoa_assert
|
||||
|
|
|
@ -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 #
|
||||
############
|
||||
|
|
|
@ -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);
|
||||
}
|
Loading…
Reference in a new issue