Move to clang-format 15 (#621)
The current version requires clang-format-9. This now getting hard to get. This commit moves it to the clang-format-15, which is the latest in 22.04. Also, updates clang-tidy to 15 as well.
This commit is contained in:
committed by
GitHub
parent
cdfedd8718
commit
9d4466093a
8
.github/workflows/main.yml
vendored
8
.github/workflows/main.yml
vendored
@@ -400,12 +400,14 @@ jobs:
|
||||
|
||||
# Job to run clang-format and report errors
|
||||
format:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
# We don't need to do the build for this job, but we need to configure it to get the clang-format target
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install clang-tidy and clang-format
|
||||
run: sudo apt install clang-tidy-9 clang-format-9
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install clang-tidy-15 clang-format-15
|
||||
- name: Configure CMake
|
||||
run: cmake -B ${{github.workspace}}/build -DSNMALLOC_USE_CXX17=ON
|
||||
# Run the clang-format check and error if it generates a diff
|
||||
@@ -417,7 +419,7 @@ jobs:
|
||||
git diff --exit-code
|
||||
- name: Run clang-tidy
|
||||
run: |
|
||||
clang-tidy-9 src/snmalloc/override/malloc.cc -header-filter="`pwd`/*" -warnings-as-errors='*' -export-fixes=tidy.fail -- -std=c++17 -mcx16 -DSNMALLOC_PLATFORM_HAS_GETENTROPY=0
|
||||
clang-tidy-15 src/snmalloc/override/malloc.cc -header-filter="`pwd`/*" -warnings-as-errors='*' -export-fixes=tidy.fail -- -std=c++17 -mcx16 -DSNMALLOC_PLATFORM_HAS_GETENTROPY=0
|
||||
if [ -f tidy.fail ] ; then
|
||||
cat tidy.fail
|
||||
exit 1
|
||||
|
||||
@@ -150,7 +150,7 @@ function(clangformat_targets)
|
||||
# tool. It does not work with older versions as AfterCaseLabel is not supported
|
||||
# in earlier versions.
|
||||
find_program(CLANG_FORMAT NAMES
|
||||
clang-format90 clang-format-9)
|
||||
clang-format150 clang-format-15)
|
||||
|
||||
# If we've found a clang-format tool, generate a target for it, otherwise emit
|
||||
# a warning.
|
||||
|
||||
@@ -14,87 +14,79 @@ namespace snmalloc
|
||||
* machine word size, and an upper bound on the address space size
|
||||
*/
|
||||
template<typename AAL>
|
||||
concept IsAAL_static_members = requires()
|
||||
{
|
||||
typename std::integral_constant<uint64_t, AAL::aal_features>;
|
||||
typename std::integral_constant<int, AAL::aal_name>;
|
||||
typename std::integral_constant<std::size_t, AAL::bits>;
|
||||
typename std::integral_constant<std::size_t, AAL::address_bits>;
|
||||
};
|
||||
concept IsAAL_static_members =
|
||||
requires() {
|
||||
typename std::integral_constant<uint64_t, AAL::aal_features>;
|
||||
typename std::integral_constant<int, AAL::aal_name>;
|
||||
typename std::integral_constant<std::size_t, AAL::bits>;
|
||||
typename std::integral_constant<std::size_t, AAL::address_bits>;
|
||||
};
|
||||
|
||||
/**
|
||||
* AALs provide a prefetch operation.
|
||||
*/
|
||||
template<typename AAL>
|
||||
concept IsAAL_prefetch = requires(void* ptr)
|
||||
{
|
||||
{
|
||||
AAL::prefetch(ptr)
|
||||
}
|
||||
noexcept->ConceptSame<void>;
|
||||
};
|
||||
concept IsAAL_prefetch = requires(void* ptr) {
|
||||
{
|
||||
AAL::prefetch(ptr)
|
||||
} noexcept -> ConceptSame<void>;
|
||||
};
|
||||
|
||||
/**
|
||||
* AALs provide a notion of high-precision timing.
|
||||
*/
|
||||
template<typename AAL>
|
||||
concept IsAAL_tick = requires()
|
||||
{
|
||||
{
|
||||
AAL::tick()
|
||||
}
|
||||
noexcept->ConceptSame<uint64_t>;
|
||||
};
|
||||
concept IsAAL_tick = requires() {
|
||||
{
|
||||
AAL::tick()
|
||||
} noexcept -> ConceptSame<uint64_t>;
|
||||
};
|
||||
|
||||
template<typename AAL>
|
||||
concept IsAAL_capptr_methods =
|
||||
requires(capptr::Chunk<void> auth, capptr::AllocFull<void> ret, size_t sz)
|
||||
{
|
||||
/**
|
||||
* Produce a pointer with reduced authority from a more privilged pointer.
|
||||
* The resulting pointer will have base at auth's address and length of
|
||||
* exactly sz. auth+sz must not exceed auth's limit.
|
||||
*/
|
||||
{
|
||||
AAL::template capptr_bound<void, capptr::bounds::Chunk>(auth, sz)
|
||||
}
|
||||
noexcept->ConceptSame<capptr::Chunk<void>>;
|
||||
requires(capptr::Chunk<void> auth, capptr::AllocFull<void> ret, size_t sz) {
|
||||
/**
|
||||
* Produce a pointer with reduced authority from a more privilged pointer.
|
||||
* The resulting pointer will have base at auth's address and length of
|
||||
* exactly sz. auth+sz must not exceed auth's limit.
|
||||
*/
|
||||
{
|
||||
AAL::template capptr_bound<void, capptr::bounds::Chunk>(auth, sz)
|
||||
} noexcept -> ConceptSame<capptr::Chunk<void>>;
|
||||
|
||||
/**
|
||||
* "Amplify" by copying the address of one pointer into one of higher
|
||||
* privilege. The resulting pointer differs from auth only in address.
|
||||
*/
|
||||
{
|
||||
AAL::capptr_rebound(auth, ret)
|
||||
}
|
||||
noexcept->ConceptSame<capptr::Chunk<void>>;
|
||||
/**
|
||||
* "Amplify" by copying the address of one pointer into one of higher
|
||||
* privilege. The resulting pointer differs from auth only in address.
|
||||
*/
|
||||
{
|
||||
AAL::capptr_rebound(auth, ret)
|
||||
} noexcept -> ConceptSame<capptr::Chunk<void>>;
|
||||
|
||||
/**
|
||||
* Round up an allocation size to a size this architecture can represent.
|
||||
* While there may also, in general, be alignment requirements for
|
||||
* representability, in snmalloc so far we have not had reason to consider
|
||||
* these explicitly: when we use our...
|
||||
*
|
||||
* - sizeclass machinery (for user-facing data), we assume that all
|
||||
* sizeclasses describe architecturally representable aligned-and-sized
|
||||
* regions
|
||||
*
|
||||
* - Range machinery (for internal meta-data), we always choose NAPOT
|
||||
* regions big enough for the requested size (returning space above the
|
||||
* allocation within such regions for use as smaller NAPOT regions).
|
||||
*
|
||||
* That is, capptr_size_round is not needed on the user-facing fast paths,
|
||||
* merely internally for bootstrap and metadata management.
|
||||
*/
|
||||
{
|
||||
AAL::capptr_size_round(sz)
|
||||
}
|
||||
noexcept->ConceptSame<size_t>;
|
||||
};
|
||||
/**
|
||||
* Round up an allocation size to a size this architecture can represent.
|
||||
* While there may also, in general, be alignment requirements for
|
||||
* representability, in snmalloc so far we have not had reason to consider
|
||||
* these explicitly: when we use our...
|
||||
*
|
||||
* - sizeclass machinery (for user-facing data), we assume that all
|
||||
* sizeclasses describe architecturally representable aligned-and-sized
|
||||
* regions
|
||||
*
|
||||
* - Range machinery (for internal meta-data), we always choose NAPOT
|
||||
* regions big enough for the requested size (returning space above the
|
||||
* allocation within such regions for use as smaller NAPOT regions).
|
||||
*
|
||||
* That is, capptr_size_round is not needed on the user-facing fast paths,
|
||||
* merely internally for bootstrap and metadata management.
|
||||
*/
|
||||
{
|
||||
AAL::capptr_size_round(sz)
|
||||
} noexcept -> ConceptSame<size_t>;
|
||||
};
|
||||
|
||||
template<typename AAL>
|
||||
concept IsAAL = IsAAL_static_members<AAL>&& IsAAL_prefetch<AAL>&&
|
||||
IsAAL_tick<AAL>&& IsAAL_capptr_methods<AAL>;
|
||||
concept IsAAL = IsAAL_static_members<AAL> && IsAAL_prefetch<AAL> &&
|
||||
IsAAL_tick<AAL> && IsAAL_capptr_methods<AAL>;
|
||||
|
||||
} // namespace snmalloc
|
||||
#endif
|
||||
|
||||
@@ -63,13 +63,11 @@ namespace snmalloc
|
||||
* C++, and not just its initializer fragment, to initialize a non-prefix
|
||||
* subset of the flags (in any order, at that).
|
||||
*/
|
||||
static constexpr Flags Options = []() constexpr
|
||||
{
|
||||
static constexpr Flags Options = []() constexpr {
|
||||
Flags opts = {};
|
||||
opts.HasDomesticate = true;
|
||||
return opts;
|
||||
}
|
||||
();
|
||||
}();
|
||||
|
||||
// This needs to be a forward reference as the
|
||||
// thread local state will need to know about this.
|
||||
|
||||
@@ -71,9 +71,10 @@ namespace snmalloc
|
||||
error("Only one inflight ABA operation at a time is allowed.");
|
||||
operation_in_flight = true;
|
||||
# endif
|
||||
return Cmp{{independent.ptr.load(std::memory_order_relaxed),
|
||||
independent.aba.load(std::memory_order_relaxed)},
|
||||
this};
|
||||
return Cmp{
|
||||
{independent.ptr.load(std::memory_order_relaxed),
|
||||
independent.aba.load(std::memory_order_relaxed)},
|
||||
this};
|
||||
}
|
||||
|
||||
struct Cmp
|
||||
|
||||
@@ -324,7 +324,7 @@ namespace snmalloc
|
||||
}
|
||||
std::array<char, 20> buf{{0}};
|
||||
const char digits[] = "0123456789";
|
||||
for (long i = long(buf.size() - 1); i >= 0; i--)
|
||||
for (long i = static_cast<long>(buf.size() - 1); i >= 0; i--)
|
||||
{
|
||||
buf[static_cast<size_t>(i)] = digits[s % 10];
|
||||
s /= 10;
|
||||
@@ -356,7 +356,7 @@ namespace snmalloc
|
||||
const char hexdigits[] = "0123456789abcdef";
|
||||
// Length of string including null terminator
|
||||
static_assert(sizeof(hexdigits) == 0x11);
|
||||
for (long i = long(buf.size() - 1); i >= 0; i--)
|
||||
for (long i = static_cast<long>(buf.size() - 1); i >= 0; i--)
|
||||
{
|
||||
buf[static_cast<size_t>(i)] = hexdigits[s & 0xf];
|
||||
s >>= 4;
|
||||
|
||||
@@ -247,10 +247,10 @@ namespace snmalloc
|
||||
*/
|
||||
full_checks + cheri_checks + clear_meta - freelist_forward_edge -
|
||||
pal_enforce_access :
|
||||
/**
|
||||
* clear_meta is important on CHERI to avoid leaking capabilities.
|
||||
*/
|
||||
sanity_checks + cheri_checks + clear_meta;
|
||||
/**
|
||||
* clear_meta is important on CHERI to avoid leaking capabilities.
|
||||
*/
|
||||
sanity_checks + cheri_checks + clear_meta;
|
||||
#else
|
||||
CHECK_CLIENT ? full_checks : no_checks;
|
||||
#endif
|
||||
|
||||
@@ -17,11 +17,10 @@ namespace snmalloc
|
||||
* ID.
|
||||
*/
|
||||
template<typename Rep>
|
||||
concept RBRepTypes = requires()
|
||||
{
|
||||
typename Rep::Handle;
|
||||
typename Rep::Contents;
|
||||
};
|
||||
concept RBRepTypes = requires() {
|
||||
typename Rep::Handle;
|
||||
typename Rep::Contents;
|
||||
};
|
||||
|
||||
/**
|
||||
* The representation must define operations on the holder and contents
|
||||
@@ -41,50 +40,36 @@ namespace snmalloc
|
||||
*/
|
||||
template<typename Rep>
|
||||
concept RBRepMethods =
|
||||
requires(typename Rep::Handle hp, typename Rep::Contents k, bool b)
|
||||
{
|
||||
{
|
||||
Rep::get(hp)
|
||||
}
|
||||
->ConceptSame<typename Rep::Contents>;
|
||||
{
|
||||
Rep::set(hp, k)
|
||||
}
|
||||
->ConceptSame<void>;
|
||||
{
|
||||
Rep::is_red(k)
|
||||
}
|
||||
->ConceptSame<bool>;
|
||||
{
|
||||
Rep::set_red(k, b)
|
||||
}
|
||||
->ConceptSame<void>;
|
||||
{
|
||||
Rep::ref(b, k)
|
||||
}
|
||||
->ConceptSame<typename Rep::Handle>;
|
||||
{
|
||||
Rep::null
|
||||
}
|
||||
->ConceptSameModRef<const typename Rep::Contents>;
|
||||
{
|
||||
typename Rep::Handle
|
||||
requires(typename Rep::Handle hp, typename Rep::Contents k, bool b) {
|
||||
{
|
||||
const_cast<
|
||||
Rep::get(hp)
|
||||
} -> ConceptSame<typename Rep::Contents>;
|
||||
{
|
||||
Rep::set(hp, k)
|
||||
} -> ConceptSame<void>;
|
||||
{
|
||||
Rep::is_red(k)
|
||||
} -> ConceptSame<bool>;
|
||||
{
|
||||
Rep::set_red(k, b)
|
||||
} -> ConceptSame<void>;
|
||||
{
|
||||
Rep::ref(b, k)
|
||||
} -> ConceptSame<typename Rep::Handle>;
|
||||
{
|
||||
Rep::null
|
||||
} -> ConceptSameModRef<const typename Rep::Contents>;
|
||||
{
|
||||
typename Rep::Handle{const_cast<
|
||||
std::remove_const_t<std::remove_reference_t<decltype(Rep::root)>>*>(
|
||||
&Rep::root)
|
||||
}
|
||||
}
|
||||
->ConceptSame<typename Rep::Handle>;
|
||||
};
|
||||
&Rep::root)}
|
||||
} -> ConceptSame<typename Rep::Handle>;
|
||||
};
|
||||
|
||||
template<typename Rep>
|
||||
concept RBRep = //
|
||||
RBRepTypes<Rep> //
|
||||
&& RBRepMethods<Rep> //
|
||||
&& ConceptSame<
|
||||
decltype(Rep::null),
|
||||
std::add_const_t<typename Rep::Contents>>;
|
||||
RBRepTypes<Rep> && RBRepMethods<Rep> &&
|
||||
ConceptSame<decltype(Rep::null), std::add_const_t<typename Rep::Contents>>;
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -275,7 +260,7 @@ namespace snmalloc
|
||||
std::array<RBStep, 128> path;
|
||||
size_t length = 0;
|
||||
|
||||
RBPath(typename Rep::Handle root) : path{}
|
||||
RBPath(typename Rep::Handle root)
|
||||
{
|
||||
path[0].set(root, false);
|
||||
length = 1;
|
||||
@@ -490,8 +475,7 @@ namespace snmalloc
|
||||
*/
|
||||
path.move(true);
|
||||
while (path.move(false))
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
K curr = path.curr();
|
||||
|
||||
@@ -510,8 +494,8 @@ namespace snmalloc
|
||||
// If we had a left child, replace ourselves with the extracted value
|
||||
// from above
|
||||
Rep::set_red(curr, Rep::is_red(splice));
|
||||
get_dir(true, curr) = K(get_dir(true, splice));
|
||||
get_dir(false, curr) = K(get_dir(false, splice));
|
||||
get_dir(true, curr) = K{get_dir(true, splice)};
|
||||
get_dir(false, curr) = K{get_dir(false, splice)};
|
||||
splice = curr;
|
||||
path.fixup();
|
||||
}
|
||||
@@ -742,8 +726,7 @@ namespace snmalloc
|
||||
|
||||
auto path = get_root_path();
|
||||
while (path.move(true))
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
K result = path.curr();
|
||||
|
||||
|
||||
@@ -192,7 +192,8 @@ namespace snmalloc
|
||||
* It's not entirely clear what we would do if this were not the case.
|
||||
* Best not think too hard about it now.
|
||||
*/
|
||||
static_assert(alignof(void*) == sizeof(void*));
|
||||
static_assert(
|
||||
alignof(void*) == sizeof(void*)); // NOLINT(misc-redundant-expression)
|
||||
|
||||
static constexpr size_t LargestRegisterSize = 16;
|
||||
|
||||
|
||||
@@ -14,18 +14,15 @@ namespace snmalloc
|
||||
*/
|
||||
template<typename Pagemap>
|
||||
concept IsReadablePagemap =
|
||||
requires(address_t addr, size_t sz, const typename Pagemap::Entry& t)
|
||||
{
|
||||
{
|
||||
Pagemap::template get_metaentry<true>(addr)
|
||||
}
|
||||
->ConceptSame<const typename Pagemap::Entry&>;
|
||||
requires(address_t addr, size_t sz, const typename Pagemap::Entry& t) {
|
||||
{
|
||||
Pagemap::template get_metaentry<true>(addr)
|
||||
} -> ConceptSame<const typename Pagemap::Entry&>;
|
||||
|
||||
{
|
||||
Pagemap::template get_metaentry<false>(addr)
|
||||
}
|
||||
->ConceptSame<const typename Pagemap::Entry&>;
|
||||
};
|
||||
{
|
||||
Pagemap::template get_metaentry<false>(addr)
|
||||
} -> ConceptSame<const typename Pagemap::Entry&>;
|
||||
};
|
||||
|
||||
/**
|
||||
* The core of the static pagemap accessor interface: {get,set}_metadata.
|
||||
@@ -36,24 +33,20 @@ namespace snmalloc
|
||||
* set_metadata updates the entry in the pagemap.
|
||||
*/
|
||||
template<typename Pagemap>
|
||||
concept IsWritablePagemap = IsReadablePagemap<Pagemap>&& requires(
|
||||
address_t addr, size_t sz, const typename Pagemap::Entry& t)
|
||||
{
|
||||
{
|
||||
Pagemap::template get_metaentry_mut<true>(addr)
|
||||
}
|
||||
->ConceptSame<typename Pagemap::Entry&>;
|
||||
concept IsWritablePagemap = IsReadablePagemap<Pagemap> &&
|
||||
requires(address_t addr, size_t sz, const typename Pagemap::Entry& t) {
|
||||
{
|
||||
Pagemap::template get_metaentry_mut<true>(addr)
|
||||
} -> ConceptSame<typename Pagemap::Entry&>;
|
||||
|
||||
{
|
||||
Pagemap::template get_metaentry_mut<false>(addr)
|
||||
}
|
||||
->ConceptSame<typename Pagemap::Entry&>;
|
||||
{
|
||||
Pagemap::template get_metaentry_mut<false>(addr)
|
||||
} -> ConceptSame<typename Pagemap::Entry&>;
|
||||
|
||||
{
|
||||
Pagemap::set_metaentry(addr, sz, t)
|
||||
}
|
||||
->ConceptSame<void>;
|
||||
};
|
||||
{
|
||||
Pagemap::set_metaentry(addr, sz, t)
|
||||
} -> ConceptSame<void>;
|
||||
};
|
||||
|
||||
/**
|
||||
* The pagemap can also be told to commit backing storage for a range of
|
||||
@@ -63,13 +56,11 @@ namespace snmalloc
|
||||
* which combines this and the core concept, above.
|
||||
*/
|
||||
template<typename Pagemap>
|
||||
concept IsPagemapWithRegister = requires(capptr::Arena<void> p, size_t sz)
|
||||
{
|
||||
{
|
||||
Pagemap::register_range(p, sz)
|
||||
}
|
||||
->ConceptSame<void>;
|
||||
};
|
||||
concept IsPagemapWithRegister = requires(capptr::Arena<void> p, size_t sz) {
|
||||
{
|
||||
Pagemap::register_range(p, sz)
|
||||
} -> ConceptSame<void>;
|
||||
};
|
||||
|
||||
/**
|
||||
* The full pagemap accessor interface, with all of {get,set}_metadata and
|
||||
@@ -81,7 +72,7 @@ namespace snmalloc
|
||||
*/
|
||||
template<typename Pagemap>
|
||||
concept IsWritablePagemapWithRegister =
|
||||
IsWritablePagemap<Pagemap>&& IsPagemapWithRegister<Pagemap>;
|
||||
IsWritablePagemap<Pagemap> && IsPagemapWithRegister<Pagemap>;
|
||||
|
||||
/**
|
||||
* The configuration also defines domestication (that is, the difference
|
||||
@@ -91,62 +82,50 @@ namespace snmalloc
|
||||
*/
|
||||
template<typename Config>
|
||||
concept IsConfigDomestication =
|
||||
requires(typename Config::LocalState* ls, capptr::AllocWild<void> ptr)
|
||||
{
|
||||
{
|
||||
Config::capptr_domesticate(ls, ptr)
|
||||
}
|
||||
->ConceptSame<capptr::Alloc<void>>;
|
||||
requires(typename Config::LocalState* ls, capptr::AllocWild<void> ptr) {
|
||||
{
|
||||
Config::capptr_domesticate(ls, ptr)
|
||||
} -> ConceptSame<capptr::Alloc<void>>;
|
||||
|
||||
{
|
||||
Config::capptr_domesticate(ls, ptr.template as_static<char>())
|
||||
}
|
||||
->ConceptSame<capptr::Alloc<char>>;
|
||||
};
|
||||
{
|
||||
Config::capptr_domesticate(ls, ptr.template as_static<char>())
|
||||
} -> ConceptSame<capptr::Alloc<char>>;
|
||||
};
|
||||
|
||||
class CommonConfig;
|
||||
struct Flags;
|
||||
|
||||
template<typename LocalState, typename PagemapEntry, typename Backend>
|
||||
concept IsBackend =
|
||||
requires(LocalState& local_state, size_t size, uintptr_t ras)
|
||||
{
|
||||
{
|
||||
Backend::alloc_chunk(local_state, size, ras)
|
||||
}
|
||||
->ConceptSame<
|
||||
std::pair<capptr::Chunk<void>, typename Backend::SlabMetadata*>>;
|
||||
}
|
||||
&&requires(LocalState* local_state, size_t size)
|
||||
{
|
||||
{
|
||||
Backend::template alloc_meta_data<void*>(local_state, size)
|
||||
}
|
||||
->ConceptSame<capptr::Alloc<void>>;
|
||||
}
|
||||
&&requires(
|
||||
LocalState& local_state,
|
||||
typename Backend::SlabMetadata& slab_metadata,
|
||||
capptr::Alloc<void> alloc,
|
||||
size_t size)
|
||||
{
|
||||
{
|
||||
Backend::dealloc_chunk(local_state, slab_metadata, alloc, size)
|
||||
}
|
||||
->ConceptSame<void>;
|
||||
}
|
||||
&&requires(address_t p)
|
||||
{
|
||||
{
|
||||
Backend::template get_metaentry<true>(p)
|
||||
}
|
||||
->ConceptSame<const PagemapEntry&>;
|
||||
requires(LocalState& local_state, size_t size, uintptr_t ras) {
|
||||
{
|
||||
Backend::alloc_chunk(local_state, size, ras)
|
||||
} -> ConceptSame<
|
||||
std::pair<capptr::Chunk<void>, typename Backend::SlabMetadata*>>;
|
||||
} &&
|
||||
requires(LocalState* local_state, size_t size) {
|
||||
{
|
||||
Backend::template alloc_meta_data<void*>(local_state, size)
|
||||
} -> ConceptSame<capptr::Alloc<void>>;
|
||||
} &&
|
||||
requires(
|
||||
LocalState& local_state,
|
||||
typename Backend::SlabMetadata& slab_metadata,
|
||||
capptr::Alloc<void> alloc,
|
||||
size_t size) {
|
||||
{
|
||||
Backend::dealloc_chunk(local_state, slab_metadata, alloc, size)
|
||||
} -> ConceptSame<void>;
|
||||
} &&
|
||||
requires(address_t p) {
|
||||
{
|
||||
Backend::template get_metaentry<true>(p)
|
||||
} -> ConceptSame<const PagemapEntry&>;
|
||||
|
||||
{
|
||||
Backend::template get_metaentry<false>(p)
|
||||
}
|
||||
->ConceptSame<const PagemapEntry&>;
|
||||
};
|
||||
{
|
||||
Backend::template get_metaentry<false>(p)
|
||||
} -> ConceptSame<const PagemapEntry&>;
|
||||
};
|
||||
|
||||
/**
|
||||
* Config objects of type T must obey a number of constraints. They
|
||||
@@ -161,38 +140,39 @@ namespace snmalloc
|
||||
*
|
||||
*/
|
||||
template<typename Config>
|
||||
concept IsConfig = std::is_base_of<CommonConfig, Config>::value&&
|
||||
IsPAL<typename Config::Pal>&& IsBackend<
|
||||
typename Config::LocalState,
|
||||
typename Config::PagemapEntry,
|
||||
typename Config::Backend>&& requires()
|
||||
{
|
||||
typename Config::LocalState;
|
||||
typename Config::Backend;
|
||||
typename Config::PagemapEntry;
|
||||
|
||||
{
|
||||
Config::Options
|
||||
}
|
||||
->ConceptSameModRef<const Flags>;
|
||||
}
|
||||
&&(
|
||||
concept IsConfig = std::is_base_of<CommonConfig, Config>::value &&
|
||||
IsPAL<typename Config::Pal> &&
|
||||
IsBackend<typename Config::LocalState,
|
||||
typename Config::PagemapEntry,
|
||||
typename Config::Backend> &&
|
||||
requires() {
|
||||
Config::Options.CoreAllocIsPoolAllocated == true;
|
||||
typename Config::GlobalPoolState;
|
||||
typename Config::LocalState;
|
||||
typename Config::Backend;
|
||||
typename Config::PagemapEntry;
|
||||
|
||||
{
|
||||
Config::pool()
|
||||
}
|
||||
->ConceptSame<typename Config::GlobalPoolState&>;
|
||||
} ||
|
||||
requires() { Config::Options.CoreAllocIsPoolAllocated == false; });
|
||||
Config::Options
|
||||
} -> ConceptSameModRef<const Flags>;
|
||||
} &&
|
||||
(
|
||||
requires() {
|
||||
Config::Options.CoreAllocIsPoolAllocated == true;
|
||||
typename Config::GlobalPoolState;
|
||||
{
|
||||
Config::pool()
|
||||
} -> ConceptSame<typename Config::GlobalPoolState&>;
|
||||
} ||
|
||||
requires() {
|
||||
Config::Options.CoreAllocIsPoolAllocated == false;
|
||||
});
|
||||
|
||||
/**
|
||||
* The lazy version of the above; please see ds_core/concept.h and use
|
||||
* sparingly.
|
||||
*/
|
||||
template<typename Config>
|
||||
concept IsConfigLazy = !is_type_complete_v<Config> || IsConfig<Config>;
|
||||
concept IsConfigLazy = !
|
||||
is_type_complete_v<Config> || IsConfig<Config>;
|
||||
|
||||
} // namespace snmalloc
|
||||
|
||||
|
||||
@@ -167,8 +167,8 @@ namespace snmalloc
|
||||
|
||||
struct SizeClassTable
|
||||
{
|
||||
ModArray<SIZECLASS_REP_SIZE, sizeclass_data_fast> fast_;
|
||||
ModArray<SIZECLASS_REP_SIZE, sizeclass_data_slow> slow_;
|
||||
ModArray<SIZECLASS_REP_SIZE, sizeclass_data_fast> fast_{};
|
||||
ModArray<SIZECLASS_REP_SIZE, sizeclass_data_slow> slow_{};
|
||||
|
||||
size_t DIV_MULT_SHIFT{0};
|
||||
|
||||
@@ -203,7 +203,7 @@ namespace snmalloc
|
||||
return slow_[index.raw()];
|
||||
}
|
||||
|
||||
constexpr SizeClassTable() : fast_(), slow_(), DIV_MULT_SHIFT()
|
||||
constexpr SizeClassTable()
|
||||
{
|
||||
size_t max_capacity = 0;
|
||||
|
||||
|
||||
@@ -116,7 +116,7 @@ extern "C"
|
||||
* now, this is always implemented to return an error.
|
||||
*/
|
||||
SNMALLOC_EXPORT int
|
||||
SNMALLOC_NAME_MANGLE(mallctl)(const char*, void*, size_t*, void*, size_t)
|
||||
SNMALLOC_NAME_MANGLE(mallctl)(const char*, void*, size_t*, void*, size_t)
|
||||
{
|
||||
return ENOENT;
|
||||
}
|
||||
@@ -265,7 +265,7 @@ extern "C"
|
||||
* controlling the thread cache and arena are ignored.
|
||||
*/
|
||||
SNMALLOC_EXPORT void*
|
||||
SNMALLOC_NAME_MANGLE(rallocx)(void* ptr, size_t size, int flags)
|
||||
SNMALLOC_NAME_MANGLE(rallocx)(void* ptr, size_t size, int flags)
|
||||
{
|
||||
auto f = JEMallocFlags(flags);
|
||||
size = f.aligned_size(size);
|
||||
|
||||
@@ -113,7 +113,7 @@ extern "C"
|
||||
|
||||
#if !defined(SNMALLOC_NO_REALLOCARRAY)
|
||||
SNMALLOC_EXPORT void*
|
||||
SNMALLOC_NAME_MANGLE(reallocarray)(void* ptr, size_t nmemb, size_t size)
|
||||
SNMALLOC_NAME_MANGLE(reallocarray)(void* ptr, size_t nmemb, size_t size)
|
||||
{
|
||||
bool overflow = false;
|
||||
size_t sz = bits::umul(size, nmemb, overflow);
|
||||
@@ -128,7 +128,7 @@ extern "C"
|
||||
|
||||
#if !defined(SNMALLOC_NO_REALLOCARR)
|
||||
SNMALLOC_EXPORT int
|
||||
SNMALLOC_NAME_MANGLE(reallocarr)(void* ptr_, size_t nmemb, size_t size)
|
||||
SNMALLOC_NAME_MANGLE(reallocarr)(void* ptr_, size_t nmemb, size_t size)
|
||||
{
|
||||
int err = errno;
|
||||
auto& a = ThreadAlloc::get();
|
||||
@@ -168,7 +168,7 @@ extern "C"
|
||||
#endif
|
||||
|
||||
SNMALLOC_EXPORT void*
|
||||
SNMALLOC_NAME_MANGLE(memalign)(size_t alignment, size_t size)
|
||||
SNMALLOC_NAME_MANGLE(memalign)(size_t alignment, size_t size)
|
||||
{
|
||||
if ((alignment == 0) || (alignment == size_t(-1)))
|
||||
{
|
||||
@@ -186,7 +186,7 @@ extern "C"
|
||||
}
|
||||
|
||||
SNMALLOC_EXPORT void*
|
||||
SNMALLOC_NAME_MANGLE(aligned_alloc)(size_t alignment, size_t size)
|
||||
SNMALLOC_NAME_MANGLE(aligned_alloc)(size_t alignment, size_t size)
|
||||
{
|
||||
SNMALLOC_ASSERT((size % alignment) == 0);
|
||||
return SNMALLOC_NAME_MANGLE(memalign)(alignment, size);
|
||||
|
||||
@@ -6,7 +6,7 @@ extern "C"
|
||||
* Snmalloc checked memcpy.
|
||||
*/
|
||||
SNMALLOC_EXPORT void*
|
||||
SNMALLOC_NAME_MANGLE(memcpy)(void* dst, const void* src, size_t len)
|
||||
SNMALLOC_NAME_MANGLE(memcpy)(void* dst, const void* src, size_t len)
|
||||
{
|
||||
return snmalloc::memcpy<true>(dst, src, len);
|
||||
}
|
||||
|
||||
@@ -38,12 +38,12 @@ void* operator new[](size_t size, std::nothrow_t&)
|
||||
return ThreadAlloc::get().alloc(size);
|
||||
}
|
||||
|
||||
void operator delete(void* p)EXCEPTSPEC
|
||||
void operator delete(void* p) EXCEPTSPEC
|
||||
{
|
||||
ThreadAlloc::get().dealloc(p);
|
||||
}
|
||||
|
||||
void operator delete(void* p, size_t size)EXCEPTSPEC
|
||||
void operator delete(void* p, size_t size) EXCEPTSPEC
|
||||
{
|
||||
if (p == nullptr)
|
||||
return;
|
||||
@@ -96,7 +96,7 @@ void* operator new[](size_t size, std::align_val_t val, std::nothrow_t&)
|
||||
return ThreadAlloc::get().alloc(size);
|
||||
}
|
||||
|
||||
void operator delete(void* p, std::align_val_t)EXCEPTSPEC
|
||||
void operator delete(void* p, std::align_val_t) EXCEPTSPEC
|
||||
{
|
||||
ThreadAlloc::get().dealloc(p);
|
||||
}
|
||||
@@ -106,7 +106,7 @@ void operator delete[](void* p, std::align_val_t) EXCEPTSPEC
|
||||
ThreadAlloc::get().dealloc(p);
|
||||
}
|
||||
|
||||
void operator delete(void* p, size_t size, std::align_val_t val)EXCEPTSPEC
|
||||
void operator delete(void* p, size_t size, std::align_val_t val) EXCEPTSPEC
|
||||
{
|
||||
size = aligned_size(size_t(val), size);
|
||||
ThreadAlloc::get().dealloc(p, size);
|
||||
|
||||
@@ -10,19 +10,19 @@
|
||||
using namespace snmalloc;
|
||||
|
||||
extern "C" SNMALLOC_EXPORT void*
|
||||
SNMALLOC_NAME_MANGLE(rust_alloc)(size_t alignment, size_t size)
|
||||
SNMALLOC_NAME_MANGLE(rust_alloc)(size_t alignment, size_t size)
|
||||
{
|
||||
return ThreadAlloc::get().alloc(aligned_size(alignment, size));
|
||||
}
|
||||
|
||||
extern "C" SNMALLOC_EXPORT void*
|
||||
SNMALLOC_NAME_MANGLE(rust_alloc_zeroed)(size_t alignment, size_t size)
|
||||
SNMALLOC_NAME_MANGLE(rust_alloc_zeroed)(size_t alignment, size_t size)
|
||||
{
|
||||
return ThreadAlloc::get().alloc<YesZero>(aligned_size(alignment, size));
|
||||
}
|
||||
|
||||
extern "C" SNMALLOC_EXPORT void
|
||||
SNMALLOC_NAME_MANGLE(rust_dealloc)(void* ptr, size_t alignment, size_t size)
|
||||
SNMALLOC_NAME_MANGLE(rust_dealloc)(void* ptr, size_t alignment, size_t size)
|
||||
{
|
||||
ThreadAlloc::get().dealloc(ptr, aligned_size(alignment, size));
|
||||
}
|
||||
|
||||
@@ -19,62 +19,54 @@ namespace snmalloc
|
||||
* PALs must advertize the bit vector of their supported features.
|
||||
*/
|
||||
template<typename PAL>
|
||||
concept IsPAL_static_features = requires()
|
||||
{
|
||||
typename std::integral_constant<uint64_t, PAL::pal_features>;
|
||||
};
|
||||
concept IsPAL_static_features =
|
||||
requires() {
|
||||
typename std::integral_constant<uint64_t, PAL::pal_features>;
|
||||
};
|
||||
|
||||
/**
|
||||
* PALs must advertise the size of the address space and their page size
|
||||
*/
|
||||
template<typename PAL>
|
||||
concept IsPAL_static_sizes = requires()
|
||||
{
|
||||
typename std::integral_constant<std::size_t, PAL::address_bits>;
|
||||
typename std::integral_constant<std::size_t, PAL::page_size>;
|
||||
};
|
||||
concept IsPAL_static_sizes =
|
||||
requires() {
|
||||
typename std::integral_constant<std::size_t, PAL::address_bits>;
|
||||
typename std::integral_constant<std::size_t, PAL::page_size>;
|
||||
};
|
||||
|
||||
/**
|
||||
* PALs expose an error reporting function which takes a const C string.
|
||||
*/
|
||||
template<typename PAL>
|
||||
concept IsPAL_error = requires(const char* const str)
|
||||
{
|
||||
{
|
||||
PAL::error(str)
|
||||
}
|
||||
->ConceptSame<void>;
|
||||
};
|
||||
concept IsPAL_error = requires(const char* const str) {
|
||||
{
|
||||
PAL::error(str)
|
||||
} -> ConceptSame<void>;
|
||||
};
|
||||
|
||||
/**
|
||||
* PALs expose a basic library of memory operations.
|
||||
*/
|
||||
template<typename PAL>
|
||||
concept IsPAL_memops = requires(void* vp, std::size_t sz)
|
||||
{
|
||||
{
|
||||
PAL::notify_not_using(vp, sz)
|
||||
}
|
||||
noexcept->ConceptSame<void>;
|
||||
concept IsPAL_memops = requires(void* vp, std::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 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>;
|
||||
};
|
||||
{
|
||||
PAL::template zero<false>(vp, sz)
|
||||
} noexcept -> ConceptSame<void>;
|
||||
{
|
||||
PAL::template zero<true>(vp, sz)
|
||||
} noexcept -> ConceptSame<void>;
|
||||
};
|
||||
|
||||
/**
|
||||
* The Pal must provide a thread id for debugging. It should not return
|
||||
@@ -82,66 +74,55 @@ namespace snmalloc
|
||||
* places.
|
||||
*/
|
||||
template<typename PAL>
|
||||
concept IsPAL_tid = requires()
|
||||
{
|
||||
{
|
||||
PAL::get_tid()
|
||||
}
|
||||
noexcept->ConceptSame<typename PAL::ThreadIdentity>;
|
||||
};
|
||||
concept IsPAL_tid =
|
||||
requires() {
|
||||
{
|
||||
PAL::get_tid()
|
||||
} noexcept -> ConceptSame<typename PAL::ThreadIdentity>;
|
||||
};
|
||||
|
||||
/**
|
||||
* Absent any feature flags, the PAL must support a crude primitive allocator
|
||||
*/
|
||||
template<typename PAL>
|
||||
concept IsPAL_reserve = requires(PAL p, std::size_t sz)
|
||||
{
|
||||
{
|
||||
PAL::reserve(sz)
|
||||
}
|
||||
noexcept->ConceptSame<void*>;
|
||||
};
|
||||
concept IsPAL_reserve = requires(PAL p, std::size_t sz) {
|
||||
{
|
||||
PAL::reserve(sz)
|
||||
} noexcept -> ConceptSame<void*>;
|
||||
};
|
||||
|
||||
/**
|
||||
* Some PALs expose a richer allocator which understands aligned allocations
|
||||
*/
|
||||
template<typename PAL>
|
||||
concept IsPAL_reserve_aligned = requires(std::size_t sz)
|
||||
{
|
||||
{
|
||||
PAL::template reserve_aligned<true>(sz)
|
||||
}
|
||||
noexcept->ConceptSame<void*>;
|
||||
{
|
||||
PAL::template reserve_aligned<false>(sz)
|
||||
}
|
||||
noexcept->ConceptSame<void*>;
|
||||
};
|
||||
concept IsPAL_reserve_aligned = requires(std::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 IsPAL_mem_low_notify = requires(PalNotificationObject* pno)
|
||||
{
|
||||
{
|
||||
PAL::expensive_low_memory_check()
|
||||
}
|
||||
->ConceptSame<bool>;
|
||||
{
|
||||
PAL::register_for_low_memory_callback(pno)
|
||||
}
|
||||
->ConceptSame<void>;
|
||||
};
|
||||
concept IsPAL_mem_low_notify = requires(PalNotificationObject* pno) {
|
||||
{
|
||||
PAL::expensive_low_memory_check()
|
||||
} -> ConceptSame<bool>;
|
||||
{
|
||||
PAL::register_for_low_memory_callback(pno)
|
||||
} -> ConceptSame<void>;
|
||||
};
|
||||
|
||||
template<typename PAL>
|
||||
concept IsPAL_get_entropy64 = requires()
|
||||
{
|
||||
{
|
||||
PAL::get_entropy64()
|
||||
}
|
||||
->ConceptSame<uint64_t>;
|
||||
};
|
||||
concept IsPAL_get_entropy64 = requires() {
|
||||
{
|
||||
PAL::get_entropy64()
|
||||
} -> ConceptSame<uint64_t>;
|
||||
};
|
||||
|
||||
/**
|
||||
* PALs ascribe to the conjunction of several concepts. These are broken
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace snmalloc
|
||||
* The minimal subset of a PAL that we need for delegation
|
||||
*/
|
||||
template<typename PAL>
|
||||
concept PALNoAllocBase = IsPAL_static_sizes<PAL>&& IsPAL_error<PAL>;
|
||||
concept PALNoAllocBase = IsPAL_static_sizes<PAL> && IsPAL_error<PAL>;
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
||||
@@ -62,14 +62,12 @@ namespace snmalloc
|
||||
* C++, and not just its initializer fragment, to initialize a non-prefix
|
||||
* subset of the flags (in any order, at that).
|
||||
*/
|
||||
static constexpr Flags Options = []() constexpr
|
||||
{
|
||||
static constexpr Flags Options = []() constexpr {
|
||||
Flags opts = {};
|
||||
opts.QueueHeadsAreTame = false;
|
||||
opts.HasDomesticate = true;
|
||||
return opts;
|
||||
}
|
||||
();
|
||||
}();
|
||||
|
||||
static GlobalPoolState& pool()
|
||||
{
|
||||
|
||||
@@ -172,7 +172,7 @@ namespace
|
||||
* sandbox but allocates memory inside.
|
||||
*/
|
||||
struct RemoteAllocator queue;
|
||||
} * shared_state;
|
||||
}* shared_state;
|
||||
|
||||
/**
|
||||
* The memory provider for this sandbox.
|
||||
@@ -195,7 +195,7 @@ namespace
|
||||
Sandbox(size_t sb_size)
|
||||
: start(alloc_sandbox_heap(sb_size)),
|
||||
top(pointer_offset(start, sb_size)),
|
||||
shared_state(new (start) SharedState()),
|
||||
shared_state(new(start) SharedState()),
|
||||
state(
|
||||
pointer_offset(CapPtr<void, CBChunk>(start), sizeof(SharedState)),
|
||||
sb_size - sizeof(SharedState)),
|
||||
|
||||
Reference in New Issue
Block a user