This extends the freelist protection to the remote message queues. They effectively perform doubly linked list entries for the message queue with the enqueue operation first linking in the previous pointer, and then then atomically setting the next. This ensures that the visible states always satisfy the invariant that the forward and backward pointers are correct for any visisble object. There is a key_global that is used for all remote deallocations. The remote cache uses the same protection to build the temporary lists before forwarding to the next allocator. The mpscq is integrated into the remoteallocator as it is no longer a reusable datastructure, but a special purpose implementation.
111 lines
2.5 KiB
C++
111 lines
2.5 KiB
C++
#pragma once
|
|
|
|
#include "../backend/backend.h"
|
|
#include "../mem/corealloc.h"
|
|
#include "../mem/pool.h"
|
|
#include "../mem/slaballocator.h"
|
|
#include "commonconfig.h"
|
|
|
|
namespace snmalloc
|
|
{
|
|
// Forward reference to thread local cleanup.
|
|
void register_clean_up();
|
|
|
|
#ifdef USE_SNMALLOC_STATS
|
|
inline static void print_stats()
|
|
{
|
|
printf("No Stats yet!");
|
|
// Stats s;
|
|
// current_alloc_pool()->aggregate_stats(s);
|
|
// s.print<Alloc>(std::cout);
|
|
}
|
|
#endif
|
|
|
|
class Globals : public CommonConfig
|
|
{
|
|
public:
|
|
using Backend = BackendAllocator<Pal, false>;
|
|
|
|
private:
|
|
SNMALLOC_REQUIRE_CONSTINIT
|
|
inline static Backend::GlobalState backend_state;
|
|
|
|
SNMALLOC_REQUIRE_CONSTINIT
|
|
inline static ChunkAllocatorState slab_allocator_state;
|
|
|
|
SNMALLOC_REQUIRE_CONSTINIT
|
|
inline static PoolState<CoreAllocator<Globals>> alloc_pool;
|
|
|
|
SNMALLOC_REQUIRE_CONSTINIT
|
|
inline static std::atomic<bool> initialised{false};
|
|
|
|
SNMALLOC_REQUIRE_CONSTINIT
|
|
inline static std::atomic_flag initialisation_lock{};
|
|
|
|
public:
|
|
Backend::GlobalState& get_backend_state()
|
|
{
|
|
return backend_state;
|
|
}
|
|
|
|
ChunkAllocatorState& get_slab_allocator_state()
|
|
{
|
|
return slab_allocator_state;
|
|
}
|
|
|
|
PoolState<CoreAllocator<Globals>>& pool()
|
|
{
|
|
return alloc_pool;
|
|
}
|
|
|
|
static constexpr bool IsQueueInline = true;
|
|
|
|
// Performs initialisation for this configuration
|
|
// of allocators. Needs to be idempotent,
|
|
// and concurrency safe.
|
|
void ensure_init()
|
|
{
|
|
FlagLock lock{initialisation_lock};
|
|
#ifdef SNMALLOC_TRACING
|
|
std::cout << "Run init_impl" << std::endl;
|
|
#endif
|
|
|
|
if (initialised)
|
|
return;
|
|
|
|
// Initialise key for remote deallocation lists
|
|
key_global = FreeListKey(get_entropy64<Backend::Pal>());
|
|
|
|
// Need to initialise pagemap.
|
|
backend_state.init();
|
|
|
|
#ifdef USE_SNMALLOC_STATS
|
|
atexit(snmalloc::print_stats);
|
|
#endif
|
|
|
|
initialised = true;
|
|
}
|
|
|
|
bool is_initialised()
|
|
{
|
|
return initialised;
|
|
}
|
|
|
|
// This needs to be a forward reference as the
|
|
// thread local state will need to know about this.
|
|
// This may allocate, so should only be called once
|
|
// a thread local allocator is available.
|
|
void register_clean_up()
|
|
{
|
|
snmalloc::register_clean_up();
|
|
}
|
|
|
|
// This is an empty structure as all the state is global
|
|
// for this allocator configuration.
|
|
static constexpr Globals get_handle()
|
|
{
|
|
return {};
|
|
}
|
|
};
|
|
} // namespace snmalloc
|