Metaslab: add MetaCommon field

This preserves the chunk pointer through the use of a chunk as a slab.  It does
grow the structure by one pointer, but on non-CHERI it is still padded to 64
bytes, even with CHECK_CLIENT guards in place:

 0: MetaCommon chunk pointer
 8: next pointer
16: builder head[0]
24: builder head[1]
32: builder tail[0]
40: builder tail[1]
48: builder length[0] (uint16_t)
50: builder length[1] (uint16_t)
52: padding (4 bytes)
56: needed (uint16_t)
58: sleeping (bool)

(Sadly, on CHERI, even without CHECK_CLIENT guards and with no padding, there
are now four pointers in the structure -- chunk, next, head, tail -- plus five
extra bytes.  We will likely wish to explore encoding the head and tail offsets
relative to the chunk pointer.)

This lets us remove the "subversive amplification" in dealloc() in favor of just
preserving the chunk pointer.  Speaking of, be sure to assign that in all the
right places, and ASSERT that we've got it right.
This commit is contained in:
Nathaniel Wesley Filardo
2021-10-17 16:38:19 +01:00
committed by Nathaniel Wesley Filardo
parent 6c115eec18
commit 599ae0e632
4 changed files with 26 additions and 12 deletions

View File

@@ -321,13 +321,16 @@ namespace snmalloc
// have the whole chunk.
auto start_of_slab = pointer_align_down<void>(
p, snmalloc::sizeclass_to_slab_size(sizeclass));
// TODO Add bounds correctly here
chunk_record->meta_common.chunk =
capptr::Chunk<void>(start_of_slab.unsafe_ptr());
SNMALLOC_ASSERT(
address_cast(start_of_slab) ==
address_cast(chunk_record->meta_common.chunk));
#ifdef SNMALLOC_TRACING
std::cout << "Slab " << start_of_slab.unsafe_ptr()
<< " is unused, Object sizeclass " << sizeclass << std::endl;
#else
UNUSED(start_of_slab);
#endif
return chunk_record;
}