Commit Graph

24 Commits

Author SHA1 Message Date
Nathaniel Wesley Filardo
4ad99d7392 Downgrade some casts
Do a quick sweep through the codebase to eliminate some reinterpret_cast<>s
where less fire power would do just fine.
2022-03-18 15:06:01 +00:00
Matthew Parkinson
5287000453 Buddy (#468)
# Small changes before rewrite

* Additional bit in remote allocator to prevent type confusion with the backend.
* Move Chunk allocator to backend.
* Improvements to RedBlack tree
* Expose message from Pal

# Complete backend rewrite

This provides two key changes:

* We use buddy allocators to allow memory to reconsolidated
* The backend is factored into a series of small operations that
    allocate and deallocate memory.

The backend now uses "Ranges", there are two ranges that don't require a
parent range:
* EmptyRange - Never returns any memory
* PalRange - Returns memory from the platform.

All other ranges require a parent range to supply memory to them.  Some
ranges support both allocation and deallocation, and some just
deallocation.  For instance,  CommitRange supports both, and maps
requests to the parent range, but will Commit and Decommit the memory.

As the ranges perform only a single task, they are generally small and
easy to follow.  The two exceptions to this are the two BuddyRanges
(Large and Small).  Large is for CHUNK_SIZE and above blocks, while
Small is for below CHUNK_SIZE blocks.  Both are implemented with a buddy
allocator, but the SmallBuddyRange uses in place meta-data, while the
LargeBuddyRange uses the pagemap for its meta-data.  This means the
LargeBuddyRange can keep the majority of memory it is managing
decommitted.

The Backend glues together the various ranges to support the appropriate
way to manage memory on the platform.
2022-03-11 18:16:06 +00:00
Matthew Parkinson
69c824d54d Expose mutable reference to pagemap 2022-02-11 13:21:46 +00:00
Matthew Parkinson
ef64f6c31b Improve check_bounds init check. 2022-01-10 16:29:06 +00:00
Schrodinger ZHU Yifan
faa80037bb put likely/unlikely in scope (#420)
* put likely/unlikely in scope

Signed-off-by: SchrodingerZhu <i@zhuyi.fan>

* make clang-format happy

Signed-off-by: SchrodingerZhu <i@zhuyi.fan>
2021-11-17 16:05:52 +00:00
Matthew Parkinson
91919f6014 Update src/backend/pagemap.h
Co-authored-by: Amaury Chamayou <amchamay@microsoft.com>
2021-11-17 09:19:08 +00:00
Nathaniel Wesley Filardo
fe43f0bea8 Placate some compiler errors on CHERI 2021-10-20 12:02:08 +01:00
Nathaniel Wesley Filardo
1a608e6066 NFC: Introduce pointer domestication backend support
`capptr_domesticate<Backend>(Backend::LocalState*, CapPtr<T, B>)` is the
intended affordance for conversion to covert from a `CapPtr<T, B>` with
`B::wildness` `Wild` to a `CapPtr<>` with `B::with_wildness<Tame>` and thence
plumbed into the rest of the machinery.

David added the SFINAE wrapper so that `Backend`-s now don't need to implement a
domestication callback; instead, if the `Backend` does not provide a
`capptr_domesticate` function, a default, which just does an explicit type cast,
will be used instead.

This is not yet hooked into the rest of the tree.

Co-authored-by: David Chisnall <David.Chisnall@microsoft.com>
2021-10-13 16:30:41 +01:00
Matthew Parkinson
b4efc40aa6 Expose notify_using_readonly
This exposes a readonly notify using, so that the underlying platform
can map the range of pages readonly into the application.  This improves
performance of external pointer on platforms that support lazy commit
of pages as it can access anything in the range.
2021-09-28 09:23:52 +01:00
Nathaniel Wesley Filardo
15e3052087 Move to AAL/PAL bits and address_bits 2021-09-23 15:42:53 +01:00
David Chisnall
51e75bca89 Add memcpy with bounds checks.
The memcpy implementation is not completely stupid but is almost
certainly not as good as a carefully tuned and optimised one.

Building snmalloc with FreeBSD's libc memcpy + jemalloc and with this,
each 10 times, does not show a statistically significant performance
difference at 95% confidence.  The snmalloc version has very slightly
lower median and worst-case times.  This is in no way a sensible
benchmark, but it serves as a smoke test for significant performance
regressions.

The CI self-host job now uses the checked memcpy.

This also fixes an off-by-one error in the external bounds.  This is
triggered by ninja, so we will see breakage in CI if it is reintroduced.

In debug builds, we provide a verbose error containing the address of
the allocation, the base and bounds of the allocation, and a backtrace.

The backtrace was broken by the CI cleanup moving the BACKTRACE_HEADER
macro into the SNMALLOC_ namespace.  This is also fixed.

The test involves hijacking `abort`, which doesn't work everywhere.  It
also requires `backtrace` to work in configurations where stack traces
are enabled.  This is disabled in QEMU because `backtrace` appears to
crash reliably in QEMU user mode.

For now, in the -checks build configurations, we are hitting a slow path
in the pagemap on accesses so that the pages that are `PROT_NONE` don't
cause crashes.  These need to be made read-only, but this requires a PAL
change.
2021-09-16 13:53:13 +01:00
Matthew Parkinson
27c4a6a55e Make pagemap check for init on some gets.
When we are accessing potentially out of range, then we might be
accessing before the pagemap has been initialised.  Move the check
into the pagemap for better codegen.
2021-08-26 14:47:56 +01:00
Istvan Haller
e45354b3ed Changed error handling to assert 2021-08-06 16:19:35 +01:00
Istvan Haller
df62abac55 Added nodiscard 2021-08-06 15:08:24 +01:00
Istvan Haller
22e2b5b689 Added reverse lookup to Pagemap 2021-08-06 14:59:31 +01:00
David Chisnall
e8374479f4 Snmalloc2 API cleanups for sandbox use. (#359)
This is the set of changes required for snmalloc2 to be usable by the
process sandboxing code and incorporates some API changes that reduce
the amount of code required to embed snmalloc.  Highlights:

 - Merge the config and back-end classes.
 - Everything in config is now global (all methods are static)
 - The GlobalState class is gone (all global state is managed by global
   methods on the config class)
 - LocalState is now a member of the config class, all methods are
   instance methods.
 - Not every configuration needs to use the lazy initialisation hooks.
   They now need to be provided only if they are used.  If the
   configuration does not provide an `ensure_init` method, it is not
   called.  If it does not provide an `is_initialised` method then the
   global initialisation state is not checked.
 - There is now an `snmalloc::Options` class that default initialises
   itself to the default behaviour.  Every configuration must provide a
   `constexpr` instance of this class.  Each flag can be separately
   overridden and new flags can be added without breaking any existing
   API consumers.

The config classes are moved into the backend directory.
2021-08-05 15:08:12 +01:00
Matthew Parkinson
0b7929327a Add errors for failing to initialise the system. 2021-07-21 09:36:06 +01:00
Matthew Parkinson
8a8669f957 Add randomised start to pagemap layout
The pagemap contains a lot of important data.  This commit makes the
checked mode overallocate, and then start the pagemap at a random
offset within this range.
2021-07-21 09:36:06 +01:00
Matthew Parkinson
5d0ae71423 Remove at_least
The Pal was providing policy for overallocating a block of memory to
achieve alignment make that part of the backend.
The backend should be responsible for layout policy.
2021-07-21 09:36:06 +01:00
Matthew Parkinson
02d2ab8f7e Pagemap requires registration of used space
This PR exposes a pagemap interface to specify ranges that are being
used. The overall invariant is that any memory in the address space
manager has the pagemap committed. This means that individual operations
do not need to commit entries.

This is important for Windows that does not support lazy commit.  It is
also important if we want to PROT_NONE most of the pagemap to reduce the
risk of memory safety issues getting access to the pagemap.

There are minor changes to test to pull memory directly from the Pal.
There are also bug fixes in the pagemap tests.
2021-07-21 09:36:06 +01:00
Matthew Parkinson
da01d5b4ca Remove address space usage from Pagemap.
The pagemap allocates it self directly either from

  * the original fixed address range it is supplied, and returns the
    remaining space after the pagemap is removed; or
  * directly allocated from the PAL without using the address space
    manager.

This change in layering is required for the next commit, which imposes
the invariant that the pagemap has been committed for all spaced managed
by the address space manager.
2021-07-21 09:36:06 +01:00
Matthew Parkinson
686cb3321f Use SFINAE for varying API on pagemap 2021-07-21 09:36:06 +01:00
Nathaniel Wesley Filardo
39c2df0b56 pagemap: don't eagerly commit on LazyCommit PALs 2021-07-13 13:50:06 +01:00
Matthew Parkinson
f0e2ab702a Major refactor of snmalloc (#343)
# Pagemap
 
The Pagemap now stores all the meta-data for the object allocation. The meta-data in the pagemap is effectively a triple of the sizeclass, the remote allocator, and a pointer to a 64 byte block of meta-data for this chunk of memory. By storing the pointer to a block, it allows the pagemap to handle multiple slab sizes without branching on the fast path. There is one entry in the pagemap per 16KiB of address space, but by using the same entry in the pagemap for 4 adjacent entries, then we can treat a 64KiB range can be treated as a single slab of allocations.

This change also means there is almost no capability amplification required by the implementation on CHERI for finding meta-data. The only amplification is required, when we change the way a chunk is used to a size of object allocation.


# Backend

There is a second major aspect of the refactor that there is now a narrow API that abstracts the Pagemap, PAL and address space management. This should better enable the compartmentalisation and makes it easier to produce alternative backends for various research directions. This is a template parameter that can be used to specialised by the front-end in different ways.

# Thread local state

The thread local state has been refactored into two components, one (called 'localalloc') that is stored directly in the TLS and is constant initialised, and one that is allocated in the address space (called 'coreallloc') which is lazily created and pooled.

# Difference

This removes Superslabs/Medium slabs as there meta-data is now part of the pagemap.
2021-07-12 15:53:36 +01:00