[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [UNIKRAFT/LIBTINYALLOC PATCH] Initial port of tinyalloc to Unikraft



Hi, Hugo.

I tested tinyalloc on linuxu and KVM, it works.

Why did you name the structure "struct tinyalloc", without the uk_
prefix as is the case with the other allocators (i.e. "struct
uk_bbpalloc" and "struct uk_allocregion").

When selecting tinyalloc in the configuration screen, the malloc
compatibility interface should also be automatically selected. It's not
obvious it has to be selected and one may miss it.

There's another comment inline.

Razvan

Hugo Lefeuvre <hugo.lefeuvre@xxxxxxxxx> writes:
> Signed-off-by: Hugo Lefeuvre <hugo.lefeuvre@xxxxxxxxx>
> ---
>  Config.uk                                          |  32 +++
>  Makefile.uk                                        |  73 +++++
>  glue.c                                             | 101 +++++++
>  include/uk/tinyalloc.h                             |  48 ++++
>  main-tree.patch                                    |  45 +++
>  .../0001-do-not-store-heap-info-statically.patch   | 312 
> +++++++++++++++++++++
>  6 files changed, 611 insertions(+)
>  create mode 100644 Config.uk
>  create mode 100644 Makefile.uk
>  create mode 100644 glue.c
>  create mode 100644 include/uk/tinyalloc.h
>  create mode 100644 main-tree.patch
>  create mode 100644 patches/0001-do-not-store-heap-info-statically.patch
>
> diff --git a/Config.uk b/Config.uk
> new file mode 100644
> index 0000000..4b9d127
> --- /dev/null
> +++ b/Config.uk
> @@ -0,0 +1,32 @@
> +menuconfig LIBTINYALLOC
> +        bool "tinyalloc - sequential fit, linked list based tiny allocator"
> +        default y
> +
> +if LIBTINYALLOC
> +     config LIBTINYALLOC_DISABLE_SPLIT
> +             bool "Disable block splitting"
> +             default n
> +             help
> +                     If splitting is enabled, split blocks according to split
> +                     threshold.
> +
> +     config LIBTINYALLOC_DISABLE_COMPACT
> +             bool "Disable block compaction"
> +             default n
> +             help
> +                     If compaction is enabled, sort blocks into the free
> +                     list, merge if appropriate. Otherwise blocks are just
> +                     added as new head of the free list.
> +
> +     config LIBTINYALLOC_HEAP_BLOCKS
> +             int "Number of available heap blocks"
> +             default 2048
> +
> +     config LIBTINYALLOC_SPLIT_THRESH
> +             int "Split threshold, in bytes"
> +             default 16
> +
> +     config LIBTINYALLOC_ALIGNMENT
> +             int "Standard allocation alignment, in bytes"
> +             default 8
> +endif
> diff --git a/Makefile.uk b/Makefile.uk
> new file mode 100644
> index 0000000..21aa8fe
> --- /dev/null
> +++ b/Makefile.uk
> @@ -0,0 +1,73 @@
> +#  libtinyalloc Makefile.uc
> +#
> +#  Authors: Hugo Lefeuvre <hugo.lefeuvre@xxxxxxxxx>
> +#
> +#  Copyright (c) 2020, NEC Europe Ltd., NEC Corporation. All rights reserved.
> +#
> +#  Redistribution and use in source and binary forms, with or without
> +#  modification, are permitted provided that the following conditions
> +#  are met:
> +#
> +#  1. Redistributions of source code must retain the above copyright
> +#     notice, this list of conditions and the following disclaimer.
> +#  2. Redistributions in binary form must reproduce the above copyright
> +#     notice, this list of conditions and the following disclaimer in the
> +#     documentation and/or other materials provided with the distribution.
> +#  3. Neither the name of the copyright holder nor the names of its
> +#     contributors may be used to endorse or promote products derived from
> +#     this software without specific prior written permission.
> +#
> +#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 
> IS"
> +#  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> +#  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> +#  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
> +#  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> +#  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
> +#  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
> +#  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> +#  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
> +#  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
> +#  POSSIBILITY OF SUCH DAMAGE.
> +
> +################################################################################
> +# Library registration
> +################################################################################
> +$(eval $(call addlib_s,libtinyalloc,$(CONFIG_LIBTINYALLOC)))
> +
> +################################################################################
> +# Sources
> +################################################################################
> +LIBTINYALLOC_VERSION=96450f32d80fe7d23f6aa5426046143e57801bc4
> +LIBTINYALLOC_URL=https://github.com/thi-ng/tinyalloc/archive/$(LIBTINYALLOC_VERSION).zip
> +LIBTINYALLOC_DIR=tinyalloc-$(LIBTINYALLOC_VERSION)
> +
> +LIBTINYALLOC_PATCHDIR=$(LIBTINYALLOC_BASE)/patches
> +$(eval $(call 
> fetch,libtinyalloc,$(LIBTINYALLOC_URL),$(LIBTINYALLOC_VERSION).zip))
> +$(eval $(call 
> patch,libtinyalloc,$(LIBTINYALLOC_PATCHDIR),$(LIBTINYALLOC_DIR)))
> +
> +################################################################################
> +# Helpers
> +################################################################################
> +LIBTINYALLOC=$(LIBTINYALLOC_ORIGIN)/$(LIBTINYALLOC_DIR)
> +
> +################################################################################
> +# Library includes
> +################################################################################
> +CINCLUDES-$(CONFIG_LIBTINYALLOC) += -I$(LIBTINYALLOC_BASE)     \
> +                                    -I$(LIBTINYALLOC_BASE)/include \
> +                                 -I$(LIBTINYALLOC)
> +
> +################################################################################
> +# Global flags
> +################################################################################
> +#LIBTINYALLOC_CFLAGS-y += -D_POSIX_SOURCE -D_GNU_SOURCE -D__GNU__
> +
> +################################################################################
> +# Glue code
> +################################################################################
> +LIBTINYALLOC_SRCS-y += $(LIBTINYALLOC_BASE)/glue.c
> +
> +################################################################################
> +# Sources
> +################################################################################
> +LIBTINYALLOC_SRCS-y += $(LIBTINYALLOC)/tinyalloc.c
> diff --git a/glue.c b/glue.c
> new file mode 100644
> index 0000000..9266e92
> --- /dev/null
> +++ b/glue.c
> @@ -0,0 +1,101 @@
> +/* SPDX-License-Identifier: BSD-3-Clause */
> +/*
> + * Authors: Hugo Lefeuvre <hugo.lefeuvre@xxxxxxxxx>
> + *
> + * Copyright (c) 2020, NEC Europe Ltd., NEC Corporation. All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + *
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + * 3. Neither the name of the copyright holder nor the names of its
> + *    contributors may be used to endorse or promote products derived from
> + *    this software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 
> IS"
> + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
> + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
> + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
> + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
> + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
> + * POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#include <uk/tinyalloc.h>
> +#include <uk/alloc_impl.h>
> +#include <string.h> /* for memset */
> +#include <tinyalloc.h>
> +
> +static void *uk_tinyalloc_malloc(struct uk_alloc *a, size_t size)
> +{
> +     struct tinyalloc *b;
> +
> +     b = (struct tinyalloc *)&a->priv;
> +     return ta_alloc(b, size);
> +}
> +
> +static void uk_tinyalloc_free(struct uk_alloc *a, void *ptr)
> +{
> +     struct tinyalloc *b;
> +
> +     b = (struct tinyalloc *)&a->priv;
> +     ta_free(b, ptr);
> +}
> +
> +/* initialization */
> +
> +struct uk_alloc *uk_tinyalloc_init(void *base, size_t len)
> +{
> +     struct uk_alloc *a;
> +     struct tinyalloc *b;
> +     size_t metalen;
> +
> +     /* TODO: This port does not support multiple memory regions yet. Because
> +      * of the multiboot layout, the first region might be a single page, so
> +      * we simply ignore it.
> +      */
> +     if (len <= __PAGE_SIZE)
> +             return NULL;
> +
> +     /* Allocate space for allocator descriptor */
> +     metalen = sizeof(*a) + sizeof(*b);
> +
> +     /* enough space for allocator available? */
> +     if (metalen > len) {
> +             uk_pr_err("Not enough space for allocator: %"__PRIsz
> +                       " B required but only %"__PRIuptr" B usable\n",
> +                       metalen, len);
> +             return NULL;
> +     }
> +
> +     /* store allocator metadata on the heap, just before the memory pool */
> +     a = (struct uk_alloc *)base;
> +     b = (struct tinyalloc *)&a->priv;
> +     memset(a, 0, metalen);
> +
> +     uk_pr_info("Initialize tinyalloc allocator @ 0x%" __PRIuptr ", len %"
> +                     __PRIsz"\n", (uintptr_t)a, len);
> +
> +     ta_init(b, base + metalen, base + len, CONFIG_LIBTINYALLOC_HEAP_BLOCKS,
> +             CONFIG_LIBTINYALLOC_SPLIT_THRESH,
> +             CONFIG_LIBTINYALLOC_ALIGNMENT);
> +
> +     if (!a) {
> +             uk_pr_err("Failed to allocate memory for uk_alloc 
> structure!\n");
> +             return NULL;
> +     }

Shouldn't this be if (!b)?

> +     uk_alloc_init_malloc_ifmalloc(a, uk_tinyalloc_malloc,
> +                                      uk_tinyalloc_free, NULL);
> +
> +     return a;
> +}
> diff --git a/include/uk/tinyalloc.h b/include/uk/tinyalloc.h
> new file mode 100644
> index 0000000..87290ed
> --- /dev/null
> +++ b/include/uk/tinyalloc.h
> @@ -0,0 +1,48 @@
> +/* SPDX-License-Identifier: BSD-3-Clause */
> +/*
> + * Authors: Hugo Lefeuvre <hugo.lefeuvre@xxxxxxxxx>
> + *
> + * Copyright (c) 2020, NEC Europe Ltd., NEC Corporation. All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + *
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + * 3. Neither the name of the copyright holder nor the names of its
> + *    contributors may be used to endorse or promote products derived from
> + *    this software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 
> IS"
> + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
> + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
> + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
> + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
> + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
> + * POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#ifndef __LIBTINYALLOC_H__
> +#define __LIBTINYALLOC_H__
> +
> +#include <uk/alloc.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +struct uk_alloc *uk_tinyalloc_init(void *base, size_t len);
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif /* __LIBTINYALLOC_H__ */
> diff --git a/main-tree.patch b/main-tree.patch
> new file mode 100644
> index 0000000..40bb096
> --- /dev/null
> +++ b/main-tree.patch
> @@ -0,0 +1,45 @@
> +From: Hugo Lefeuvre <hugo.lefeuvre@xxxxxxxxx>
> +Subject: Add tinyalloc entry to the menuconfig and initialize it
> +diff --git a/lib/ukboot/Config.uk b/lib/ukboot/Config.uk
> +index a888bc1c..694762fa 100644
> +--- a/lib/ukboot/Config.uk
> ++++ b/lib/ukboot/Config.uk
> +@@ -32,6 +32,16 @@ if LIBUKBOOT
> +               Satisfy allocation as fast as possible. No support for free().
> +               Refer to help in ukallocregion for more information.
> + 
> ++            config LIBUKBOOT_INITTINYALLOC
> ++            bool "tinyalloc"
> ++            select LIBTINYALLOC
> ++            help
> ++              Minimalist allocator implementation, meant for use in systems
> ++              with unmanaged linear memory such as WebAssembly or embedded
> ++              systems. tinyalloc is highly configurable and offers high
> ++              performance and reasonable memory usage when used and
> ++              configured appropriately.
> ++
> +             config LIBUKBOOT_NOALLOC
> +             bool "No memory allocator"
> + 
> +diff --git a/lib/ukboot/boot.c b/lib/ukboot/boot.c
> +index 4e749aa5..b8bf0a20 100644
> +--- a/lib/ukboot/boot.c
> ++++ b/lib/ukboot/boot.c
> +@@ -45,6 +45,8 @@
> + #include <uk/allocbbuddy.h>
> + #elif CONFIG_LIBUKBOOT_INITREGION
> + #include <uk/allocregion.h>
> ++#elif CONFIG_LIBUKBOOT_INITTINYALLOC
> ++#include <uk/tinyalloc.h>
> + #endif
> + #if CONFIG_LIBUKSCHED
> + #include <uk/sched.h>
> +@@ -233,6 +235,8 @@ void ukplat_entry(int argc, char *argv[])
> +                     a = uk_allocbbuddy_init(md.base, md.len);
> + #elif CONFIG_LIBUKBOOT_INITREGION
> +                     a = uk_allocregion_init(md.base, md.len);
> ++#elif CONFIG_LIBUKBOOT_INITTINYALLOC
> ++                    a = uk_tinyalloc_init(md.base, md.len);
> + #endif
> +             } else {
> +                     uk_alloc_addmem(a, md.base, md.len);
> diff --git a/patches/0001-do-not-store-heap-info-statically.patch 
> b/patches/0001-do-not-store-heap-info-statically.patch
> new file mode 100644
> index 0000000..fd7b953
> --- /dev/null
> +++ b/patches/0001-do-not-store-heap-info-statically.patch
> @@ -0,0 +1,312 @@
> +From: Hugo Lefeuvre <hugo.lefeuvre@xxxxxxxxx>
> +Subject: Adapt tinyalloc interface to Unikraft
> + - avoid statics: create a struct tinyalloc to store allocator metadata
> + - pass struct metadata as argument to allocation functions
> +diff -urNp tinyalloc-orig/tinyalloc.c tinyalloc-patched/tinyalloc.c
> +--- tinyalloc-orig/tinyalloc.c       2019-08-17 23:56:45.000000000 +0200
> ++++ tinyalloc-patched/tinyalloc.c    2020-06-30 10:34:24.945558078 +0200
> +@@ -9,36 +9,16 @@ extern void print_i(size_t);
> + #define print_i(X)
> + #endif
> + 
> +-typedef struct Block Block;
> +-
> +-struct Block {
> +-    void *addr;
> +-    Block *next;
> +-    size_t size;
> +-};
> +-
> +-typedef struct {
> +-    Block *free;   // first free block
> +-    Block *used;   // first used block
> +-    Block *fresh;  // first available blank block
> +-    size_t top;    // top free addr
> +-    Block *blocks;
> +-} Heap;
> +-
> +-static Heap *heap = NULL;
> +-static void *heap_limit = NULL;
> +-static size_t heap_split_thresh;
> +-static size_t heap_alignment;
> +-static size_t heap_max_blocks;
> +-
> + /**
> +  * If compaction is enabled, inserts block
> +  * into free list, sorted by addr.
> +  * If disabled, add block has new head of
> +  * the free list.
> +  */
> +-static void insert_block(Block *block) {
> +-#ifndef TA_DISABLE_COMPACT
> ++static void insert_block(struct tinyalloc *a, Block *block) {
> ++    Heap *heap = a->heap;
> ++
> ++#ifndef CONFIG_LIBTINYALLOC_DISABLE_COMPACT
> +     Block *ptr  = heap->free;
> +     Block *prev = NULL;
> +     while (ptr != NULL) {
> +@@ -66,8 +46,10 @@ static void insert_block(Block *block) {
> + #endif
> + }
> + 
> +-#ifndef TA_DISABLE_COMPACT
> +-static void release_blocks(Block *scan, Block *to) {
> ++#ifndef CONFIG_LIBTINYALLOC_DISABLE_COMPACT
> ++static void release_blocks(struct tinyalloc *a, Block *scan, Block *to) {
> ++    Heap *heap = a->heap;
> ++
> +     Block *scan_next;
> +     while (scan != to) {
> +         print_s("release");
> +@@ -81,7 +63,9 @@ static void release_blocks(Block *scan,
> +     }
> + }
> + 
> +-static void compact() {
> ++static void compact(struct tinyalloc *a) {
> ++    Heap *heap = a->heap;
> ++
> +     Block *ptr = heap->free;
> +     Block *prev;
> +     Block *scan;
> +@@ -103,7 +87,7 @@ static void compact() {
> +             ptr->size   = new_size;
> +             Block *next = prev->next;
> +             // make merged blocks available
> +-            release_blocks(ptr->next, prev->next);
> ++            release_blocks(a, ptr->next, prev->next);
> +             // relink
> +             ptr->next = next;
> +         }
> +@@ -112,30 +96,36 @@ static void compact() {
> + }
> + #endif
> + 
> +-bool ta_init(const void *base, const void *limit, const size_t heap_blocks, 
> const size_t split_thresh, const size_t alignment) {
> +-    heap = (Heap *)base;
> +-    heap_limit = limit;
> +-    heap_split_thresh = split_thresh;
> +-    heap_alignment = alignment;
> +-    heap_max_blocks = heap_blocks;
> ++void ta_init(struct tinyalloc *a, const void *base, const void *limit,
> ++             const size_t heap_blocks, const size_t split_thresh,
> ++             const size_t alignment) {
> ++    Heap *heap;
> ++
> ++    a->heap = (Heap *)base;
> ++    a->heap_limit = limit;
> ++    a->heap_split_thresh = split_thresh;
> ++    a->heap_alignment = alignment;
> ++    a->heap_max_blocks = heap_blocks;
> + 
> ++    heap = a->heap;
> +     heap->free   = NULL;
> +     heap->used   = NULL;
> ++    heap->blocks = (Block*) ((size_t)base + sizeof(Heap));
> +     heap->fresh  = heap->blocks;
> +     heap->top    = (size_t)base + sizeof(Heap) + heap_blocks * 
> sizeof(Block);
> +-    heap->blocks = base + sizeof(Heap);
> + 
> +     Block *block = heap->blocks;
> +-    size_t i     = heap_max_blocks - 1;
> ++    size_t i     = a->heap_max_blocks - 1;
> +     while (i--) {
> +         block->next = block + 1;
> +         block++;
> +     }
> +     block->next = NULL;
> +-    return true;
> + }
> + 
> +-bool ta_free(void *free) {
> ++void ta_free(struct tinyalloc *a, void *free) {
> ++    Heap *heap = a->heap;
> ++
> +     Block *block = heap->used;
> +     Block *prev  = NULL;
> +     while (block != NULL) {
> +@@ -145,25 +135,28 @@ bool ta_free(void *free) {
> +             } else {
> +                 heap->used = block->next;
> +             }
> +-            insert_block(block);
> +-#ifndef TA_DISABLE_COMPACT
> +-            compact();
> ++            insert_block(a, block);
> ++#ifndef CONFIG_LIBTINYALLOC_DISABLE_COMPACT
> ++            compact(a);
> + #endif
> +-            return true;
> ++            return;
> +         }
> +         prev  = block;
> +         block = block->next;
> +     }
> +-    return false;
> ++    return;
> + }
> + 
> +-static Block *alloc_block(size_t num) {
> ++static Block *alloc_block(struct tinyalloc *a, size_t num) {
> ++    Heap *heap = a->heap;
> ++
> +     Block *ptr  = heap->free;
> +     Block *prev = NULL;
> +     size_t top  = heap->top;
> +-    num         = (num + heap_alignment - 1) & -heap_alignment;
> ++    num         = (num + a->heap_alignment - 1) & - a->heap_alignment;
> +     while (ptr != NULL) {
> +-        const int is_top = ((size_t)ptr->addr + ptr->size >= top) && 
> ((size_t)ptr->addr + num <= heap_limit);
> ++        const int is_top = ((size_t)ptr->addr + ptr->size >= top)
> ++                    && ((size_t)ptr->addr + num <= a->heap_limit);
> +         if (is_top || ptr->size >= num) {
> +             if (prev != NULL) {
> +                 prev->next = ptr->next;
> +@@ -176,10 +169,10 @@ static Block *alloc_block(size_t num) {
> +                 print_s("resize top block");
> +                 ptr->size = num;
> +                 heap->top = (size_t)ptr->addr + num;
> +-#ifndef TA_DISABLE_SPLIT
> ++#ifndef CONFIG_LIBTINYALLOC_DISABLE_SPLIT
> +             } else if (heap->fresh != NULL) {
> +                 size_t excess = ptr->size - num;
> +-                if (excess >= heap_split_thresh) {
> ++                if (excess >= a->heap_split_thresh) {
> +                     ptr->size    = num;
> +                     Block *split = heap->fresh;
> +                     heap->fresh  = split->next;
> +@@ -187,9 +180,9 @@ static Block *alloc_block(size_t num) {
> +                     print_s("split");
> +                     print_i((size_t)split->addr);
> +                     split->size = excess;
> +-                    insert_block(split);
> +-#ifndef TA_DISABLE_COMPACT
> +-                    compact();
> ++                    insert_block(a, split);
> ++#ifndef CONFIG_LIBTINYALLOC_DISABLE_COMPACT
> ++                    compact(a);
> + #endif
> +                 }
> + #endif
> +@@ -199,10 +192,11 @@ static Block *alloc_block(size_t num) {
> +         prev = ptr;
> +         ptr  = ptr->next;
> +     }
> ++
> +     // no matching free blocks
> +     // see if any other blocks available
> +     size_t new_top = top + num;
> +-    if (heap->fresh != NULL && new_top <= heap_limit) {
> ++    if (heap->fresh != NULL && new_top <= (size_t)a->heap_limit) {
> +         ptr         = heap->fresh;
> +         heap->fresh = ptr->next;
> +         ptr->addr   = (void *)top;
> +@@ -212,11 +206,12 @@ static Block *alloc_block(size_t num) {
> +         heap->top   = new_top;
> +         return ptr;
> +     }
> ++
> +     return NULL;
> + }
> + 
> +-void *ta_alloc(size_t num) {
> +-    Block *block = alloc_block(num);
> ++void *ta_alloc(struct tinyalloc *a, size_t num) {
> ++    Block *block = alloc_block(a, num);
> +     if (block != NULL) {
> +         return block->addr;
> +     }
> +@@ -236,9 +231,9 @@ static void memclear(void *ptr, size_t n
> +     }
> + }
> + 
> +-void *ta_calloc(size_t num, size_t size) {
> ++void *ta_calloc(struct tinyalloc *a, size_t num, size_t size) {
> +     num *= size;
> +-    Block *block = alloc_block(num);
> ++    Block *block = alloc_block(a, num);
> +     if (block != NULL) {
> +         memclear(block->addr, num);
> +         return block->addr;
> +@@ -255,18 +250,21 @@ static size_t count_blocks(Block *ptr) {
> +     return num;
> + }
> + 
> +-size_t ta_num_free() {
> ++size_t ta_num_free(struct tinyalloc *a) {
> ++    Heap *heap = a->heap;
> +     return count_blocks(heap->free);
> + }
> + 
> +-size_t ta_num_used() {
> ++size_t ta_num_used(struct tinyalloc *a) {
> ++    Heap *heap = a->heap;
> +     return count_blocks(heap->used);
> + }
> + 
> +-size_t ta_num_fresh() {
> ++size_t ta_num_fresh(struct tinyalloc *a) {
> ++    Heap *heap = a->heap;
> +     return count_blocks(heap->fresh);
> + }
> + 
> +-bool ta_check() {
> +-    return heap_max_blocks == ta_num_free() + ta_num_used() + 
> ta_num_fresh();
> ++bool ta_check(struct tinyalloc *a) {
> ++    return a->heap_max_blocks == ta_num_free(a) + ta_num_used(a) + 
> ta_num_fresh(a);
> + }
> +diff -urNp tinyalloc-orig/tinyalloc.h tinyalloc-patched/tinyalloc.h
> +--- tinyalloc-orig/tinyalloc.h       2019-08-17 23:56:45.000000000 +0200
> ++++ tinyalloc-patched/tinyalloc.h    2020-06-30 10:38:59.734724059 +0200
> +@@ -1,12 +1,41 @@
> + #include <stdbool.h>
> + #include <stddef.h>
> + 
> +-bool ta_init(const void *base, const void *limit, const size_t heap_blocks, 
> const size_t split_thresh, const size_t alignment);
> +-void *ta_alloc(size_t num);
> +-void *ta_calloc(size_t num, size_t size);
> +-bool ta_free(void *ptr);
> +-
> +-size_t ta_num_free();
> +-size_t ta_num_used();
> +-size_t ta_num_fresh();
> +-bool ta_check();
> ++typedef struct Block Block;
> ++
> ++struct Block {
> ++    void *addr;
> ++    Block *next;
> ++    size_t size;
> ++};
> ++
> ++typedef struct {
> ++    Block *free;   // first free block
> ++    Block *used;   // first used block
> ++    Block *fresh;  // first available blank block
> ++    size_t top;    // top free addr
> ++    Block *blocks;
> ++} Heap;
> ++
> ++struct tinyalloc {
> ++    Heap *heap;
> ++    void *heap_limit;
> ++    size_t heap_split_thresh;
> ++    size_t heap_alignment;
> ++    size_t heap_max_blocks;
> ++};
> ++
> ++void ta_init(struct tinyalloc *a, const void *base, const void *limit,
> ++             const size_t heap_blocks, const size_t split_thresh,
> ++             const size_t alignment);
> ++
> ++void *ta_alloc(struct tinyalloc *a, size_t num);
> ++void *ta_calloc(struct tinyalloc *a, size_t num, size_t size);
> ++void  ta_free(struct tinyalloc *a, void *ptr);
> ++int   ta_posix_memalign(struct tinyalloc *a, void **memptr, size_t align,
> ++                    size_t size);
> ++
> ++size_t ta_num_free(struct tinyalloc *a);
> ++size_t ta_num_used(struct tinyalloc *a);
> ++size_t ta_num_fresh(struct tinyalloc *a);
> ++bool   ta_check(struct tinyalloc *a);



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.