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:
Nathaniel Wesley Filardo
2021-09-21 19:17:51 +01:00
committed by Nathaniel Wesley Filardo
parent 55cd5e87c0
commit 7e53a2e82a
7 changed files with 99 additions and 91 deletions

View File

@@ -36,11 +36,11 @@ namespace snmalloc
// Store the message queue on a separate cacheline. It is mutable data that
// is read by other threads.
alignas(CACHELINE_SIZE)
FreeObject::AtomicQueuePtr<capptr::bounds::AllocFull> back{nullptr};
FreeObject::AtomicQueuePtr<capptr::bounds::Alloc> back{nullptr};
// Store the two ends on different cache lines as access by different
// threads.
alignas(CACHELINE_SIZE)
FreeObject::QueuePtr<capptr::bounds::AllocFull> front{nullptr};
alignas(CACHELINE_SIZE) FreeObject::QueuePtr<capptr::bounds::Alloc> front{
nullptr};
constexpr RemoteAllocator() = default;
@@ -50,7 +50,7 @@ namespace snmalloc
SNMALLOC_ASSERT(front != nullptr);
}
void init(FreeObject::QueuePtr<capptr::bounds::AllocFull> stub)
void init(FreeObject::QueuePtr<capptr::bounds::Alloc> stub)
{
FreeObject::atomic_store_null(stub, key_global);
front = stub;
@@ -58,9 +58,9 @@ namespace snmalloc
invariant();
}
FreeObject::QueuePtr<capptr::bounds::AllocFull> destroy()
FreeObject::QueuePtr<capptr::bounds::Alloc> destroy()
{
FreeObject::QueuePtr<capptr::bounds::AllocFull> fnt = front;
FreeObject::QueuePtr<capptr::bounds::Alloc> fnt = front;
back.store(nullptr, std::memory_order_relaxed);
front = nullptr;
return fnt;
@@ -68,7 +68,7 @@ namespace snmalloc
inline bool is_empty()
{
FreeObject::QueuePtr<capptr::bounds::AllocFull> bk =
FreeObject::QueuePtr<capptr::bounds::Alloc> bk =
back.load(std::memory_order_relaxed);
return bk == front;
@@ -79,22 +79,22 @@ namespace snmalloc
* last should be linked together through their next pointers.
*/
void enqueue(
FreeObject::QueuePtr<capptr::bounds::AllocFull> first,
FreeObject::QueuePtr<capptr::bounds::AllocFull> last,
FreeObject::QueuePtr<capptr::bounds::Alloc> first,
FreeObject::QueuePtr<capptr::bounds::Alloc> last,
const FreeListKey& key)
{
invariant();
FreeObject::atomic_store_null(last, key);
// exchange needs to be a release, so nullptr in next is visible.
FreeObject::QueuePtr<capptr::bounds::AllocFull> prev =
FreeObject::QueuePtr<capptr::bounds::Alloc> prev =
back.exchange(last, std::memory_order_release);
// XXX prev is not known to be domesticated
FreeObject::atomic_store_next(prev, first, key);
}
FreeObject::QueuePtr<capptr::bounds::AllocFull> peek()
FreeObject::QueuePtr<capptr::bounds::Alloc> peek()
{
return front;
}
@@ -103,16 +103,16 @@ namespace snmalloc
* Returns the front message, or null if not possible to return a message.
*/
std::pair<
FreeObject::HeadPtr<capptr::bounds::AllocFull, capptr::bounds::AllocFull>,
FreeObject::HeadPtr<capptr::bounds::Alloc, capptr::bounds::Alloc>,
bool>
dequeue(const FreeListKey& key)
{
auto domesticate = [](FreeObject::QueuePtr<capptr::bounds::AllocFull> p)
auto domesticate = [](FreeObject::QueuePtr<capptr::bounds::Alloc> p)
SNMALLOC_FAST_PATH_LAMBDA { return p; };
invariant();
FreeObject::HeadPtr<capptr::bounds::AllocFull, capptr::bounds::AllocFull>
first = domesticate(front);
FreeObject::QueuePtr<capptr::bounds::AllocFull> next =
FreeObject::HeadPtr<capptr::bounds::Alloc, capptr::bounds::Alloc> first =
domesticate(front);
FreeObject::QueuePtr<capptr::bounds::Alloc> next =
first->atomic_read_next(key, domesticate);
if (next != nullptr)