Merge pull request #13 from Microsoft/matt-refactor
Simplification around remote allocation
This commit is contained in:
@@ -522,16 +522,27 @@ namespace snmalloc
|
||||
size_t size = 0;
|
||||
RemoteList list[REMOTE_SLOTS];
|
||||
|
||||
/// Used to find the index into the array of queues for remote
|
||||
/// deallocation
|
||||
/// r is used for which round of sending this is.
|
||||
inline size_t get_slot(size_t id, size_t r)
|
||||
{
|
||||
constexpr size_t allocator_size =
|
||||
sizeof(Allocator<MemoryProvider, PageMap, IsQueueInline>);
|
||||
constexpr size_t initial_shift =
|
||||
bits::next_pow2_bits_const(allocator_size);
|
||||
return (id >> (initial_shift + (r * REMOTE_SLOT_BITS))) & REMOTE_MASK;
|
||||
}
|
||||
|
||||
void dealloc(alloc_id_t target_id, void* p, uint8_t sizeclass)
|
||||
{
|
||||
this->size += sizeclass_to_size(sizeclass);
|
||||
|
||||
Remote* r = (Remote*)p;
|
||||
r->set_sizeclass_and_target_id(target_id, sizeclass);
|
||||
assert(r->sizeclass() == sizeclass);
|
||||
r->set_target_id(target_id);
|
||||
assert(r->target_id() == target_id);
|
||||
|
||||
RemoteList* l = &list[target_id & REMOTE_MASK];
|
||||
RemoteList* l = &list[get_slot(target_id, 0)];
|
||||
l->last->non_atomic_next = r;
|
||||
l->last = r;
|
||||
}
|
||||
@@ -541,11 +552,11 @@ namespace snmalloc
|
||||
// When the cache gets big, post lists to their target allocators.
|
||||
size = 0;
|
||||
|
||||
size_t shift = 0;
|
||||
size_t post_round = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
auto my_slot = (id >> shift) & REMOTE_MASK;
|
||||
auto my_slot = get_slot(id, post_round);
|
||||
|
||||
for (size_t i = 0; i < REMOTE_SLOTS; i++)
|
||||
{
|
||||
@@ -575,13 +586,13 @@ namespace snmalloc
|
||||
resend->last->non_atomic_next = nullptr;
|
||||
resend->clear();
|
||||
|
||||
shift += REMOTE_SLOT_BITS;
|
||||
post_round++;
|
||||
|
||||
while (r != nullptr)
|
||||
{
|
||||
// Use the next N bits to spread out remote deallocs in our own
|
||||
// slot.
|
||||
size_t slot = (r->target_id() >> shift) & REMOTE_MASK;
|
||||
size_t slot = get_slot(r->target_id(), post_round);
|
||||
RemoteList* l = &list[slot];
|
||||
l->last->non_atomic_next = r;
|
||||
l->last = r;
|
||||
@@ -693,21 +704,34 @@ namespace snmalloc
|
||||
{
|
||||
if (p != &stub)
|
||||
{
|
||||
uint8_t sizeclass = p->sizeclass();
|
||||
Superslab* super = Superslab::get(p);
|
||||
|
||||
if (p->target_id() == id())
|
||||
if (super->get_kind() == Super)
|
||||
{
|
||||
stats().remote_receive(sizeclass);
|
||||
|
||||
if (sizeclass < NUM_SMALL_CLASSES)
|
||||
small_dealloc(Superslab::get(p), p, sizeclass);
|
||||
Slab* slab = Slab::get(p);
|
||||
Metaslab& meta = super->get_meta(slab);
|
||||
if (p->target_id() == id())
|
||||
{
|
||||
small_dealloc(super, p, meta.sizeclass);
|
||||
}
|
||||
else
|
||||
medium_dealloc(Mediumslab::get(p), p, sizeclass);
|
||||
{
|
||||
// Queue for remote dealloc elsewhere.
|
||||
remote.dealloc(p->target_id(), p, meta.sizeclass);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Queue for remote dealloc elsewhere.
|
||||
remote.dealloc(p->target_id(), p, sizeclass);
|
||||
Mediumslab* slab = Mediumslab::get(p);
|
||||
if (p->target_id() == id())
|
||||
{
|
||||
medium_dealloc(slab, p, slab->get_sizeclass());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Queue for remote dealloc elsewhere.
|
||||
remote.dealloc(p->target_id(), p, slab->get_sizeclass());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,8 @@ namespace snmalloc
|
||||
if (p != nullptr)
|
||||
return p;
|
||||
|
||||
p = (T*)memory_provider.alloc_chunk(sizeof(T));
|
||||
p = (T*)memory_provider
|
||||
.template alloc_chunk<bits::next_pow2_const(sizeof(T))>(sizeof(T));
|
||||
|
||||
new (p) T(std::forward<Args...>(args)...);
|
||||
|
||||
|
||||
@@ -10,13 +10,6 @@ namespace snmalloc
|
||||
{
|
||||
struct Remote
|
||||
{
|
||||
static const size_t PTR_BITS = sizeof(void*) * 8;
|
||||
static const size_t SIZECLASS_BITS =
|
||||
bits::next_pow2_bits_const(NUM_SIZECLASSES);
|
||||
static const bool USE_TOP_BITS =
|
||||
SIZECLASS_BITS + bits::ADDRESS_BITS < PTR_BITS;
|
||||
static const uintptr_t SIZECLASS_MASK = ((1ULL << SIZECLASS_BITS) - 1);
|
||||
|
||||
using alloc_id_t = size_t;
|
||||
union
|
||||
{
|
||||
@@ -24,65 +17,22 @@ namespace snmalloc
|
||||
Remote* non_atomic_next;
|
||||
};
|
||||
|
||||
// Uses an intptr_t so that when we use the TOP_BITS to encode the
|
||||
// sizeclass, then we can use signed shift to correctly handle kernel versus
|
||||
// user mode.
|
||||
intptr_t value;
|
||||
alloc_id_t allocator_id;
|
||||
|
||||
// This will not exist for the minimum object size. This is only used if
|
||||
// USE_TOP_BITS is false, and the bottom bit of value is set.
|
||||
uint8_t possible_sizeclass;
|
||||
|
||||
void set_sizeclass_and_target_id(alloc_id_t id, uint8_t sizeclass)
|
||||
void set_target_id(alloc_id_t id)
|
||||
{
|
||||
if constexpr (USE_TOP_BITS)
|
||||
{
|
||||
value = (intptr_t)(
|
||||
(id << SIZECLASS_BITS) | ((static_cast<uintptr_t>(sizeclass))));
|
||||
}
|
||||
else
|
||||
{
|
||||
assert((id & 1) == 0);
|
||||
if (sizeclass == 0)
|
||||
{
|
||||
value = (intptr_t)(id | 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
value = (intptr_t)id;
|
||||
possible_sizeclass = sizeclass;
|
||||
}
|
||||
}
|
||||
allocator_id = id;
|
||||
}
|
||||
|
||||
alloc_id_t target_id()
|
||||
{
|
||||
if constexpr (USE_TOP_BITS)
|
||||
{
|
||||
return (alloc_id_t)(value >> SIZECLASS_BITS);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (alloc_id_t)(value & ~1);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t sizeclass()
|
||||
{
|
||||
if constexpr (USE_TOP_BITS)
|
||||
{
|
||||
return (static_cast<uint8_t>((uintptr_t)value & SIZECLASS_MASK));
|
||||
}
|
||||
else
|
||||
{
|
||||
return ((value & 1) == 1) ? 0 : possible_sizeclass;
|
||||
}
|
||||
return allocator_id;
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(
|
||||
(offsetof(Remote, possible_sizeclass)) <= MIN_ALLOC_SIZE,
|
||||
"Need to be able to cast any small alloc to Remote");
|
||||
sizeof(Remote) <= MIN_ALLOC_SIZE,
|
||||
"Needs to be able to fit in smallest allocation.");
|
||||
|
||||
struct RemoteAllocator
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user