Files
snmalloc/src/pal/pal_concept.h
David Chisnall c33f355736 Fix the sandbox use case and add a test. (#269)
Summary of changes:

- Add a new PAL that doesn't allocate memory, which can be used with a
  memory provider that is pre-initialised with a range of memory.
- Add a `NoAllocation` PAL property so that the methods on a PAL that 
  doesn't support dynamically reserving address space will never be
  called and therefore don't need to be implemented.
- Slightly refactor the memory provider class so that it has a narrower
  interface with LargeAlloc and is easier to proxy.
- Allow the address space manager and the memory provider to be
  initialised with a range of memory.

This may eventually also remove the need for (or, at least, simplify)
the Open Enclave PAL.

This commit also ends up with a few other cleanups:

 - The `malloc_useable_size` CMake test that checks whether the
   parameter is const qualified was failing on FreeBSD where this
   function is declared in `malloc_np.h` but where including
   `malloc.h` raises an error.  This should now be more robust.
 - The BSD aligned PAL inherited from the BSD PAL, which does not
   expose aligned allocation. This meant that it exposed both the
   aligned and non-aligned allocation interfaces and so happily
   accepted incorrect `constexpr` if blocks that expected one or 
   the other but accidentally required both to exist. The unaligned
   function is now deleted so the same failures that appear in CI should
   appear locally for anyone using this PAL.
2021-01-11 14:06:51 +00:00

103 lines
3.2 KiB
C++

#pragma once
#ifdef __cpp_concepts
# include "../ds/concept.h"
# include "pal_consts.h"
# include <utility>
namespace snmalloc
{
/**
* PALs must advertize the bit vector of their supported features and the
* platform's page size. This concept enforces that these are indeed
* constants that fit in the desired types. (This is subtly different from
* saying that they are the required types; C++ may handle constants without
* much regard for their claimed type.)
*/
template<typename PAL>
concept ConceptPAL_static_members = requires()
{
typename std::integral_constant<uint64_t, PAL::pal_features>;
typename std::integral_constant<size_t, PAL::page_size>;
};
/**
* PALs expose an error reporting function which takes a const C string.
*/
template<typename PAL>
concept ConceptPAL_error = requires(const char* const str)
{
{ PAL::error(str) } -> ConceptSame<void>;
};
/**
* PALs expose a basic library of memory operations.
*/
template<typename PAL>
concept ConceptPAL_memops = requires(void* vp, size_t sz)
{
{ PAL::notify_not_using(vp, sz) } noexcept -> ConceptSame<void>;
{ PAL::template notify_using<NoZero>(vp, sz) } noexcept
-> ConceptSame<void>;
{ PAL::template notify_using<YesZero>(vp, sz) } noexcept
-> ConceptSame<void>;
{ PAL::template zero<false>(vp, sz) } noexcept -> ConceptSame<void>;
{ PAL::template zero<true>(vp, sz) } noexcept -> ConceptSame<void>;
};
/**
* Absent any feature flags, the PAL must support a crude primitive allocator
*/
template<typename PAL>
concept ConceptPAL_reserve_at_least = requires(PAL p, void* vp, size_t sz)
{
{ PAL::reserve_at_least(sz) } noexcept
-> ConceptSame<std::pair<void*, size_t>>;
};
/**
* Some PALs expose a richer allocator which understands aligned allocations
*/
template<typename PAL>
concept ConceptPAL_reserve_aligned = requires(size_t sz)
{
{ PAL::template reserve_aligned<true>(sz) } noexcept -> ConceptSame<void*>;
{ PAL::template reserve_aligned<false>(sz) } noexcept
-> ConceptSame<void*>;
};
/**
* Some PALs can provide memory pressure callbacks.
*/
template<typename PAL>
concept ConceptPAL_mem_low_notify = requires(PalNotificationObject* pno)
{
{ PAL::expensive_low_memory_check() } -> ConceptSame<bool>;
{ PAL::register_for_low_memory_callback(pno) } -> ConceptSame<void>;
};
/**
* PALs ascribe to the conjunction of several concepts. These are broken
* out by the shape of the requires() quantifiers required and by any
* requisite claimed pal_features. PALs not claiming particular features
* are, naturally, not bound by the corresponding concept.
*/
template<typename PAL>
concept ConceptPAL =
ConceptPAL_static_members<PAL> &&
ConceptPAL_error<PAL> &&
ConceptPAL_memops<PAL> &&
(!(PAL::pal_features & LowMemoryNotification) ||
ConceptPAL_mem_low_notify<PAL>) &&
(!(PAL::pal_features & NoAllocation) && (
(!!(PAL::pal_features & AlignedAllocation) ||
ConceptPAL_reserve_at_least<PAL>) &&
(!(PAL::pal_features & AlignedAllocation) ||
ConceptPAL_reserve_aligned<PAL>)));
} // namespace snmalloc
#endif