From ad2fa2bf6f737ba5b8d86716dc96375e8aa56db7 Mon Sep 17 00:00:00 2001 From: Danny Lin Date: Wed, 7 Apr 2021 01:32:19 -0700 Subject: [PATCH] Fix thread ID getter on Android ARM/AArch64 Android's Bionic libc stores the thread ID in TLS slot 1 instead of 0 on 32-bit ARM and AArch64. Slot 0 contains a pointer to the ELF DTV (Dynamic Thread Vector) instead, which is constant for each loaded DSO. Because mimalloc uses the thread ID to determine whether operations are thread-local or cross-thread (atomic), all threads having the same ID causes internal data structures to get corrupted quickly when multiple threads are using the allocator: mimalloc: assertion failed: at "external/mimalloc/src/page.c":563, mi_page_extend_free assertion: "page->local_free == NULL" mimalloc: assertion failed: at "external/mimalloc/src/page.c":74, mi_page_is_valid_init assertion: "page->used <= page->capacity" mimalloc: assertion failed: at "external/mimalloc/src/page.c":100, mi_page_is_valid_init assertion: "page->used + free_count == page->capacity" mimalloc: assertion failed: at "external/mimalloc/src/page.c":74, mi_page_is_valid_init assertion: "page->used <= page->capacity" Add support for Android's alternate TLS layout to fix the crashes in multi-threaded use cases. Fixes #376. --- include/mimalloc-internal.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/mimalloc-internal.h b/include/mimalloc-internal.h index 7160bc47..d1b8f107 100644 --- a/include/mimalloc-internal.h +++ b/include/mimalloc-internal.h @@ -751,6 +751,9 @@ static inline uintptr_t _mi_thread_id(void) mi_attr_noexcept { #if defined(__aarch64__) && defined(__APPLE__) // M1 // on macOS on the M1, slot 0 does not seem to work, so we fall back to portable C for now. See issue #354 return (uintptr_t)&_mi_heap_default; +#elif defined(__BIONIC__) && (defined(__arm__) || defined(__aarch64__)) + // on Android, slot 1 is the thread ID (pointer to pthread internal struct) + return (uintptr_t)mi_tls_slot(1); #else // in all our other targets, slot 0 is the pointer to the thread control block return (uintptr_t)mi_tls_slot(0);