Files
snmalloc/src/mem/globalconfig.h
Matthew Parkinson f0e2ab702a Major refactor of snmalloc (#343)
# Pagemap
 
The Pagemap now stores all the meta-data for the object allocation. The meta-data in the pagemap is effectively a triple of the sizeclass, the remote allocator, and a pointer to a 64 byte block of meta-data for this chunk of memory. By storing the pointer to a block, it allows the pagemap to handle multiple slab sizes without branching on the fast path. There is one entry in the pagemap per 16KiB of address space, but by using the same entry in the pagemap for 4 adjacent entries, then we can treat a 64KiB range can be treated as a single slab of allocations.

This change also means there is almost no capability amplification required by the implementation on CHERI for finding meta-data. The only amplification is required, when we change the way a chunk is used to a size of object allocation.


# Backend

There is a second major aspect of the refactor that there is now a narrow API that abstracts the Pagemap, PAL and address space management. This should better enable the compartmentalisation and makes it easier to produce alternative backends for various research directions. This is a template parameter that can be used to specialised by the front-end in different ways.

# Thread local state

The thread local state has been refactored into two components, one (called 'localalloc') that is stored directly in the TLS and is constant initialised, and one that is allocated in the address space (called 'coreallloc') which is lazily created and pooled.

# Difference

This removes Superslabs/Medium slabs as there meta-data is now part of the pagemap.
2021-07-12 15:53:36 +01:00

108 lines
2.4 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;
// 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