[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [UNIKRAFT/LIBMIMALLOC PATCH v3] Initial port of mimalloc to Unikraft
The main tree patch will need to be rebased before merge. Otherwise looks good. Reviewed-by: Daniel Dinca <dincadaniel97@xxxxxxxxx>
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
|