From 233be3073193f90f3c195e6c6821e5b9e4f556f5 Mon Sep 17 00:00:00 2001 From: Matthew Parkinson Date: Wed, 16 Jan 2019 14:37:18 +0000 Subject: [PATCH] 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. --- src/mem/alloc.h | 7 +++++-- src/mem/pagemap.h | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/src/mem/alloc.h b/src/mem/alloc.h index 38c89d1..096ad47 100644 --- a/src/mem/alloc.h +++ b/src/mem/alloc.h @@ -38,7 +38,10 @@ namespace snmalloc PMMediumslab = 2 }; - using SuperslabPagemap = Pagemap; + using SuperslabPagemap = std::conditional_t< + bits::is64(), + Pagemap, + FlatPagemap>; HEADER_GLOBAL SuperslabPagemap global_pagemap; /** @@ -131,7 +134,7 @@ namespace snmalloc }; static_assert( - SUPERSLAB_SIZE == Pagemap::GRANULARITY, + SUPERSLAB_SIZE == SuperslabPagemap::GRANULARITY, "The superslab size should be the same as the pagemap granularity"); #ifndef SNMALLOC_DEFAULT_PAGEMAP diff --git a/src/mem/pagemap.h b/src/mem/pagemap.h index 20b01e2..e0e73b1 100644 --- a/src/mem/pagemap.h +++ b/src/mem/pagemap.h @@ -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 + 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 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); + } + }; }