[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |