Commit Graph

48 Commits

Author SHA1 Message Date
Matthew Parkinson
f15dc6ee2e Expose Entropy
Define various parts of random that can be used to make the layout of
memory more random.  Thread this through the allocator.

Expose the concept as part of the Pal. Subsequent commits will expose
that on different platforms.
2021-04-06 14:09:18 +01:00
Matthew Parkinson
afc6283e01 Threshold freelist wakeup
When a slab has been fully allocated, then we no longer
check it has entries until something returns an allocation to this slab.
However, it is possible that only a single allocation is available, and
then we can end up frequently on the slow path.

This change only considers free lists that cover at least 1/8 of a slab.
This means that we will hit the slow path less frequently.  This also
means that the randomisation changes will have more entropy: with a
single element free list there is only one order.

For large small sizes it can still be a single element, as 1/8 is of the
slab capacity is below 1. We max out the trigger at 31 elements to
reduce unneeded wasted space.
2021-03-25 12:04:36 +00:00
Matthew Parkinson
578abd8db4 Randomise slab allocation pattern (#304)
The slab allocation pattern is randomised based on the deallocation
pattern.  This achieved by using two queues to enqueue free elements
onto.  We pick "randomly", which queue to add to, and then when we take
the free_queue to use, we splice the two queues together.
2021-03-24 16:12:22 +00:00
Matthew Parkinson
63f231f484 Bug fix for superslab meta-data (#302)
* Replace time measuring macro

The DO_TIME macro was used originally to get performance numbers. The
macro makes tests hard to debug. This commit replaces it with a proper
C++ class with destructor.

* Bug fix

If the superslab meta data is large, then the calculation for the
sizeclasses that could use the short slab was incorrect.  This fixes
that calculation.

Co-authored-by: Nathaniel Wesley Filardo <nfilardo@microsoft.com>
2021-03-23 12:42:11 +00:00
Matthew Parkinson
04a185e634 Remove allocated field from Metaslab
The metaslab contains a field specifying how many elements have been
allocated.  As the code has evolved this field has now always become
the maximum capacity of the slab for the sizeclass.

This commit looks up this value based on the sizeclass, and removes the
field from the slab's metadata.
2021-03-22 13:07:57 +00:00
Matthew Parkinson
ed615eade9 Refactor checks to improve codegen. 2021-03-19 11:28:39 +00:00
Matthew Parkinson
0983f1837b Alternate allocation pattern 2021-03-19 11:28:39 +00:00
Matthew Parkinson
50f412157f Protect free list pointers stored in object space
Free list pointers can be exploited by attackers. This commit implements
a simple encoding scheme to detect corruption of the pointers.  This can
be used to detect UAF and double free.

This does not currently address anything for Medium or Large
allocations.  It also does not address cross thread deallocations.

Co-authored-by: Nathaniel Wesley Filardo <nfilardo@microsoft.com>
2021-03-19 11:28:39 +00:00
Nathaniel Filardo
4f6cf8cb40 NFC: make Slab, Mediumslab interfaces static
Going forward, this gives us explicit pointers with which to carry bounds
annotations.  Otherwise, assuming AuthPtr overloads operator->, a OOP-style call
like

    AuthPtr<Slab, Bounds> slab;
    slab->foo()

will create a `Slab* this` within the body of `Slab::foo`, leaving it unable to
see or propagate the Bounds annotation.  If it invokes callees that expect
`AuthPtr` arguments, it will therefore have to fabricate new `Bounds` unsafely.
2021-03-16 09:29:19 +00:00
Nathaniel Filardo
49fefc3f83 NFC: introduce SlabNext type for intra-small-slab free pointers
Mostly cosmetic, but eliminates some void*-s and makes intention clearer.
2021-03-16 09:29:19 +00:00
Matthew Parkinson
59edf294d0 Move link out of object space.
The link object was previously stored in a disused object.  This is
good for reducing meta-data, but if we want to reduce the meta-data
corruption potential, then this is not a good design choice.

This commit moves it into the Metaslab.
2021-03-15 13:28:03 +00:00
Matthew Parkinson
e7dce55f19 Move is_start_of_object into Metaslab. 2021-03-15 13:28:03 +00:00
Nathaniel Filardo
1e8d0bd743 MemoryProviderStateMixin is not a PAL 2020-09-09 12:55:48 +01:00
Matthew Parkinson
06eef5c4c5 Small changes (#159)
* Use NoZero for fresh pages
* MADV_DONTNEED only use for greater than a whole slab
* Simplify free list threading code
2020-04-02 07:04:03 +01:00
Matthew Parkinson
d900e29424 Improve slow path performance for allocation (#143)
* Remote dealloc refactor.

* Improve remote dealloc

Change remote to count down to 0, so fast path does not need a constant.

Use signed value so that branch does not depend on addition.

* Inline remote_dealloc

The fast path of remote_dealloc is sufficiently compact that it can be
inlined.

* Improve fast path in Slab::alloc

Turn the internal structure into tail calls, to improve fast path.
Should be no algorithmic changes.

* Refactor initialisation to help fast path.

Break lazy initialisation into two functions, so it is easier to codegen
fast paths.

* Minor tidy to statically sized dealloc.

* Refactor semi-slow path for alloc

Make the backup path a bit faster.  Only algorithmic change is to delay
checking for first allocation. Otherwise, should be unchanged.

* Test initial operation of a thread

The first operation a new thread takes is special.  It results in
allocating an allocator, and swinging it into the TLS.  This makes
this a very special path, that is rarely tested.  This test generates
a lot of threads to cover the first alloc and dealloc operations.

* Correctly handle reusing get_noncachable

* Fix large alloc stats

Large alloc stats aren't necessarily balanced on a thread, this changes
to tracking individual pushs and pops, rather than the net effect
(with an unsigned value).

* Fix TLS init on large alloc path

* Add Bump ptrs to allocator

Each allocator has a bump ptr for each size class.  This is no longer
slab local.

Slabs that haven't been fully allocated no longer need to be in the DLL
for this sizeclass.

* Change to a cycle non-empty list

This change reduces the branching in the case of finding a new free
list. Using a non-empty cyclic list enables branch free add, and a
single branch in remove to detect the empty case.

* Update differences

* Rename first allocation

Use needs initialisation as makes more sense for other scenarios.

* Use a ptrdiff to help with zero init.

* Make GlobalPlaceholder zero init

The GlobalPlaceholder allocator is now a zero init block of memory.
This removes various issues for when things are initialised. It is made read-only
to we detect write to it on some platforms.
2020-03-31 09:17:53 +01:00
Amaury Chamayou
acbcbce597 replace assert with SNMALLOC_ASSERT 2020-03-04 16:57:44 +00:00
Matthew Parkinson
c9da18a145 Improve Debug test speed.
Removed some very expensive debug checks off the fast path
of deallocation.
2020-02-06 13:05:40 +00:00
Matthew Parkinson
02427f98f0 Clangformat. 2020-02-04 14:12:28 +00:00
Matthew Parkinson
2e4b289991 Removed DecommitAll strategy
The DecommitAll strategy performs badly.  We are not
functionally testing it, and it does not seem investing in it due to its
performance.
2020-01-29 11:58:57 +00:00
Matthew Parkinson
a2b56f9740 Remove a notify_using that regressed perf
The performance on Windows was significantly regressed by the
notify_using during the bump allocation.  This change removes that.
It appears that the pages are already committed by
the large allocator.
2020-01-29 11:25:13 +00:00
Nathaniel Filardo
83c467eb92 ds/address: add pointer diff function
And use it rather than open-coding subtraction of two address_cast-s.
2019-11-26 15:50:22 +00:00
Nathaniel Filardo
261249d9cb Preserve provenance through pointer offsetting 2019-11-26 14:59:54 +00:00
Matthew Parkinson
1d0c42449e CR feedback 2019-11-21 11:39:55 +00:00
Matthew Parkinson
df1dfa55db improved comments and rename field
Replaced used with needed, the number of objects needed empty this slab.

Some mild improvement to the comments.
2019-11-21 11:39:55 +00:00
Matthew Parkinson
efd5228da6 Store a full pointer in the Metaslab
This improves the codegen.
2019-11-21 11:39:55 +00:00
Matthew Parkinson
cb4b8fa545 Changes the representation in Metaslab Used
Used is now set to 1, when the slab is full.  This means that the test
for
 used - 1 == 0
can be used to detect leaving full, and entering empty, reducing fast
path deallocation branchs by 1.
2019-11-19 16:25:27 +00:00
Paul Liétar
7047cda8ed Fix warning about shadowing. 2019-07-17 14:13:44 +01:00
Paul Liétar
a5379b24d5 Add remove_cache_friendly_offset calls in a few places that were missing it. 2019-07-17 13:14:59 +01:00
David Chisnall
c35a3941fe Merge pull request #65 from microsoft/queue_of_slabs
Use a queue of slabs for free lists
2019-07-08 20:53:06 +01:00
Matthew Parkinson
d1db6d07ad Use a queue of slabs for free lists
This commit changes the strategy for finding a free list from
a stack to a queue.  This tends to avoid the slow path considerably more.
It has some memory overheads.

TOOD:  We should move the bump allocation data out of the metaslab and
into the allocator.  At the moment, the slab contains the bump allocation
data, we should move this into the allocator, as it only ever has one slab
it is bump allocating from per sizeclass.
2019-07-05 17:04:55 +01:00
David Chisnall
2efcddfc3d Rework free list so that 0 is the placeholder.
This is needed because in some configurations the constructor for the
global placeholder is not called before the first allocation (i.e. when
other globals call the allocator in their constructor) and so we ended
up following a null pointer.
2019-07-05 14:20:24 +01:00
Matthew Parkinson
eb4e28e8d0 CR Feedback
Removed stub from message queue, and use an actual allocation.
2019-07-02 14:08:05 +01:00
Matthew Parkinson
621b7e6b9a Clang format. 2019-07-02 10:51:18 +01:00
Matthew Parkinson
187a016c39 Clang Tidy and Warnings 2019-07-01 14:35:36 +01:00
Matthew Parkinson
3c7d122dea Add macro for ASSUME and FAST_PATH/SLOW_PATH
Fixes GCC warning that was incorrect using an ASSUME.

Made fast path and slow path Macros so we can add additional attributes.
2019-07-01 14:35:36 +01:00
Matthew Parkinson
7a198cbda5 Aggressively optimise fast path for allocation
This change introduces a per small sizeclass free list.  That can be
used to access the free objects for that sizeclass with minimal
calculations being required.

It changes to a partial bump ptr.  We bump allocate a whole OS
page worth of objects at a go, so we don't switch as frequently
between bump and free list allocation.

The code for the fast paths has been restructured to minimise the
work required on the common case, and also it is all inlined for the
common case.

Allocating a zero sized object is moved off the fast path.  Ask for 1
byte if you want to be fast.
2019-07-01 14:35:35 +01:00
Matthew Parkinson
cc6a9775d6 Made checks on client have own macro. 2019-06-12 15:29:25 +01:00
Matthew Parkinson
88d9534453 CR Feedback + clangformat 2019-06-12 13:54:14 +01:00
Matthew Parkinson
a8dd065fd7 A few checks for easy corruptions
Will detect corruption caused by either
* Use-after-free
* Double-free
Neither is comprehensive.  Full temporal safety is not possible.
This just aids with debugging.
2019-06-06 13:31:25 +01:00
Matthew Parkinson
7de46182a8 Used start of a slab for link. 2019-05-21 09:47:23 +01:00
David Chisnall
5c197e4ae4 [NFC] More checks, comments on end of namespace braces. 2019-04-30 09:46:01 +01:00
David Chisnall
28fac4d700 Fix the remaining clang-tidy warnings.
This introduces a new `address_t` type and two new casts: `pointer_cast`
and `address_cast` for casting between an `address_t` and a pointer.
These should make it easier to audit the codebase for casts between
pointers and integers.  In particular, the remaining `reinterpret_cast`s
and `pointer_cast`s should be the only places where we could perform
invalid pointer arithmetic.

Also adds a `pointer_offset` helper that adds an offset (in bytes) to a
pointer, preserving its original type.  This is a sufficiently common
pattern that it seemed worthwhile to centralise it.
2019-04-29 13:37:05 +01:00
David Chisnall
4bafca9be7 [NFC] Automatic fixes from clang-tidy. 2019-04-29 11:33:07 +01:00
Paul Liétar
4ac3421487 Place the next pointer at a different place on every object.
This limits the collision in cache buckets, especially for larger objects.
2019-02-18 14:22:50 +00:00
theodus
85cf5dd097 Avoid unnecessary allocation from realloc 2019-02-02 14:47:06 -05:00
Matthew Parkinson
2083b29c9b Remove a raw pointer usage
Metaslab can be handled as as ref, rather than a raw pointer.
2019-01-24 11:39:18 +00:00
Matthew Parkinson
b097b47aa2 Handle 2^16 slabs
This code assumes that 16bit uint wrapping can be used, rather than
masking by SLAB_SIZE-1.  Add explicit mask, so we can change the
SLAB_SIZE to be smaller.
2019-01-17 14:09:50 +00:00
Matthew Parkinson
4f9d991449 Initial commit of snmalloc
History squashed from internal development.

Internal history has commit hash:
  e27a0e485c44a5003a802de2661ce3b21e120316
2019-01-15 14:17:55 +00:00