Implement a FlatPagemap

The current pagemap assumes there is at least one level of indexing.
This commit introduces a new pagemap that is completely flat.  This is
useful for 32bit, where there is no need to introduce the indexing
structure.

This pagemap is also considerably faster for 64bit platforms, but
does require a global allocation of 16MiB of the flat page map.
This commit is contained in:
Matthew Parkinson
2019-01-16 14:37:18 +00:00
parent 82595dc9cd
commit 233be30731
2 changed files with 49 additions and 2 deletions

View File

@@ -38,7 +38,10 @@ namespace snmalloc
PMMediumslab = 2
};
using SuperslabPagemap = Pagemap<SUPERSLAB_BITS, uint8_t, 0>;
using SuperslabPagemap = std::conditional_t<
bits::is64(),
Pagemap<SUPERSLAB_BITS, uint8_t, 0>,
FlatPagemap<SUPERSLAB_BITS, uint8_t>>;
HEADER_GLOBAL SuperslabPagemap global_pagemap;
/**
@@ -131,7 +134,7 @@ namespace snmalloc
};
static_assert(
SUPERSLAB_SIZE == Pagemap<SUPERSLAB_BITS, size_t, 0>::GRANULARITY,
SUPERSLAB_SIZE == SuperslabPagemap::GRANULARITY,
"The superslab size should be the same as the pagemap granularity");
#ifndef SNMALLOC_DEFAULT_PAGEMAP

View File

@@ -21,6 +21,10 @@ namespace snmalloc
static constexpr size_t CONTENT_BITS =
bits::next_pow2_bits_const(sizeof(T));
static_assert(
PAGEMAP_BITS - CONTENT_BITS < COVERED_BITS,
"Should use the FlatPageMap as it does not require a tree");
static constexpr size_t BITS_FOR_LEAF = PAGEMAP_BITS - CONTENT_BITS;
static constexpr size_t ENTRIES_PER_LEAF = 1 << BITS_FOR_LEAF;
static constexpr size_t LEAF_MASK = ENTRIES_PER_LEAF - 1;
@@ -224,4 +228,44 @@ namespace snmalloc
} while (length > 0);
}
};
template<size_t GRANULARITY_BITS, typename T>
class FlatPagemap
{
private:
static constexpr size_t COVERED_BITS =
bits::ADDRESS_BITS - GRANULARITY_BITS;
static constexpr size_t CONTENT_BITS =
bits::next_pow2_bits_const(sizeof(T));
static constexpr size_t ENTRIES = 1ULL << (COVERED_BITS + CONTENT_BITS);
static constexpr size_t SHIFT = GRANULARITY_BITS;
public:
static constexpr size_t GRANULARITY = 1 << GRANULARITY_BITS;
private:
std::atomic<T> top[ENTRIES];
public:
T get(void* p)
{
return top[(size_t)p >> SHIFT].load(std::memory_order_relaxed);
}
void set(void* p, T x)
{
top[(size_t)p >> SHIFT].store(x, std::memory_order_relaxed);
}
void set_range(void* p, T x, size_t length)
{
size_t index = (size_t)p >> SHIFT;
do
{
top[index].store(x, std::memory_order_relaxed);
index++;
length--;
} while (length > 0);
}
};
}