# `mimalloc` issues ## Shared Library On macOS Mojave ```bash macOS Mojave version 10.14.5 ``` ```bash $ uname -a Darwin Kernel Version 18.6.0 ``` ### Add shared library (All of them works on Linux) ```cmake set (mi_sources src/stats.c src/os.c src/segment.c src/page.c src/alloc.c src/alloc-aligned.c src/heap.c src/options.c src/init.c) . . . add_library(mimalloc SHARED ${mi_sources}) ``` #### test(failed) ```bash $ ./dynamic-override [1] 72000 abort ./dynamic-override ``` --- ```cmake set (mi_sources SHARED src/stats.c src/os.c src/segment.c src/page.c src/alloc.c src/alloc-aligned.c src/heap.c src/options.c src/init.c) . . . add_library(mimalloc SHARED ${mi_sources}) ``` #### test(success) ```bash $ ./dynamic-override heap stats: peak total freed unit count elapsed: 0.000 s process: user: 0.001 s, system: 0.001 s, faults: 0, reclaims: 405, rss: 848.0 kb ``` --- ```cmake add_library(mimalloc SHARED src/stats.c src/os.c src/segment.c src/page.c src/alloc.c src/alloc-aligned.c src/heap.c src/options.c src/init.c) ``` #### test(success) ```bash $ ./dynamic-override heap stats: peak total freed unit count elapsed: 0.000 s process: user: 0.001 s, system: 0.001 s, faults: 0, reclaims: 415, rss: 868.0 kb ``` ## Add header to usr/local/include (both on linux and macos) (done) ```cmake install(FILES include/mimalloc.h DESTINATION ${mi_install_dir}/include) ``` `{$mi_install_dir}` = `lib/mimalloc-${mi_version}` but on [guide](https://github.com/microsoft/mimalloc#macos-linux-bsd-etc) > install the library and header files in /usr/local/lib and /usr/local/include which lead to ```bash $ gcc -o main -lmimalloc main.c main.c:3:10: fatal error: 'mimalloc.h' file not found #include <mimalloc.h> ^~~~~~~~~~~~ 1 error generated. ``` solution: ```cmake install(FILES include/mimalloc.h DESTINATION include) ``` [#89](https://github.com/microsoft/mimalloc/pull/89/files) ## IRI build with Mimalloc [Full report](https://hackmd.io/@hPMCWajOS-ORQdEEAQ04-w/HywEX8YNH) ### integrate with dltcollab iri (todo) * efficience comparison * updaet epic ## Refactor page_queue * refactor ` mi_page_queue_remove ` to ` mi_page_queue_remove_clear ` * add ` _mi_page_queue_remove ` * add ` _mi_page_clear ` ### _mi_page_queue_remove ```clike static void _mi_page_queue_remove(mi_page_queue_t* queue, mi_page_t* page) { if (page->prev != NULL) page->prev->next = page->next; if (page->next != NULL) page->next->prev = page->prev; if (page == queue->last) queue->last = page->prev; if (page == queue->first) { queue->first = page->next; // update first mi_heap_t* heap = page->heap; mi_assert_internal(mi_heap_contains_queue(heap, queue)); mi_heap_queue_first_update(heap,queue); } page->heap->page_count--; } ``` ### _mi_page_clear ```clike static void _mi_page_clear(mi_page_t* page) { page->next = NULL; page->prev = NULL; page->heap = NULL; page->flags.in_full = false; } ``` ### mi_page_queue_remove_clear ```clike static void mi_page_queue_remove_clear(mi_page_queue_t* queue, mi_page_t* page) { mi_assert_internal(page != NULL); mi_assert_expensive(mi_page_queue_contains(queue, page)); mi_assert_internal(page->block_size == queue->block_size || (page->block_size > MI_LARGE_SIZE_MAX && mi_page_queue_is_huge(queue)) || (page->flags.in_full && mi_page_queue_is_full(queue))); _mi_page_queue_remove(queue, page); _mi_page_clear(page); } ``` --- * refactor ` mi_page_queue_push ` * add ` _mi_page_queue_add ` * refactor ` mi_page_queue_enqueue_from ` * using ` _mi_page_queue_add ` ` _mi_page_queue_remove ` ### _mi_page_queue_add ```clike static void _mi_page_queue_add(mi_page_queue_t* queue,mi_page_t* page) { page->flags.in_full = mi_page_queue_is_full(queue); page->next = queue->first; page->prev = NULL; if (queue->first != NULL) { mi_assert_internal(queue->first->prev == NULL); queue->first->prev = page; } else { queue->last = page; } queue->first = page; } ``` ### mi_page_queue_push ```clike static void mi_page_queue_push(mi_heap_t* heap, mi_page_queue_t* queue, mi_page_t* page) { mi_assert_internal(page->heap == NULL); mi_assert_internal(!mi_page_queue_contains(queue, page)); mi_assert_internal(page->block_size == queue->block_size || (page->block_size > MI_LARGE_SIZE_MAX && mi_page_queue_is_huge(queue)) || (page->flags.in_full && mi_page_queue_is_full(queue))); page->heap = heap; heap->page_count++; _mi_page_queue_add(queue, page); // update direct mi_heap_queue_first_update(heap, queue); } ``` ### mi_page_queue_enqueue_from ```clike static void mi_page_queue_enqueue_from(mi_page_queue_t* to, mi_page_queue_t* from, mi_page_t* page) { mi_assert_internal(page != NULL); mi_assert_expensive(mi_page_queue_contains(from, page)); mi_assert_expensive(!mi_page_queue_contains(to, page)); mi_assert_internal(page->block_size == to->block_size || (page->block_size > MI_LARGE_SIZE_MAX && (mi_page_queue_is_huge(to) || mi_page_queue_is_full(to))) || (page->block_size == from->block_size && mi_page_queue_is_full(to))); _mi_page_queue_remove(from, page); mi_page_queue_push(page->heap, to, page); } ``` --- ### Breaking long assertion lines ### todo * add internal functions to internal function header file for instance `mimalloc-internal.h` ```clike // "page.c" void* _mi_malloc_generic(mi_heap_t* heap, size_t size) mi_attr_noexcept mi_attr_malloc; void _mi_page_retire(mi_page_t* page); // free the page if there are no other pages with many free blocks void _mi_page_unfull(mi_page_t* page); void _mi_page_free(mi_page_t* page, mi_page_queue_t* pq, bool force); // free the page void _mi_page_abandon(mi_page_t* page, mi_page_queue_t* pq); // abandon the page, to be picked up by another thread... void _mi_heap_delayed_free(mi_heap_t* heap); void _mi_page_use_delayed_free(mi_page_t* page, mi_delayed_t delay); size_t _mi_page_queue_append(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_queue_t* append); void _mi_deferred_free(mi_heap_t* heap, bool force); void _mi_page_free_collect(mi_page_t* page); void _mi_page_reclaim(mi_heap_t* heap, mi_page_t* page); // callback from segments size_t _mi_bin_size(uint8_t bin); // for stats uint8_t _mi_bin(size_t size); // for stats uint8_t _mi_bsr(uintptr_t x); // bit-scan-right, used on BSD in "os.c" ``` * rename queue ### reference [linux kernel list.h](https://github.com/torvalds/linux/blob/master/include/linux/list.h) [linux kernel coding style](https://www.kernel.org/doc/html/v4.10/process/coding-style.html#functions) ###### tags: `Cprogramming`