CapPtr: shift free lists to Alloc bounds
This is incomplete, yet still more reflective of what's going on: we take the exported pointers back from userspace and thread them directly into the free lists. So: move capptr_to_user_address_control to list construction time rather than list consumption time.
This commit is contained in:
committed by
Nathaniel Wesley Filardo
parent
55cd5e87c0
commit
7e53a2e82a
@@ -214,30 +214,29 @@ namespace snmalloc
|
||||
auto slowpath =
|
||||
[&](
|
||||
sizeclass_t sizeclass,
|
||||
FreeListIter<capptr::bounds::AllocFull, capptr::bounds::AllocFull>*
|
||||
fl) SNMALLOC_FAST_PATH_LAMBDA {
|
||||
if (likely(core_alloc != nullptr))
|
||||
{
|
||||
return core_alloc->handle_message_queue(
|
||||
[](
|
||||
CoreAlloc* core_alloc,
|
||||
sizeclass_t sizeclass,
|
||||
FreeListIter<
|
||||
capptr::bounds::AllocFull,
|
||||
capptr::bounds::AllocFull>* fl) {
|
||||
return core_alloc->template small_alloc<zero_mem>(
|
||||
sizeclass, *fl);
|
||||
FreeListIter<capptr::bounds::Alloc, capptr::bounds::Alloc>* fl)
|
||||
SNMALLOC_FAST_PATH_LAMBDA {
|
||||
if (likely(core_alloc != nullptr))
|
||||
{
|
||||
return core_alloc->handle_message_queue(
|
||||
[](
|
||||
CoreAlloc* core_alloc,
|
||||
sizeclass_t sizeclass,
|
||||
FreeListIter<capptr::bounds::Alloc, capptr::bounds::Alloc>*
|
||||
fl) {
|
||||
return core_alloc->template small_alloc<zero_mem>(
|
||||
sizeclass, *fl);
|
||||
},
|
||||
core_alloc,
|
||||
sizeclass,
|
||||
fl);
|
||||
}
|
||||
return lazy_init(
|
||||
[&](CoreAlloc*, sizeclass_t sizeclass) {
|
||||
return small_alloc<zero_mem>(sizeclass_to_size(sizeclass));
|
||||
},
|
||||
core_alloc,
|
||||
sizeclass,
|
||||
fl);
|
||||
}
|
||||
return lazy_init(
|
||||
[&](CoreAlloc*, sizeclass_t sizeclass) {
|
||||
return small_alloc<zero_mem>(sizeclass_to_size(sizeclass));
|
||||
},
|
||||
sizeclass);
|
||||
};
|
||||
sizeclass);
|
||||
};
|
||||
|
||||
return local_cache.template alloc<zero_mem, SharedStateHandle>(
|
||||
size, slowpath);
|
||||
@@ -260,20 +259,18 @@ namespace snmalloc
|
||||
* In the second case we need to recheck if this is a remote deallocation,
|
||||
* as we might acquire the originating allocator.
|
||||
*/
|
||||
SNMALLOC_SLOW_PATH void dealloc_remote_slow(void* p)
|
||||
SNMALLOC_SLOW_PATH void dealloc_remote_slow(capptr::Alloc<void> p)
|
||||
{
|
||||
if (core_alloc != nullptr)
|
||||
{
|
||||
#ifdef SNMALLOC_TRACING
|
||||
std::cout << "Remote dealloc post" << p << " size " << alloc_size(p)
|
||||
<< std::endl;
|
||||
std::cout << "Remote dealloc post" << p.unsafe_ptr() << " size "
|
||||
<< alloc_size(p.unsafe_ptr()) << std::endl;
|
||||
#endif
|
||||
MetaEntry entry = SharedStateHandle::Pagemap::get_metaentry(
|
||||
core_alloc->backend_state_ptr(), address_cast(p));
|
||||
local_cache.remote_dealloc_cache.template dealloc<sizeof(CoreAlloc)>(
|
||||
entry.get_remote()->trunc_id(),
|
||||
capptr::AllocFull<void>(p),
|
||||
key_global);
|
||||
entry.get_remote()->trunc_id(), p, key_global);
|
||||
post_remote_cache();
|
||||
return;
|
||||
}
|
||||
@@ -281,8 +278,8 @@ namespace snmalloc
|
||||
// Recheck what kind of dealloc we should do incase, the allocator we get
|
||||
// from lazy_init is the originating allocator.
|
||||
lazy_init(
|
||||
[&](CoreAlloc*, void* p) {
|
||||
dealloc(p); // TODO don't double count statistics
|
||||
[&](CoreAlloc*, CapPtr<void, capptr::bounds::Alloc> p) {
|
||||
dealloc(p.unsafe_ptr()); // TODO don't double count statistics
|
||||
return nullptr;
|
||||
},
|
||||
p);
|
||||
@@ -450,10 +447,10 @@ namespace snmalloc
|
||||
return alloc<zero_mem>(size);
|
||||
}
|
||||
|
||||
SNMALLOC_FAST_PATH void dealloc(void* p)
|
||||
SNMALLOC_FAST_PATH void dealloc(void* p_raw)
|
||||
{
|
||||
#ifdef SNMALLOC_PASS_THROUGH
|
||||
external_alloc::free(p);
|
||||
external_alloc::free(p_raw);
|
||||
#else
|
||||
// TODO:
|
||||
// Care is needed so that dealloc(nullptr) works before init
|
||||
@@ -461,6 +458,7 @@ namespace snmalloc
|
||||
// before init, that maps null to a remote_deallocator that will never be
|
||||
// in thread local state.
|
||||
|
||||
auto p = capptr_from_client(p_raw);
|
||||
const MetaEntry& entry = SharedStateHandle::Pagemap::get_metaentry(
|
||||
core_alloc->backend_state_ptr(), address_cast(p));
|
||||
if (likely(local_cache.remote_allocator == entry.get_remote()))
|
||||
@@ -478,12 +476,10 @@ namespace snmalloc
|
||||
if (local_cache.remote_dealloc_cache.reserve_space(entry))
|
||||
{
|
||||
local_cache.remote_dealloc_cache.template dealloc<sizeof(CoreAlloc)>(
|
||||
entry.get_remote()->trunc_id(),
|
||||
capptr::AllocFull<void>(p),
|
||||
key_global);
|
||||
entry.get_remote()->trunc_id(), p, key_global);
|
||||
# ifdef SNMALLOC_TRACING
|
||||
std::cout << "Remote dealloc fast" << p << " size " << alloc_size(p)
|
||||
<< std::endl;
|
||||
std::cout << "Remote dealloc fast" << p_raw << " size "
|
||||
<< alloc_size(p_raw) << std::endl;
|
||||
# endif
|
||||
return;
|
||||
}
|
||||
@@ -493,7 +489,7 @@ namespace snmalloc
|
||||
}
|
||||
|
||||
// Large deallocation or null.
|
||||
if (likely(p != nullptr))
|
||||
if (likely(p.unsafe_ptr() != nullptr))
|
||||
{
|
||||
// Check this is managed by this pagemap.
|
||||
check_client(entry.get_sizeclass() != 0, "Not allocated by snmalloc.");
|
||||
@@ -511,7 +507,14 @@ namespace snmalloc
|
||||
# endif
|
||||
ChunkRecord* slab_record =
|
||||
reinterpret_cast<ChunkRecord*>(entry.get_metaslab());
|
||||
slab_record->chunk = capptr::Chunk<void>(p);
|
||||
/*
|
||||
* StrictProvenance TODO: this is a subversive amplification. p is
|
||||
* AllocWild-bounded, but we're coercing it to Chunk-bounded. We
|
||||
* should, instead, not be storing ->chunk here, but should be keeping
|
||||
* a CapPtr<void, Chunk> to this region internally even while it's
|
||||
* allocated.
|
||||
*/
|
||||
slab_record->chunk = capptr::Chunk<void>(p.unsafe_ptr());
|
||||
check_init(
|
||||
[](
|
||||
CoreAlloc* core_alloc,
|
||||
|
||||
Reference in New Issue
Block a user