Merge pull request #185 from nwf/pal-page-size
Move OS_PAGE_SIZE to PAL, add Linux PowerPC w/ 64KiB pages
This commit is contained in:
@@ -19,6 +19,10 @@
|
||||
# define PLATFORM_IS_ARM
|
||||
#endif
|
||||
|
||||
#if defined(__powerpc__) || defined(__powerpc64__)
|
||||
# define PLATFORM_IS_POWERPC
|
||||
#endif
|
||||
|
||||
namespace snmalloc
|
||||
{
|
||||
/**
|
||||
@@ -44,6 +48,14 @@ namespace snmalloc
|
||||
StrictProvenance = (1 << 2),
|
||||
};
|
||||
|
||||
enum AalName : int
|
||||
{
|
||||
ARM,
|
||||
PowerPC,
|
||||
X86,
|
||||
X86_SGX,
|
||||
};
|
||||
|
||||
/**
|
||||
* Architecture Abstraction Layer. Includes default implementations of some
|
||||
* functions using compiler builtins. Falls back to the definitions in the
|
||||
@@ -133,6 +145,8 @@ namespace snmalloc
|
||||
# include "aal_x86_sgx.h"
|
||||
#elif defined(PLATFORM_IS_ARM)
|
||||
# include "aal_arm.h"
|
||||
#elif defined(PLATFORM_IS_POWERPC)
|
||||
# include "aal_powerpc.h"
|
||||
#endif
|
||||
|
||||
namespace snmalloc
|
||||
|
||||
@@ -27,6 +27,10 @@ namespace snmalloc
|
||||
static constexpr uint64_t aal_features =
|
||||
IntegerPointers | NoCpuCycleCounters;
|
||||
|
||||
static constexpr enum AalName aal_name = ARM;
|
||||
|
||||
static constexpr size_t smallest_page_size = 0x1000;
|
||||
|
||||
/**
|
||||
* On pipelined processors, notify the core that we are in a spin loop and
|
||||
* that speculative execution past this point may not be a performance gain.
|
||||
|
||||
37
src/aal/aal_powerpc.h
Normal file
37
src/aal/aal_powerpc.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(__powerpc64__)
|
||||
# define SNMALLOC_VA_BITS_64
|
||||
#else
|
||||
# define SNMALLOC_VA_BITS_32
|
||||
#endif
|
||||
|
||||
namespace snmalloc
|
||||
{
|
||||
/**
|
||||
* ARM-specific architecture abstraction layer.
|
||||
*/
|
||||
class AAL_PowerPC
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Bitmap of AalFeature flags
|
||||
*/
|
||||
static constexpr uint64_t aal_features = IntegerPointers;
|
||||
|
||||
static constexpr enum AalName aal_name = PowerPC;
|
||||
|
||||
static constexpr size_t smallest_page_size = 0x1000;
|
||||
|
||||
/**
|
||||
* On pipelined processors, notify the core that we are in a spin loop and
|
||||
* that speculative execution past this point may not be a performance gain.
|
||||
*/
|
||||
static inline void pause()
|
||||
{
|
||||
__asm__ volatile("or 27,27,27"); // "yield"
|
||||
}
|
||||
};
|
||||
|
||||
using AAL_Arch = AAL_PowerPC;
|
||||
} // namespace snmalloc
|
||||
@@ -60,6 +60,10 @@ namespace snmalloc
|
||||
*/
|
||||
static constexpr uint64_t aal_features = IntegerPointers;
|
||||
|
||||
static constexpr enum AalName aal_name = X86;
|
||||
|
||||
static constexpr size_t smallest_page_size = 0x1000;
|
||||
|
||||
/**
|
||||
* On pipelined processors, notify the core that we are in a spin loop and
|
||||
* that speculative execution past this point may not be a performance gain.
|
||||
|
||||
@@ -26,6 +26,10 @@ namespace snmalloc
|
||||
*/
|
||||
static constexpr uint64_t aal_features = IntegerPointers;
|
||||
|
||||
static constexpr enum AalName aal_name = X86_SGX;
|
||||
|
||||
static constexpr size_t smallest_page_size = 0x1000;
|
||||
|
||||
/**
|
||||
* On pipelined processors, notify the core that we are in a spin loop and
|
||||
* that speculative execution past this point may not be a performance gain.
|
||||
|
||||
@@ -733,12 +733,6 @@ namespace snmalloc
|
||||
size_t size1 = sizeclass_to_size(sc1);
|
||||
size_t size2 = sizeclass_to_size(sc2);
|
||||
|
||||
// All medium size classes are page aligned.
|
||||
if (i > NUM_SMALL_CLASSES)
|
||||
{
|
||||
SNMALLOC_ASSERT(is_aligned_block<OS_PAGE_SIZE>(nullptr, size1));
|
||||
}
|
||||
|
||||
SNMALLOC_ASSERT(sc1 == i);
|
||||
SNMALLOC_ASSERT(sc1 == sc2);
|
||||
SNMALLOC_ASSERT(size1 == size);
|
||||
|
||||
@@ -92,18 +92,7 @@ namespace snmalloc
|
||||
// Used to isolate values on cache lines to prevent false sharing.
|
||||
static constexpr size_t CACHELINE_SIZE = 64;
|
||||
|
||||
// Used to keep Superslab metadata committed.
|
||||
static constexpr size_t OS_PAGE_SIZE = 0x1000;
|
||||
static constexpr size_t PAGE_ALIGNED_SIZE = OS_PAGE_SIZE << INTERMEDIATE_BITS;
|
||||
// Some system headers (e.g. Linux' sys/user.h, FreeBSD's machine/param.h)
|
||||
// define `PAGE_SIZE` as a macro. We don't use `PAGE_SIZE` as our variable
|
||||
// name, to avoid conflicts, but if we do see a macro definition then check
|
||||
// that our value matches the platform's expected value.
|
||||
#ifdef PAGE_SIZE
|
||||
static_assert(
|
||||
PAGE_SIZE == OS_PAGE_SIZE,
|
||||
"Page size from system header does not match snmalloc config page size.");
|
||||
#endif
|
||||
|
||||
// Minimum allocation size is space for two pointers.
|
||||
static_assert(bits::next_pow2_const(sizeof(void*)) == sizeof(void*));
|
||||
|
||||
@@ -85,11 +85,10 @@ namespace snmalloc
|
||||
void* p = pointer_offset(this, (static_cast<size_t>(index) << 8));
|
||||
free--;
|
||||
|
||||
SNMALLOC_ASSERT(is_aligned_block<OS_PAGE_SIZE>(p, OS_PAGE_SIZE));
|
||||
size = bits::align_up(size, OS_PAGE_SIZE);
|
||||
|
||||
if constexpr (zero_mem == YesZero)
|
||||
memory_provider.template zero<true>(p, size);
|
||||
memory_provider.zero(p, size);
|
||||
else
|
||||
UNUSED(size);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "../pal/pal_consts.h"
|
||||
#include "../pal/pal.h"
|
||||
#include "allocconfig.h"
|
||||
|
||||
namespace snmalloc
|
||||
|
||||
@@ -59,4 +59,25 @@ namespace snmalloc
|
||||
*/
|
||||
template<PalFeatures F, typename PAL = Pal>
|
||||
constexpr static bool pal_supports = (PAL::pal_features & F) == F;
|
||||
|
||||
// Used to keep Superslab metadata committed.
|
||||
static constexpr size_t OS_PAGE_SIZE = Pal::page_size;
|
||||
|
||||
static_assert(
|
||||
bits::next_pow2_const(OS_PAGE_SIZE) == OS_PAGE_SIZE,
|
||||
"OS_PAGE_SIZE must be a power of two");
|
||||
static_assert(
|
||||
OS_PAGE_SIZE % Aal::smallest_page_size == 0,
|
||||
"The smallest architectural page size must divide OS_PAGE_SIZE");
|
||||
|
||||
// Some system headers (e.g. Linux' sys/user.h, FreeBSD's machine/param.h)
|
||||
// define `PAGE_SIZE` as a macro. We don't use `PAGE_SIZE` as our variable
|
||||
// name, to avoid conflicts, but if we do see a macro definition then check
|
||||
// that our value matches the platform's expected value.
|
||||
#ifdef PAGE_SIZE
|
||||
static_assert(
|
||||
PAGE_SIZE == OS_PAGE_SIZE,
|
||||
"Page size from system header does not match snmalloc config page size.");
|
||||
#endif
|
||||
|
||||
} // namespace snmalloc
|
||||
|
||||
@@ -32,9 +32,9 @@ namespace snmalloc
|
||||
template<bool page_aligned = false>
|
||||
void zero(void* p, size_t size)
|
||||
{
|
||||
if (page_aligned || is_aligned_block<OS_PAGE_SIZE>(p, size))
|
||||
if (page_aligned || is_aligned_block<page_size>(p, size))
|
||||
{
|
||||
SNMALLOC_ASSERT(is_aligned_block<OS_PAGE_SIZE>(p, size));
|
||||
SNMALLOC_ASSERT(is_aligned_block<page_size>(p, size));
|
||||
void* r = mmap(
|
||||
p,
|
||||
size,
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace snmalloc
|
||||
*/
|
||||
void notify_not_using(void* p, size_t size) noexcept
|
||||
{
|
||||
SNMALLOC_ASSERT(is_aligned_block<OS_PAGE_SIZE>(p, size));
|
||||
SNMALLOC_ASSERT(is_aligned_block<OS::page_size>(p, size));
|
||||
madvise(p, size, MADV_FREE);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "../ds/bits.h"
|
||||
#include "../mem/allocconfig.h"
|
||||
|
||||
#if defined(FreeBSD_KERNEL)
|
||||
extern "C"
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
#if defined(__linux__)
|
||||
# include "../ds/bits.h"
|
||||
# include "../mem/allocconfig.h"
|
||||
# include "pal_posix.h"
|
||||
|
||||
# include <string.h>
|
||||
@@ -26,6 +25,9 @@ namespace snmalloc
|
||||
*/
|
||||
static constexpr uint64_t pal_features = PALPOSIX::pal_features;
|
||||
|
||||
static constexpr size_t page_size =
|
||||
Aal::aal_name == PowerPC ? 0x10000 : 0x1000;
|
||||
|
||||
/**
|
||||
* OS specific function for zeroing memory.
|
||||
*
|
||||
@@ -41,12 +43,12 @@ namespace snmalloc
|
||||
// MADV_DONTNEED. switch back to memset only for QEMU.
|
||||
# ifndef SNMALLOC_QEMU_WORKAROUND
|
||||
if (
|
||||
(page_aligned || is_aligned_block<OS_PAGE_SIZE>(p, size)) &&
|
||||
(size > SLAB_SIZE))
|
||||
(page_aligned || is_aligned_block<page_size>(p, size)) &&
|
||||
(size > 16 * page_size))
|
||||
{
|
||||
// Only use this on large allocations as memset faster, and doesn't
|
||||
// introduce IPI so faster for small allocations.
|
||||
SNMALLOC_ASSERT(is_aligned_block<OS_PAGE_SIZE>(p, size));
|
||||
SNMALLOC_ASSERT(is_aligned_block<page_size>(p, size));
|
||||
madvise(p, size, MADV_DONTNEED);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -19,6 +19,9 @@ namespace snmalloc
|
||||
* PAL supports.
|
||||
*/
|
||||
static constexpr uint64_t pal_features = 0;
|
||||
|
||||
static constexpr size_t page_size = 0x1000;
|
||||
|
||||
[[noreturn]] static void error(const char* const str)
|
||||
{
|
||||
UNUSED(str);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "../ds/bits.h"
|
||||
#include "../mem/allocconfig.h"
|
||||
|
||||
namespace snmalloc
|
||||
{
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "../ds/address.h"
|
||||
#include "../mem/allocconfig.h"
|
||||
#if defined(BACKTRACE_HEADER)
|
||||
# include BACKTRACE_HEADER
|
||||
#endif
|
||||
@@ -39,6 +38,8 @@ namespace snmalloc
|
||||
*/
|
||||
static constexpr uint64_t pal_features = LazyCommit;
|
||||
|
||||
static constexpr size_t page_size = 0x1000;
|
||||
|
||||
static void print_stack_trace()
|
||||
{
|
||||
#ifdef BACKTRACE_HEADER
|
||||
@@ -72,7 +73,7 @@ namespace snmalloc
|
||||
*/
|
||||
void notify_not_using(void* p, size_t size) noexcept
|
||||
{
|
||||
SNMALLOC_ASSERT(is_aligned_block<OS_PAGE_SIZE>(p, size));
|
||||
SNMALLOC_ASSERT(is_aligned_block<OS::page_size>(p, size));
|
||||
#ifdef USE_POSIX_COMMIT_CHECKS
|
||||
mprotect(p, size, PROT_NONE);
|
||||
#else
|
||||
@@ -92,7 +93,7 @@ namespace snmalloc
|
||||
void notify_using(void* p, size_t size) noexcept
|
||||
{
|
||||
SNMALLOC_ASSERT(
|
||||
is_aligned_block<OS_PAGE_SIZE>(p, size) || (zero_mem == NoZero));
|
||||
is_aligned_block<OS::page_size>(p, size) || (zero_mem == NoZero));
|
||||
|
||||
#ifdef USE_POSIX_COMMIT_CHECKS
|
||||
mprotect(p, size, PROT_READ | PROT_WRITE);
|
||||
@@ -119,9 +120,9 @@ namespace snmalloc
|
||||
template<bool page_aligned = false>
|
||||
void zero(void* p, size_t size) noexcept
|
||||
{
|
||||
if (page_aligned || is_aligned_block<OS_PAGE_SIZE>(p, size))
|
||||
if (page_aligned || is_aligned_block<OS::page_size>(p, size))
|
||||
{
|
||||
SNMALLOC_ASSERT(is_aligned_block<OS_PAGE_SIZE>(p, size));
|
||||
SNMALLOC_ASSERT(is_aligned_block<OS::page_size>(p, size));
|
||||
void* r = mmap(
|
||||
p,
|
||||
size,
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
#include "../ds/address.h"
|
||||
#include "../ds/bits.h"
|
||||
#include "../mem/allocconfig.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
# ifndef _MSC_VER
|
||||
@@ -83,6 +82,8 @@ namespace snmalloc
|
||||
# endif
|
||||
;
|
||||
|
||||
static constexpr size_t page_size = 0x1000;
|
||||
|
||||
/**
|
||||
* Check whether the low memory state is still in effect. This is an
|
||||
* expensive operation and should not be on any fast paths.
|
||||
@@ -115,7 +116,7 @@ namespace snmalloc
|
||||
/// Notify platform that we will not be using these pages
|
||||
void notify_not_using(void* p, size_t size) noexcept
|
||||
{
|
||||
SNMALLOC_ASSERT(is_aligned_block<OS_PAGE_SIZE>(p, size));
|
||||
SNMALLOC_ASSERT(is_aligned_block<page_size>(p, size));
|
||||
|
||||
BOOL ok = VirtualFree(p, size, MEM_DECOMMIT);
|
||||
|
||||
@@ -128,7 +129,7 @@ namespace snmalloc
|
||||
void notify_using(void* p, size_t size) noexcept
|
||||
{
|
||||
SNMALLOC_ASSERT(
|
||||
is_aligned_block<OS_PAGE_SIZE>(p, size) || (zero_mem == NoZero));
|
||||
is_aligned_block<page_size>(p, size) || (zero_mem == NoZero));
|
||||
|
||||
void* r = VirtualAlloc(p, size, MEM_COMMIT, PAGE_READWRITE);
|
||||
|
||||
@@ -140,9 +141,9 @@ namespace snmalloc
|
||||
template<bool page_aligned = false>
|
||||
void zero(void* p, size_t size) noexcept
|
||||
{
|
||||
if (page_aligned || is_aligned_block<OS_PAGE_SIZE>(p, size))
|
||||
if (page_aligned || is_aligned_block<page_size>(p, size))
|
||||
{
|
||||
SNMALLOC_ASSERT(is_aligned_block<OS_PAGE_SIZE>(p, size));
|
||||
SNMALLOC_ASSERT(is_aligned_block<page_size>(p, size));
|
||||
notify_not_using(p, size);
|
||||
notify_using<YesZero>(p, size);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user