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

Re: [UNIKRAFT/LIBMIMALLOC PATCH] Initial port of mimalloc to Unikraft



Hi,

main-tree.patch is missing an `#include <uk/mimalloc.h>` in
`lib/ukboot/boot.c`. We might want to do a v2 just for that, but
waiting for the actual review to happen first.

Hugo

On Fri, 2020-06-26 at 10:27 +0200, Hugo Lefeuvre wrote:
> ---
>  Config.uk                                 |  16 ++
>  Makefile.uk                               |  95 ++++++++++++
>  README.md                                 |  13 ++
>  glue.c                                    | 240
> ++++++++++++++++++++++++++++++
>  include/uk/mimalloc.h                     |  49 ++++++
>  include/uk/mimalloc_impl.h                |  56 +++++++
>  main-tree.patch                           |  30 ++++
>  patches/adapt-to-unikraft-interface.patch | 160 ++++++++++++++++++++
>  8 files changed, 659 insertions(+)
>  create mode 100644 Config.uk
>  create mode 100644 Makefile.uk
>  create mode 100644 README.md
>  create mode 100644 glue.c
>  create mode 100644 include/uk/mimalloc.h
>  create mode 100644 include/uk/mimalloc_impl.h
>  create mode 100644 main-tree.patch
>  create mode 100644 patches/adapt-to-unikraft-interface.patch
> 
> diff --git a/Config.uk b/Config.uk
> new file mode 100644
> index 0000000..7ee8aee
> --- /dev/null
> +++ b/Config.uk
> @@ -0,0 +1,16 @@
> +menuconfig LIBMIMALLOC
> +     bool "mimalloc - a compact general purpose allocator with
> excellent performance"
> +     default n
> +     select LIBUKSCHED
> +     select LIBNEWLIBC
> +     select LIBPOSIX_SYSINFO
> +     select LIBPTHREAD_EMBEDDED
> +     select LIBUKALLOCREGION
> +if LIBMIMALLOC
> +     config MIMALLOC_DEBUG
> +             int "Mimalloc debug level"
> +             default 0
> +     config MIMALLOC_ASSERT
> +             bool "Mimalloc assertions"
> +             default n
> +endif
> diff --git a/Makefile.uk b/Makefile.uk
> new file mode 100644
> index 0000000..0289cb2
> --- /dev/null
> +++ b/Makefile.uk
> @@ -0,0 +1,95 @@
> +#  libmimalloc Makefile.uc
> +#
> +#  Authors: Hugo Lefeuvre <hugo.lefeuvre@xxxxxxxxx>
> +#
> +#
> +#  Copyright (c) 2017, 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,libmimalloc,$(CONFIG_LIBMIMALLOC)))
> +
> +####################################################################
> ############
> +# Sources
> +####################################################################
> ############
> +LIBMIMALLOC_VERSION=1.6.1
> +LIBMIMALLOC_URL=https://github.com/microsoft/mimalloc/archive/v$(LIB
> MIMALLOC_VERSION).zip
> +LIBMIMALLOC_DIR=mimalloc-$(LIBMIMALLOC_VERSION)
> +
> +LIBMIMALLOC_PATCHDIR=$(LIBMIMALLOC_BASE)/patches
> +$(eval $(call
> fetch,libmimalloc,$(LIBMIMALLOC_URL),v$(LIBMIMALLOC_VERSION).zip))
> +$(eval $(call
> patch,libmimalloc,$(LIBMIMALLOC_PATCHDIR),$(LIBMIMALLOC_DIR)))
> +
> +####################################################################
> ############
> +# Helpers
> +####################################################################
> ############
> +LIBMIMALLOC=$(LIBMIMALLOC_ORIGIN)/$(LIBMIMALLOC_DIR)
> +
> +####################################################################
> ############
> +# Library includes
> +####################################################################
> ############
> +
> +CINCLUDES-$(CONFIG_LIBMIMALLOC) += -I$(LIBMIMALLOC_BASE) \
> +                                   -I$(LIBMIMALLOC_BASE)/include \
> +                                   -I$(LIBMIMALLOC)/include
> +
> +####################################################################
> ############
> +# Global flags
> +####################################################################
> ############
> +LIBMIMALLOC_GLOBAL_FLAGS-$(CONFIG_MIMALLOC_ASSERT) += -DNDEBUG
> +LIBMIMALLOC_CFLAGS-y += -Wall -Wextra -Wno-unknown-pragmas
> -fvisibility=hidden \
> +                     -Wno-invalid-memory-model \
> +                     -D'MI_DEBUG=${CONFIG_MIMALLOC_DEBUG}'\
> +                     ${LIBMIMALLOC_GLOBAL_FLAGS-n}
> +
> +####################################################################
> ############
> +# Glue code
> +####################################################################
> ############
> +LIBMIMALLOC_SRCS-y += $(LIBMIMALLOC_BASE)/glue.c
> +
> +####################################################################
> ############
> +# Sources
> +####################################################################
> ############
> +LIBMIMALLOC_SRCS-y += $(LIBMIMALLOC)/src/stats.c
> +LIBMIMALLOC_SRCS-y += $(LIBMIMALLOC)/src/random.c
> +LIBMIMALLOC_SRCS-y += $(LIBMIMALLOC)/src/os.c
> +LIBMIMALLOC_SRCS-y += $(LIBMIMALLOC)/src/arena.c
> +LIBMIMALLOC_SRCS-y += $(LIBMIMALLOC)/src/region.c
> +LIBMIMALLOC_SRCS-y += $(LIBMIMALLOC)/src/segment.c
> +LIBMIMALLOC_SRCS-y += $(LIBMIMALLOC)/src/page.c
> +LIBMIMALLOC_SRCS-y += $(LIBMIMALLOC)/src/alloc.c
> +LIBMIMALLOC_SRCS-y += $(LIBMIMALLOC)/src/alloc-aligned.c
> +LIBMIMALLOC_SRCS-y += $(LIBMIMALLOC)/src/alloc-posix.c
> +#LIBMIMALLOC_SRCS-y += $(LIBMIMALLOC)/src/bitmap.inc.c
> +LIBMIMALLOC_SRCS-y += $(LIBMIMALLOC)/src/heap.c
> +LIBMIMALLOC_SRCS-y += $(LIBMIMALLOC)/src/options.c
> +LIBMIMALLOC_SRCS-y += $(LIBMIMALLOC)/src/init.c
> +#LIBMIMALLOC_SRCS-y += $(LIBMIMALLOC)/src/alloc-override.c
> +#LIBMIMALLOC_SRCS-y += $(LIBMIMALLOC)/src/page-queue.c
> diff --git a/README.md b/README.md
> new file mode 100644
> index 0000000..a43779c
> --- /dev/null
> +++ b/README.md
> @@ -0,0 +1,13 @@
> +Mimalloc for Unikraft
> +=====================
> +
> +This is the port of the Mimalloc [0] general-purpose memory
> allocator for
> +Unikraft as an external library.
> +
> +How to use this allocator in your unikernel application:
> +
> +- apply main-tree.patch to the main tree
> +- select "Mimalloc" in `ukboot > Default memory allocator`
> +- pass at least 256MiB of memory to the unikernel
> +
> +[0] https://microsoft.github.io/mimalloc/
> diff --git a/glue.c b/glue.c
> new file mode 100644
> index 0000000..d6f7d51
> --- /dev/null
> +++ b/glue.c
> @@ -0,0 +1,240 @@
> +/* 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/mimalloc_impl.h>
> +#include <uk/mimalloc.h>
> +#include <mimalloc.h>
> +#include <mimalloc-internal.h> // _mi_options_init()
> +#include <uk/alloc_impl.h>
> +#include <uk/print.h>
> +#include <uk/allocregion.h>
> +#include <uk/thread.h>       // uk_thread_current()
> +#include <uk/page.h> // round_pgup()
> +#include <uk/sched.h>        // uk_mimalloc_init_internal()
> +
> +/* Notes of Unikraft's Mimalloc port:
> + *
> + * 1. Minimum heap size required: 256MiB, which is the size of an
> arena.
> + *
> + * 2. Maximum number of Mimalloc instances:
> + *    Mimalloc's current code base relies strongly on static
> variables. Instead
> + *    of heavily patching it (and maintaining the patches) we simply
> restrict
> + *    the maximum number of Mimalloc instances to one.
> + *
> + * 3. Early boot time allocator:
> + *    Mimalloc can only be initialized after pthread. However the
> early boot
> + *    process including pthread's initialization itself requires a
> functioning
> + *    memory allocator. We solve this problem by relying on
> ukallocregion during
> + *    the early boot time. The transition to Mimalloc is triggered
> as soon as
> + *    _tls_ready() returns true. We expect that this won't cause
> significant
> + *    memory leak since memory allocated during EBT is typically not
> freed.
> + *
> + * 4. Transition EBT allocator -> Mimalloc:
> + *    We transition as soon as the TLS has been allocated and the
> %fs register
> + *    set. This is checked at every EBT allocation by inspecting
> + *    uk_thread_current()->prv which typically points to the thread
> local
> + *    storage. Since memory allocations might happen during
> Mimalloc's
> + *    initialization itself (e.g. calls to malloc() by pthread) the
> early boot
> + *    time allocator continues to satisfy requests until Mimalloc is
> ready
> + *    (after mi_process_load() returned).
> + */
> +
> +/* Minimum heap size (size of an arena)
> + * TODO: can Mimalloc be reconfigured/patched to lower/remove this
> limitation?
> + */
> +#define MIN_HEAP_SIZE 268435456L
> +
> +/* Rely on ukallocregion to satisfy boot-time allocations */
> +static struct uk_alloc *__region_alloc;
> +
> +/* make sure that the transition from boot-time allocation to
> Mimalloc is done
> + * only once: calls to malloc() during Mimalloc initialization
> should be
> + * satisfied using the boot-time allocator.
> + */
> +static int __initialized = 0;
> +
> +static inline int _tls_ready(void)
> +{
> +     /* Is the thread local storage ready? */
> +     struct uk_thread *current = uk_thread_current();
> +     return current && current->prv != NULL;
> +}
> +
> +/* boot-time malloc interface */
> +
> +static void uk_mimalloc_init_internal(struct uk_alloc *a);
> +
> +/* NOTE: not static, this is used in the mimalloc code base to
> request memory
> + * "from the OS"
> + */
> +void *uk_mimalloc_region_malloc(struct uk_alloc *a, size_t size)
> +{
> +     /* detect call from main thread to leave boot time mode */
> +     if (_tls_ready() && !__initialized) {
> +             uk_pr_debug("%s: leaving early boot-time allocation
> mode\n",
> +                        uk_thread_current()->name);
> +             __initialized = 1;
> +             uk_mimalloc_init_internal(a);
> +
> +             /* satisfy request using new malloc interface */
> +             return uk_malloc(a, size);
> +     }
> +
> +     uk_pr_debug("allocating %zu from region allocator\n", size);
> +
> +     return uk_malloc(__region_alloc, size);
> +}
> +
> +static int uk_mimalloc_region_posix_memalign(struct uk_alloc *a
> __unused, void **memptr,
> +                                     size_t align, size_t size)
> +{
> +     uk_pr_debug("allocating %zu aligned at %zu from region
> allocator\n", size,
> +                     align);
> +
> +     return uk_posix_memalign(__region_alloc, memptr, align,
> size);
> +}
> +
> +static void uk_mimalloc_region_free(struct uk_alloc *a __unused,
> void *ptr)
> +{
> +     uk_pr_info("attempt to free memory during early boot
> time\n");
> +
> +     return uk_free(__region_alloc, ptr);
> +}
> +
> +/* malloc interface */
> +
> +static void *uk_mimalloc_malloc(struct uk_alloc *a __unused, size_t
> size)
> +{
> +     return mi_malloc(size);
> +}
> +
> +static void uk_mimalloc_free(struct uk_alloc *a __unused, void *ptr)
> +{
> +     mi_free(ptr);
> +}
> +
> +static void *uk_mimalloc_realloc(struct uk_alloc *a __unused, void
> *ptr, size_t size)
> +{
> +     return mi_realloc(ptr, size);
> +}
> +
> +static void *uk_mimalloc_calloc(struct uk_alloc *a __unused, size_t
> nelem,
> +                      size_t elem_size)
> +{
> +     return mi_calloc(nelem, elem_size);
> +}
> +
> +static int uk_mimalloc_posix_memalign(struct uk_alloc *a __unused,
> void** p,
> +                            size_t alignment, size_t size)
> +{
> +     return mi_posix_memalign(p, alignment, size);
> +}
> +
> +static void *uk_mimalloc_memalign(struct uk_alloc *a __unused,
> size_t alignment,
> +                        size_t size)
> +{
> +     return mi_memalign(alignment, size);
> +}
> +
> +static void uk_mimalloc_init_internal(struct uk_alloc *a)
> +{
> +     mi_process_load();
> +
> +     /* rebind interface to actual malloc interface */
> +     (a)->malloc         = uk_mimalloc_malloc;
> +     (a)->calloc         = uk_mimalloc_calloc;
> +     (a)->realloc        = uk_mimalloc_realloc;
> +     (a)->posix_memalign = uk_mimalloc_posix_memalign;
> +     (a)->memalign       = uk_mimalloc_memalign;
> +     (a)->free           = uk_mimalloc_free;
> +
> +     /* delay this after interface rebinding to avoid using early
> boot
> +      * time memory.
> +      */
> +     _mi_options_init();
> +
> +     uk_pr_info("Successfully initialized Mimalloc\n");
> +}
> +
> +struct uk_alloc *uk_mimalloc_init(void *base, size_t len)
> +{
> +     struct uk_alloc *a;
> +     size_t metalen;
> +
> +     /* TODO: This Mimalloc 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;
> +
> +     if (__region_alloc) {
> +             uk_pr_err("mimalloc already initialized (max number
> of instances: 1)\n");
> +             return NULL;
> +     }
> +
> +     metalen = round_pgup(sizeof(*a));
> +
> +     /* 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;
> +     }
> +
> +     /* enough space to allocate arena? */
> +     if (len < MIN_HEAP_SIZE) {
> +             /* Note: we don't exit, but calls to malloc will
> return NULL. */
> +             uk_pr_err("Not enough space to allocate arena: %lu
> bytes required"
> +                       "but only %" __PRIsz" bytes usable\n",
> 268435456L, len);
> +     }
> +
> +     /* store allocator metadata on the heap, just before the
> memory pool */
> +     a = (struct uk_alloc *)base;
> +     uk_pr_info("Initialize mimalloc allocator (early boot time
> mode) @ 0x%"
> +                __PRIuptr ", len %"__PRIsz"\n", (uintptr_t)a,
> len);
> +
> +     /* register mimalloc *before* initializing the region
> allocator: in all cases
> +      * we want Mimalloc to be the default allocator.
> +      * FIXME: add uk_allocregion_init_noregister() that
> initializes a region
> +      * allocator without registering it.
> +      */
> +     uk_alloc_init_malloc(a, uk_mimalloc_region_malloc,
> uk_calloc_compat,
> +                             uk_realloc_compat,
> uk_mimalloc_region_free,
> +                             uk_mimalloc_region_posix_memalign,
> +                             uk_memalign_compat, NULL);
> +
> +     __region_alloc = uk_allocregion_init((void*)((uintptr_t)
> base + metalen),
> +                                             len - metalen);
> +
> +     return a;
> +}
> diff --git a/include/uk/mimalloc.h b/include/uk/mimalloc.h
> new file mode 100644
> index 0000000..8e465aa
> --- /dev/null
> +++ b/include/uk/mimalloc.h
> @@ -0,0 +1,49 @@
> +/* 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 __UKMIMALLOC_H__
> +#define __UKMIMALLOC_H__
> +
> +#include <uk/alloc.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/* allocator initialization */
> +struct uk_alloc *uk_mimalloc_init(void *base, size_t len);
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif /* __UKMIMALLOC_H__ */
> diff --git a/include/uk/mimalloc_impl.h b/include/uk/mimalloc_impl.h
> new file mode 100644
> index 0000000..9fc3fe9
> --- /dev/null
> +++ b/include/uk/mimalloc_impl.h
> @@ -0,0 +1,56 @@
> +/* 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.
> + */
> +
> +/*
> + * NOTE: These functions are not part of the public ukmimalloc API.
> + * This interface is used in the mimalloc code base to request
> memory
> + * "from the OS".
> + */
> +
> +#ifndef __UK_MIMALLOC_IMPL_H__
> +#define __UK_MIMALLOC_IMPL_H__
> +
> +#include <uk/alloc.h>
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/* region allocator */
> +
> +void *uk_mimalloc_region_malloc(struct uk_alloc *a, size_t size);
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif /* __UK_MIMALLOC_IMPL_H__ */
> diff --git a/main-tree.patch b/main-tree.patch
> new file mode 100644
> index 0000000..5c0d7f9
> --- /dev/null
> +++ b/main-tree.patch
> @@ -0,0 +1,30 @@
> +From: Hugo Lefeuvre <hugo.lefeuvre@xxxxxxxxx>
> +Subject: Add Mimalloc entry to the menuconfig and initialize it
> +diff --git a/lib/ukboot/Config.uk b/lib/ukboot/Config.uk
> +index a888bc1c..8c9a1dc2 100644
> +--- a/lib/ukboot/Config.uk
> ++++ b/lib/ukboot/Config.uk
> +@@ -32,6 +32,10 @@ if LIBUKBOOT
> +               Satisfy allocation as fast as possible. No
> support for free().
> +               Refer to help in ukallocregion for more
> information.
>
> ++            config LIBUKBOOT_INITMIMALLOC
> ++            bool "Mimalloc"
> ++            select LIBMIMALLOC
> ++
> +             config LIBUKBOOT_NOALLOC
> +             bool "No memory allocator"
>
> +diff --git a/lib/ukboot/boot.c b/lib/ukboot/boot.c
> +index 4e749aa5..06561b82 100644
> +--- a/lib/ukboot/boot.c
> ++++ b/lib/ukboot/boot.c
> +@@ -233,6 +233,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_INITMIMALLOC
> ++                    a = uk_mimalloc_init(md.base, md.len);
> + #endif
> +             } else {
> +                     uk_alloc_addmem(a, md.base, md.len);
> diff --git a/patches/adapt-to-unikraft-interface.patch
> b/patches/adapt-to-unikraft-interface.patch
> new file mode 100644
> index 0000000..8a41454
> --- /dev/null
> +++ b/patches/adapt-to-unikraft-interface.patch
> @@ -0,0 +1,160 @@
> +From: Hugo Lefeuvre <hugo.lefeuvre@xxxxxxxxx>
> +Subject: Adapt Mimalloc interface to Unikraft
> + - expose mi_process_load() since it is called in the glue code
> + - remove useless ATOMIC_VAR_INIT calls since they cause problems
> with newlib
> + - request memory from the OS via mi_unikraft_heap_grow(), which
> relies
> +   internally on uk_mimalloc_region_malloc(), our underlying region
> manager
> + - at the time where Mimalloc was ported, the support for memory
> protections
> +   by Unikraft was unclear, so it is here disabled. A future update
> of this
> +   port should address this.
> +diff -urNp mimalloc-orig/include/mimalloc.h mimalloc-
> patched/include/mimalloc.h
> +--- mimalloc-orig/include/mimalloc.h 2020-02-17
> 19:10:22.000000000 +0100
> ++++ mimalloc-patched/include/mimalloc.h      2020-06-24
> 10:16:31.439830260 +0200
> +@@ -144,6 +144,7 @@ mi_decl_export void mi_stats_print(void*
> + mi_decl_export void mi_stats_print_out(mi_output_fun* out, void*
> arg) mi_attr_noexcept;
>
> + mi_decl_export void mi_process_init(void)     mi_attr_noexcept;
> ++mi_decl_export void mi_process_load(void)     mi_attr_noexcept;
> + mi_decl_export void mi_thread_init(void)      mi_attr_noexcept;
> + mi_decl_export void mi_thread_done(void)      mi_attr_noexcept;
> + mi_decl_export void mi_thread_stats_print_out(mi_output_fun* out,
> void* arg) mi_attr_noexcept;
> +diff -urNp mimalloc-orig/src/init.c mimalloc-patched/src/init.c
> +--- mimalloc-orig/src/init.c 2020-02-17 19:10:22.000000000
> +0100
> ++++ mimalloc-patched/src/init.c      2020-06-24 10:16:31.443830218
> +0200
> +@@ -25,8 +25,8 @@ const mi_page_t _mi_page_empty = {
> +   0,       // used
> +   0,       // xblock_size
> +   NULL,    // local_free
> +-  ATOMIC_VAR_INIT(0), // xthread_free
> +-  ATOMIC_VAR_INIT(0), // xheap
> ++  0, // xthread_free
> ++  0, // xheap
> +   NULL, NULL
> + };
>
> +@@ -91,7 +91,7 @@ const mi_heap_t _mi_heap_empty = {
> +   NULL,
> +   MI_SMALL_PAGES_EMPTY,
> +   MI_PAGE_QUEUES_EMPTY,
> +-  ATOMIC_VAR_INIT(NULL),
> ++  NULL,
> +   0,                // tid
> +   0,                // cookie
> +   { 0, 0 },         // keys
> +@@ -125,7 +125,7 @@ mi_heap_t _mi_heap_main = {
> +   &tld_main,
> +   MI_SMALL_PAGES_EMPTY,
> +   MI_PAGE_QUEUES_EMPTY,
> +-  ATOMIC_VAR_INIT(NULL),
> ++  NULL,
> +   0,                // thread id
> +   0,                // initial cookie
> +   { 0, 0 },         // the key of the main heap can be fixed
> (unlike page keys that need to be secure!)
> +@@ -430,7 +430,7 @@ static void mi_allocator_done() {
> + #endif
>
> + // Called once by the process loader
> +-static void mi_process_load(void) {
> ++void mi_process_load(void) {
> +   mi_heap_main_init();
> +   #if defined(MI_TLS_RECURSE_GUARD)
> +   volatile mi_heap_t* dummy = _mi_heap_default; // access TLS to
> allocate it before setting tls_initialized to true;
> +@@ -438,7 +438,9 @@ static void mi_process_load(void) {
> +   #endif
> +   os_preloading = false;
> +   atexit(&mi_process_done);
> +-  _mi_options_init();
> ++  // delay _mi_options_init() after initialization as it allocates
> a lot of
> ++  // memory and we want to avoid doing that with the early boot
> time allocator
> ++  //_mi_options_init();
> +   mi_process_init();
> +   //mi_stats_reset();-
> +   if (mi_redirected) _mi_verbose_message("malloc is
> redirected.\n");
> +@@ -519,6 +521,8 @@ static void mi_process_done(void) {
> +   }
> +   static bool mi_initialized = _mi_process_init();
>
> ++#elif defined(CONFIG_LIBMIMALLOC)
> ++  // called by uk_init_mimalloc()
> + #elif defined(__GNUC__) || defined(__clang__)
> +   // GCC,Clang: use the constructor attribute
> +   static void __attribute__((constructor)) _mi_process_init(void) {
> +diff -urNp mimalloc-orig/src/os.c mimalloc-patched/src/os.c
> +--- mimalloc-orig/src/os.c   2020-02-17 19:10:22.000000000
> +0100
> ++++ mimalloc-patched/src/os.c        2020-06-24 14:44:56.745158608
> +0200
> +@@ -14,11 +14,14 @@ terms of the MIT license. A copy of the
>
> + #include <string.h>  // strerror
>
> ++#include <uk/mimalloc_impl.h> // uk_mimalloc_region_malloc
>
> + #if defined(_WIN32)
> + #include <windows.h>
> + #elif defined(__wasi__)
> + // stdlib.h is all we need, and has already been included in
> mimalloc.h
> ++#elif defined(CONFIG_LIBMIMALLOC)
> ++#include <unistd.h>    // sysconf
> + #else
> + #include <sys/mman.h>  // mmap
> + #include <unistd.h>    // sysconf
> +@@ -184,8 +187,8 @@ static bool mi_os_mem_free(void* addr, s
> +   bool err = false;
> + #if defined(_WIN32)
> +   err = (VirtualFree(addr, 0, MEM_RELEASE) == 0);
> +-#elif defined(__wasi__)
> +-  err = 0; // WebAssembly's heap cannot be shrunk
> ++#elif defined(__wasi__) || defined(CONFIG_LIBMIMALLOC)
> ++  err = 0; // WebAssembly's/Unikraft's heap cannot be shrunk
> + #else
> +   err = (munmap(addr, size) == -1);
> + #endif
> +@@ -272,6 +275,10 @@ static void* mi_wasm_heap_grow(size_t si
> +   }
> +   return (void*)aligned_base;
> + }
> ++#elif defined(CONFIG_LIBMIMALLOC)
> ++static void* mi_unikraft_heap_grow(size_t size, size_t
> try_alignment) {
> ++  return uk_mimalloc_region_malloc(NULL, size);
> ++}
> + #else
> + #define MI_OS_USE_MMAP
> + static void* mi_unix_mmapx(void* addr, size_t size, size_t
> try_alignment, int protect_flags, int flags, int fd) {
> +@@ -450,6 +457,9 @@ static void* mi_os_mem_alloc(size_t size
> +   #elif defined(__wasi__)
> +     *is_large = false;
> +     p = mi_wasm_heap_grow(size, try_alignment);
> ++  #elif defined(CONFIG_LIBMIMALLOC)
> ++    *is_large = false;
> ++    p = mi_unikraft_heap_grow(size, try_alignment);
> +   #else
> +     int protect_flags = (commit ? (PROT_WRITE | PROT_READ) :
> PROT_NONE);
> +     p = mi_unix_mmap(NULL, size, try_alignment, protect_flags,
> false, allow_large, is_large);
> +@@ -638,8 +648,8 @@ static bool mi_os_commitx(void* addr, si
> +     BOOL ok = VirtualFree(start, csize, MEM_DECOMMIT);
> +     err = (ok ? 0 : GetLastError());
> +   }
> +-  #elif defined(__wasi__)
> +-  // WebAssembly guests can't control memory protection
> ++  #elif defined(__wasi__) || defined(CONFIG_LIBMIMALLOC)
> ++  // Unikraft/WebAssembly guests can't control memory protection
> +   #elif defined(MAP_FIXED)
> +   if (!commit) {
> +     // use mmap with MAP_FIXED to discard the existing memory (and
> reduce commit charge)
> +@@ -714,7 +724,7 @@ static bool mi_os_resetx(void* addr, siz
> +     advice = MADV_DONTNEED;
> +     err = madvise(start, csize, advice);
> +   }
> +-#elif defined(__wasi__)
> ++#elif defined(__wasi__) || defined(CONFIG_LIBMIMALLOC)
> +   int err = 0;
> + #else
> +   int err = madvise(start, csize, MADV_DONTNEED);
> +@@ -768,7 +778,7 @@ static  bool mi_os_protectx(void* addr,
> +   DWORD oldprotect = 0;
> +   BOOL ok = VirtualProtect(start, csize, protect ? PAGE_NOACCESS :
> PAGE_READWRITE, &oldprotect);
> +   err = (ok ? 0 : GetLastError());
> +-#elif defined(__wasi__)
> ++#elif defined(__wasi__) || defined(CONFIG_LIBMIMALLOC)
> +   err = 0;
> + #else
> +   err = mprotect(start, csize, protect ? PROT_NONE : (PROT_READ |
> PROT_WRITE));



 


Rackspace

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