Move to FreeObject::T<capptr::bound<>>
FreeObject itself is now just a namespace (but `friend`-ly); the actual free
list nodes are FreeObject::T-s that are templatized on the (perceived)
`capptr::bound<>` of the pointer they contain. (These may differ across an
instantiated snmalloc; for example, in the sandboxing design, the in-sandbox
allocators may perceive all remotes to be full of `AllocUser` while the
privileged allocator of sandbox memory should perceive its remote queue as
holding `AllocUserWild` pointers in need of domestication.)
The interfaces to `FreeObject::T`-s now let us distinguish between the base and
inductive cases of the queues:
* in the inductive case, the pointer we hold to a `FreeObject::T` and its
next_object have the same bounds
* in the base case, the pointer we hold has different bounds (typically,
domesticated by contrast to the wild pointers in the queues).
To keep the clutter down a bit, we occasionally use raw pointers when we can be
reasonably certain that domestication is assured. Moreover, we define some type
aliases, `FreeObject::{HeadPtr, QueuePtr, AtomicQueuePtr}`, that are slightly
more convenient labels than, e.g., `CapPtr<FreeObject::T<BQueue>, BView>`.
Because we are using template parameters for the `capptr::bound<>`s themselves,
we cannot use the aliases for `CapPtr<>s` provided within `capptr::`.
The two primary interfaces around free objects (`FreeListIter` AND
`FreeListBuilder`) are adjusted appropriately and their `BView` and `BQueue`
template paramters are plumbed explicitly around the tree. This makes for quite
a bit of noise at the moment, but means that we'll be able to evolve parts of
the tree separately and can consider putting defaults in once that's done.
This commit is contained in:
committed by
Nathaniel Wesley Filardo
parent
d76f5fdd28
commit
e25db7b832
@@ -161,8 +161,9 @@ namespace snmalloc
|
||||
{
|
||||
// Manufacture an allocation to prime the queue
|
||||
// Using an actual allocation removes a conditional from a critical path.
|
||||
auto dummy = capptr::AllocFull<void>(small_alloc_one(MIN_ALLOC_SIZE))
|
||||
.template as_static<FreeObject>();
|
||||
auto dummy =
|
||||
capptr::AllocFull<void>(small_alloc_one(MIN_ALLOC_SIZE))
|
||||
.template as_static<FreeObject::T<capptr::bounds::AllocFull>>();
|
||||
if (dummy == nullptr)
|
||||
{
|
||||
error("Critical error: Out-of-memory during initialisation.");
|
||||
@@ -181,9 +182,11 @@ namespace snmalloc
|
||||
SNMALLOC_ASSERT(attached_cache != nullptr);
|
||||
// Use attached cache, and fill it if it is empty.
|
||||
return attached_cache->template alloc<NoZero, SharedStateHandle>(
|
||||
size, [&](sizeclass_t sizeclass, FreeListIter* fl) {
|
||||
return small_alloc<NoZero>(sizeclass, *fl);
|
||||
});
|
||||
size,
|
||||
[&](
|
||||
sizeclass_t sizeclass,
|
||||
FreeListIter<capptr::bounds::AllocFull, capptr::bounds::AllocFull>*
|
||||
fl) { return small_alloc<NoZero>(sizeclass, *fl); });
|
||||
}
|
||||
|
||||
static SNMALLOC_FAST_PATH void alloc_new_list(
|
||||
@@ -244,7 +247,10 @@ namespace snmalloc
|
||||
auto curr_ptr = start_ptr;
|
||||
do
|
||||
{
|
||||
b.add(FreeObject::make(curr_ptr.as_void()), key, entropy);
|
||||
b.add(
|
||||
FreeObject::make<capptr::bounds::AllocFull>(curr_ptr.as_void()),
|
||||
key,
|
||||
entropy);
|
||||
curr_ptr = curr_ptr->next;
|
||||
} while (curr_ptr != start_ptr);
|
||||
#else
|
||||
@@ -252,7 +258,9 @@ namespace snmalloc
|
||||
do
|
||||
{
|
||||
b.add(
|
||||
Aal::capptr_bound<FreeObject, capptr::bounds::AllocFull>(p, rsize),
|
||||
Aal::capptr_bound<
|
||||
FreeObject::T<capptr::bounds::AllocFull>,
|
||||
capptr::bounds::AllocFull>(p, rsize),
|
||||
key);
|
||||
p = pointer_offset(p, rsize);
|
||||
} while (p < slab_end);
|
||||
@@ -264,7 +272,7 @@ namespace snmalloc
|
||||
ChunkRecord* clear_slab(Metaslab* meta, sizeclass_t sizeclass)
|
||||
{
|
||||
auto& key = entropy.get_free_list_key();
|
||||
FreeListIter fl;
|
||||
FreeListIter<capptr::bounds::AllocFull, capptr::bounds::AllocFull> fl;
|
||||
auto more = meta->free_queue.close(fl, key);
|
||||
UNUSED(more);
|
||||
void* p = finish_alloc_no_zero(fl.take(key), sizeclass);
|
||||
@@ -426,7 +434,9 @@ namespace snmalloc
|
||||
* need_post will be set to true, if capacity is exceeded.
|
||||
*/
|
||||
void handle_dealloc_remote(
|
||||
const MetaEntry& entry, capptr::AllocFull<FreeObject> p, bool& need_post)
|
||||
const MetaEntry& entry,
|
||||
FreeObject::QueuePtr<capptr::bounds::AllocFull> p,
|
||||
bool& need_post)
|
||||
{
|
||||
// TODO this needs to not double count stats
|
||||
// TODO this needs to not double revoke if using MTE
|
||||
@@ -580,7 +590,8 @@ namespace snmalloc
|
||||
Metaslab::is_start_of_object(entry.get_sizeclass(), address_cast(p)),
|
||||
"Not deallocating start of an object");
|
||||
|
||||
auto cp = capptr::AllocFull<FreeObject>(reinterpret_cast<FreeObject*>(p));
|
||||
auto cp = FreeObject::QueuePtr<capptr::bounds::AllocFull>(
|
||||
reinterpret_cast<FreeObject::T<capptr::bounds::AllocFull>*>(p));
|
||||
|
||||
auto& key = entropy.get_free_list_key();
|
||||
|
||||
@@ -591,8 +602,10 @@ namespace snmalloc
|
||||
}
|
||||
|
||||
template<ZeroMem zero_mem>
|
||||
SNMALLOC_SLOW_PATH void*
|
||||
small_alloc(sizeclass_t sizeclass, FreeListIter& fast_free_list)
|
||||
SNMALLOC_SLOW_PATH void* small_alloc(
|
||||
sizeclass_t sizeclass,
|
||||
FreeListIter<capptr::bounds::AllocFull, capptr::bounds::AllocFull>&
|
||||
fast_free_list)
|
||||
{
|
||||
size_t rsize = sizeclass_to_size(sizeclass);
|
||||
|
||||
@@ -650,7 +663,10 @@ namespace snmalloc
|
||||
|
||||
template<ZeroMem zero_mem>
|
||||
SNMALLOC_SLOW_PATH void* small_alloc_slow(
|
||||
sizeclass_t sizeclass, FreeListIter& fast_free_list, size_t rsize)
|
||||
sizeclass_t sizeclass,
|
||||
FreeListIter<capptr::bounds::AllocFull, capptr::bounds::AllocFull>&
|
||||
fast_free_list,
|
||||
size_t rsize)
|
||||
{
|
||||
// No existing free list get a new slab.
|
||||
size_t slab_size = sizeclass_to_slab_size(sizeclass);
|
||||
@@ -712,6 +728,7 @@ namespace snmalloc
|
||||
auto& entry = SharedStateHandle::Pagemap::get_metaentry(
|
||||
backend_state_ptr(), snmalloc::address_cast(p));
|
||||
handle_dealloc_remote(entry, p, need_post);
|
||||
// XXX n is not known to be domesticated
|
||||
p = n;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user