#pragma once
#include "../aal/aal.h"
#include "pal_concept.h"
#include "pal_consts.h"
#if defined(OPEN_ENCLAVE)
# include "pal_open_enclave.h"
#endif
#if !defined(OPEN_ENCLAVE) || defined(OPEN_ENCLAVE_SIMULATION)
# include "pal_apple.h"
# include "pal_dragonfly.h"
# include "pal_freebsd.h"
# include "pal_freebsd_kernel.h"
# include "pal_haiku.h"
# include "pal_linux.h"
# include "pal_netbsd.h"
# include "pal_openbsd.h"
# include "pal_solaris.h"
# include "pal_windows.h"
#endif
#include "pal_noalloc.h"
#include "pal_plain.h"
namespace snmalloc
{
using DefaultPal =
#if defined(SNMALLOC_MEMORY_PROVIDER)
SNMALLOC_MEMORY_PROVIDER;
#elif defined(OPEN_ENCLAVE)
PALOpenEnclave;
#elif defined(_WIN32)
PALWindows;
#elif defined(__APPLE__)
PALApple<>;
#elif defined(__linux__)
PALLinux;
#elif defined(FreeBSD_KERNEL)
PALFreeBSDKernel;
#elif defined(__FreeBSD__)
PALFreeBSD;
#elif defined(__HAIKU__)
PALHaiku;
#elif defined(__NetBSD__)
PALNetBSD;
#elif defined(__OpenBSD__)
PALOpenBSD;
#elif defined(__sun)
PALSolaris;
#elif defined(__DragonFly__)
PALDragonfly;
#else
# error Unsupported platform
#endif
[[noreturn]] SNMALLOC_SLOW_PATH inline void error(const char* const str)
{
DefaultPal::error(str);
}
static constexpr size_t OS_PAGE_SIZE = DefaultPal::page_size;
template<
typename PAL = DefaultPal,
typename AAL = Aal,
typename T,
SNMALLOC_CONCEPT(capptr::IsBound) B>
static inline typename stl::enable_if_t<
!aal_supports<StrictProvenance, AAL>,
CapPtr<T, capptr::user_address_control_type<B>>>
capptr_to_user_address_control(CapPtr<T, B> p)
{
return CapPtr<T, capptr::user_address_control_type<B>>::unsafe_from(
p.unsafe_ptr());
}
template<
typename PAL = DefaultPal,
typename AAL = Aal,
typename T,
SNMALLOC_CONCEPT(capptr::IsBound) B>
static SNMALLOC_FAST_PATH typename stl::enable_if_t<
aal_supports<StrictProvenance, AAL>,
CapPtr<T, capptr::user_address_control_type<B>>>
capptr_to_user_address_control(CapPtr<T, B> p)
{
return PAL::capptr_to_user_address_control(p);
}
template<
typename PAL,
bool page_aligned = false,
typename T,
SNMALLOC_CONCEPT(capptr::IsBound) B>
static SNMALLOC_FAST_PATH void pal_zero(CapPtr<T, B> p, size_t sz)
{
static_assert(
!page_aligned || B::spatial >= capptr::dimension::Spatial::Chunk);
PAL::template zero<page_aligned>(p.unsafe_ptr(), sz);
}
static_assert(
bits::is_pow2(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");
#ifdef PAGE_SIZE
static_assert(
# if __has_builtin(__builtin_constant_p)
!__builtin_constant_p(PAGE_SIZE) || (PAGE_SIZE == OS_PAGE_SIZE),
# else
true,
# endif
"Page size from system header does not match snmalloc config page size.");
#endif
template<size_t BufferSize, typename... Args>
[[noreturn]] inline void report_fatal_error(Args... args)
{
MessageBuilder<BufferSize> msg{stl::forward<Args>(args)...};
DefaultPal::error(msg.get_message());
}
template<size_t BufferSize, typename... Args>
inline void message(Args... args)
{
MessageBuilder<BufferSize> msg{stl::forward<Args>(args)...};
MessageBuilder<BufferSize> msg_tid{
"{}: {}", debug_get_tid(), msg.get_message()};
DefaultPal::message(msg_tid.get_message());
}
}