mediumslab: limit header to min of page or slab

This had not been observed as an issue prior to
923705e514 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 3d3b048776.
This commit is contained in:
Nathaniel Filardo
2020-11-20 02:47:29 +00:00
committed by Matthew Parkinson
parent 3e7ea1a85f
commit b8b5f30513
2 changed files with 10 additions and 5 deletions

View File

@@ -100,7 +100,7 @@ namespace snmalloc
static constexpr size_t MIN_ALLOC_SIZE = 2 * sizeof(void*); static constexpr size_t MIN_ALLOC_SIZE = 2 * sizeof(void*);
static constexpr size_t MIN_ALLOC_BITS = bits::ctz_const(MIN_ALLOC_SIZE); 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 = static constexpr size_t SLAB_BITS =
USE_SMALL_CHUNKS ? 13 : (USE_LARGE_CHUNKS ? 16 : 14); USE_SMALL_CHUNKS ? 13 : (USE_LARGE_CHUNKS ? 16 : 14);
static constexpr size_t SLAB_SIZE = 1 << SLAB_BITS; static constexpr size_t SLAB_SIZE = 1 << SLAB_BITS;

View File

@@ -25,7 +25,7 @@ namespace snmalloc
uint16_t stack[SLAB_COUNT - 1]; uint16_t stack[SLAB_COUNT - 1];
public: public:
static constexpr uint32_t header_size() static constexpr size_t header_size()
{ {
static_assert( static_assert(
sizeof(Mediumslab) < OS_PAGE_SIZE, sizeof(Mediumslab) < OS_PAGE_SIZE,
@@ -34,9 +34,14 @@ namespace snmalloc
sizeof(Mediumslab) < SLAB_SIZE, sizeof(Mediumslab) < SLAB_SIZE,
"Mediumslab header size must be less than the 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. * Always use a full page or SLAB, whichever is smaller, in order
return OS_PAGE_SIZE; * 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) static Mediumslab* get(const void* p)