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

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



I added Hugo with his non-NEC e-mail address.

Razvan

Razvan Deaconescu <razvan.deaconescu@xxxxxxxxx> writes:
> 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®.