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

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



Signed-off-by: Hugo Lefeuvre <hugo.lefeuvre@xxxxxxxxx>
---
 Config.uk                                 |  16 ++
 Makefile.uk                               |  95 ++++++++++++
 README.md                                 |  13 ++
 glue.c                                    | 247 ++++++++++++++++++++++++++++++
 include/uk/mimalloc.h                     |  50 ++++++
 include/uk/mimalloc_impl.h                |  57 +++++++
 main-tree.patch                           |  39 +++++
 patches/adapt-to-unikraft-interface.patch | 160 +++++++++++++++++++
 8 files changed, 677 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..84f8aea
--- /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 "Debug level"
+               default 0
+       config MIMALLOC_ASSERT
+               bool "Enable assertions"
+               default n
+endif
diff --git a/Makefile.uk b/Makefile.uk
new file mode 100644
index 0000000..911ec7a
--- /dev/null
+++ b/Makefile.uk
@@ -0,0 +1,95 @@
+#  libmimalloc Makefile.uk
+#
+#  Authors: Hugo Lefeuvre <hugo.lefeuvre@xxxxxxxxx>
+#
+#  Copyright (c) 2020, NEC Laboratories Europe GmbH, 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$(LIBMIMALLOC_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..1d23ec5
--- /dev/null
+++ b/glue.c
@@ -0,0 +1,247 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Authors: Hugo Lefeuvre <hugo.lefeuvre@xxxxxxxxx>
+ *
+ * Copyright (c) 2020, NEC Laboratories Europe GmbH, 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;
+
+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..eadeae1
--- /dev/null
+++ b/include/uk/mimalloc.h
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Authors: Hugo Lefeuvre <hugo.lefeuvre@xxxxxxxxx>
+ *
+ * Copyright (c) 2020, NEC Laboratories Europe GmbH, 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 __LIBMIMALLOC_H__
+#define __LIBMIMALLOC_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 /* __LIBMIMALLOC_H__ */
diff --git a/include/uk/mimalloc_impl.h b/include/uk/mimalloc_impl.h
new file mode 100644
index 0000000..6b237cd
--- /dev/null
+++ b/include/uk/mimalloc_impl.h
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Authors: Hugo Lefeuvre <hugo.lefeuvre@xxxxxxxxx>
+ *
+ * Copyright (c) 2020, NEC Laboratories Europe GmbH, 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 __LIBMIMALLOC_IMPL_H__
+#define __LIBMIMALLOC_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 /* __LIBMIMALLOC_IMPL_H__ */
diff --git a/main-tree.patch b/main-tree.patch
new file mode 100644
index 0000000..40f0268
--- /dev/null
+++ b/main-tree.patch
@@ -0,0 +1,39 @@
+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 07139e2b..cfc306d7 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 "None"
+ 
+diff --git a/lib/ukboot/boot.c b/lib/ukboot/boot.c
+index 4e749aa5..a400749d 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_INITMIMALLOC
++#include <uk/mimalloc.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_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));
-- 
2.7.4




 


Rackspace

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