Common cache line sizes are 32, 64 and 128 bytes. On x86_64 the standard
cache line size is 64B. Even though this is not architecturally required,
all the x86_64implementations stick to it. Some AArch64 processors also
follow the x86_64 style with 64B cachelines. However, on Apple M1
devices, the underlying hardware is using a 128B cache line size. Quote
from Apple Developer documentation [1]:
"Some features of Apple silicon are decidedly different than those of
Intel-based Mac computers, and may impact your code if you don't fetch
them dynamically. These features include:
* Cache line sizes are different. Fetch the hw.cachelinesize setting
using sysctl."
M1 cache lines are double of what is commonly used by x86_64 and other
Arm implementation. The cache line sizes for Arm depend on implementations,
not architectures. For example, TI AM57x (Cortex-A15) uses 64B cache
line while TI AM437x (Cortex-A9) uses 32B cache line. And, there are
even Arm implementations with cache line sizes configurable at boot time.
This patch attempts to detect L1 cache size at compile time. For Aarch64
hosts, the build process would collect system information and determine
L1 cache line size. At present, both macOS and Linux are supported. For
Arm targets, the software packages are usually cross-compiled, and
developers should specify the appropriate MI_CACHE_LINE setting in
advance.
64B is the default cache line size if none of the above is able to set.
[1] https://developer.apple.com/documentation/apple-silicon/addressing-architectural-differences-in-your-macos-code
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.
The pthread slot approach is somewhat buggy (pretty visible
with the stress unit test which segfault more or less randomly,
but the stats never show up).
Using the default approach instead, the test passes eventough
it s relatively slow (e.g 1.5 sec on FreeBSD vs 4.5 on DragonFly with same
machine).