Skip to content

Commit c005ba1

Browse files
committed
WIP
1 parent 4c038b9 commit c005ba1

File tree

3 files changed

+68
-75
lines changed

3 files changed

+68
-75
lines changed

src/snmalloc/ds_core/cheri.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ namespace snmalloc
7070
/*
7171
* At present we check for the pointer also being the start of an
7272
* allocation closer to dealloc; for small objects, that happens in
73-
* dealloc_local_object_fast, either below or *on the far end of message
73+
* dealloc_local_object, either below or *on the far end of message
7474
* receipt*. For large objects, it happens below by directly rounding to
7575
* power of two rather than using the is_start_of_object helper.
7676
* (XXX This does mean that we might end up threading our remote queue

src/snmalloc/mem/corealloc.h

+66-69
Original file line numberDiff line numberDiff line change
@@ -357,13 +357,14 @@ namespace snmalloc
357357
/**
358358
* Handles the messages in the queue if there are any,
359359
* and then calls the action.
360-
*
360+
*
361361
* This is designed to provide a fast path common case that simply
362362
* checks the queue and calls the action if it is empty. If there
363363
* are messages, then it goes to the slow path, handle_message_queue_slow.
364-
*
364+
*
365365
* This is heavily templated to cause inlining, and passing of arguments on
366-
* the stack as often closing over the arguments would cause less good codegen.
366+
* the stack as often closing over the arguments would cause less good
367+
* codegen.
367368
*/
368369
template<typename Action, typename... Args>
369370
SNMALLOC_FAST_PATH decltype(auto)
@@ -485,6 +486,46 @@ namespace snmalloc
485486
entry.get_remote()->trunc_id(), msg);
486487
}
487488

489+
template<typename Domesticator>
490+
SNMALLOC_FAST_PATH static auto dealloc_local_objects_fast(
491+
capptr::Alloc<RemoteMessage> msg,
492+
const PagemapEntry& entry,
493+
BackendSlabMetadata* meta,
494+
LocalEntropy& entropy,
495+
Domesticator domesticate,
496+
size_t& bytes_freed)
497+
{
498+
SNMALLOC_ASSERT(!meta->is_unused());
499+
500+
snmalloc_check_client(
501+
mitigations(sanity_checks),
502+
is_start_of_object(entry.get_sizeclass(), address_cast(msg)),
503+
"Not deallocating start of an object");
504+
505+
size_t objsize = sizeclass_full_to_size(entry.get_sizeclass());
506+
507+
auto [curr, length] = RemoteMessage::template open_free_ring<Config>(
508+
msg,
509+
objsize,
510+
freelist::Object::key_root,
511+
meta->as_key_tweak(),
512+
domesticate);
513+
514+
// TODO this should be fixed in a separate PR.
515+
bytes_freed += objsize * length;
516+
517+
// Update the head and the next pointer in the free list.
518+
meta->free_queue.append_segment(
519+
curr,
520+
msg.template as_reinterpret<freelist::Object::T<>>(),
521+
length,
522+
freelist::Object::key_root,
523+
meta->as_key_tweak(),
524+
entropy);
525+
526+
return meta->return_objects(length);
527+
}
528+
488529
/*************************************************************************
489530
* Allocation Code Overview
490531
*
@@ -879,7 +920,16 @@ namespace snmalloc
879920
/***************************************************************************
880921
* Deallocation code
881922
*
923+
* The main deallocation code is in dealloc. This, like alloc, takes a
924+
* template to initialise the state of the allocator. It is possible for
925+
*the first operation on a thread to be a deallocation.
882926
*
927+
* The algorithm is
928+
* - dealloc(void*)
929+
* - If object, originated from this allocator, then
930+
* - dealloc_local_object(void*)
931+
* - Otherwise
932+
* - dealloc_remote(void*)
883933
***************************************************************************/
884934
template<typename CheckInit = CheckInitNoOp>
885935
SNMALLOC_FAST_PATH void dealloc(void* p_raw)
@@ -935,27 +985,6 @@ namespace snmalloc
935985
{
936986
auto meta = entry.get_slab_metadata();
937987

938-
if (SNMALLOC_LIKELY(dealloc_local_object_fast(p, entry, meta, entropy)))
939-
return;
940-
941-
dealloc_local_object_slow(p, entry, meta);
942-
}
943-
944-
SNMALLOC_FAST_PATH void
945-
dealloc_local_object(CapPtr<void, capptr::bounds::Alloc> p)
946-
{
947-
// PagemapEntry-s seen here are expected to have meaningful Remote
948-
// pointers
949-
dealloc_local_object(
950-
p, Config::Backend::get_metaentry(snmalloc::address_cast(p)));
951-
}
952-
953-
SNMALLOC_FAST_PATH static bool dealloc_local_object_fast(
954-
CapPtr<void, capptr::bounds::Alloc> p,
955-
const PagemapEntry& entry,
956-
BackendSlabMetadata* meta,
957-
LocalEntropy& entropy)
958-
{
959988
SNMALLOC_ASSERT(!meta->is_unused());
960989

961990
snmalloc_check_client(
@@ -969,47 +998,10 @@ namespace snmalloc
969998
meta->free_queue.add(
970999
cp, freelist::Object::key_root, meta->as_key_tweak(), entropy);
9711000

972-
return SNMALLOC_LIKELY(!meta->return_object());
973-
}
974-
975-
template<typename Domesticator>
976-
SNMALLOC_FAST_PATH static auto dealloc_local_objects_fast(
977-
capptr::Alloc<RemoteMessage> msg,
978-
const PagemapEntry& entry,
979-
BackendSlabMetadata* meta,
980-
LocalEntropy& entropy,
981-
Domesticator domesticate,
982-
size_t& bytes_freed)
983-
{
984-
SNMALLOC_ASSERT(!meta->is_unused());
985-
986-
snmalloc_check_client(
987-
mitigations(sanity_checks),
988-
is_start_of_object(entry.get_sizeclass(), address_cast(msg)),
989-
"Not deallocating start of an object");
990-
991-
size_t objsize = sizeclass_full_to_size(entry.get_sizeclass());
992-
993-
auto [curr, length] = RemoteMessage::template open_free_ring<Config>(
994-
msg,
995-
objsize,
996-
freelist::Object::key_root,
997-
meta->as_key_tweak(),
998-
domesticate);
999-
1000-
// TODO this should be fixed in a separate PR.
1001-
bytes_freed += objsize * length;
1002-
1003-
// Update the head and the next pointer in the free list.
1004-
meta->free_queue.append_segment(
1005-
curr,
1006-
msg.template as_reinterpret<freelist::Object::T<>>(),
1007-
length,
1008-
freelist::Object::key_root,
1009-
meta->as_key_tweak(),
1010-
entropy);
1001+
if (SNMALLOC_LIKELY(!meta->return_object()))
1002+
return;
10111003

1012-
return meta->return_objects(length);
1004+
dealloc_local_object_slow(p, entry, meta);
10131005
}
10141006

10151007
/**
@@ -1339,15 +1331,20 @@ namespace snmalloc
13391331

13401332
for (size_t i = 0; i < NUM_SMALL_SIZECLASSES; i++)
13411333
{
1342-
// TODO could optimise this, to return the whole list in one append
1343-
// call.
1344-
while (!small_fast_free_lists[i].empty())
1334+
if (small_fast_free_lists[i].empty())
1335+
continue;
1336+
1337+
// All elements should have the same entry.
1338+
const auto& entry =
1339+
Config::Backend::get_metaentry(small_fast_free_lists[i].peek());
1340+
do
13451341
{
1342+
// return each element
13461343
auto p = small_fast_free_lists[i].take(key, domesticate);
13471344
SNMALLOC_ASSERT(is_start_of_object(
13481345
sizeclass_t::from_small_class(i), address_cast(p)));
1349-
dealloc_local_object(p.as_void());
1350-
}
1346+
dealloc_local_object(p.as_void(), entry);
1347+
} while (!small_fast_free_lists[i].empty());
13511348
}
13521349

13531350
auto posted = remote_dealloc_cache.template post<sizeof(Allocator)>(

src/test/func/malloc/malloc.cc

+1-5
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,7 @@ constexpr int SUCCESS = 0;
1515
void check_result(size_t size, size_t align, void* p, int err, bool null)
1616
{
1717
bool failed = false;
18-
EXPECT(
19-
(errno == err),
20-
"Expected error: {} but got {}",
21-
err,
22-
errno);
18+
EXPECT((errno == err), "Expected error: {} but got {}", err, errno);
2319
if (null)
2420
{
2521
EXPECT(p == nullptr, "Expected null but got {}", p);

0 commit comments

Comments
 (0)