From b8b5f30513d679996f8676c3cccfa429656150d4 Mon Sep 17 00:00:00 2001 From: Nathaniel Filardo Date: Fri, 20 Nov 2020 02:47:29 +0000 Subject: [PATCH] mediumslab: limit header to min of page or slab This had not been observed as an issue prior to 923705e514e850ee0070cef470fca9d9c47ca3da because CMakeLists.txt had, until then, been using EQUAL, not STREQUAL, to test for oe (and to then enable USE_SMALL_CHUNKS). This test would fail, and so the default SLAB_SIZE was used. Absent this min operation, the use of a whole page on a 64KiB page causes a crash when using the largest medium size class, as, ultimately, size classes are not based on page sizes, and so committing a whole page to the header leaves too little room for that class. See also 3d3b048776fd576c725a06bd8c4432c50abca81b. --- src/mem/allocconfig.h | 2 +- src/mem/mediumslab.h | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/mem/allocconfig.h b/src/mem/allocconfig.h index 0ea5257..5bb03fb 100644 --- a/src/mem/allocconfig.h +++ b/src/mem/allocconfig.h @@ -100,7 +100,7 @@ namespace snmalloc static constexpr size_t MIN_ALLOC_SIZE = 2 * sizeof(void*); static constexpr size_t MIN_ALLOC_BITS = bits::ctz_const(MIN_ALLOC_SIZE); - // Slabs are 64 KiB unless constrained to 16 KiB. + // Slabs are 64 KiB unless constrained to 16 or even 8 KiB static constexpr size_t SLAB_BITS = USE_SMALL_CHUNKS ? 13 : (USE_LARGE_CHUNKS ? 16 : 14); static constexpr size_t SLAB_SIZE = 1 << SLAB_BITS; diff --git a/src/mem/mediumslab.h b/src/mem/mediumslab.h index 9dcfa66..905d760 100644 --- a/src/mem/mediumslab.h +++ b/src/mem/mediumslab.h @@ -25,7 +25,7 @@ namespace snmalloc uint16_t stack[SLAB_COUNT - 1]; public: - static constexpr uint32_t header_size() + static constexpr size_t header_size() { static_assert( sizeof(Mediumslab) < OS_PAGE_SIZE, @@ -34,9 +34,14 @@ namespace snmalloc sizeof(Mediumslab) < SLAB_SIZE, "Mediumslab header size must be less than the slab size"); - // Always use a full page as the header, in order to get page sized - // alignment of individual allocations. - return OS_PAGE_SIZE; + /* + * Always use a full page or SLAB, whichever is smaller, in order + * to get good alignment of individual allocations. Some platforms + * have huge minimum pages (e.g., Linux on PowerPC uses 64KiB) and + * our SLABs are occasionally small by comparison (e.g., in OE, when + * we take them to be 8KiB). + */ + return bits::align_up(sizeof(Mediumslab), min(OS_PAGE_SIZE, SLAB_SIZE)); } static Mediumslab* get(const void* p)