* 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.
On platforms that support low-memory notifications register callbacks
that perform lazy decommit. This allows idle processes to return memory
to the OS. Without incurring the cost of constantly committing and
decommitting memory.
Code review and CI changes
* Fixed test to use a template to make constexpr magic work
* Factored out basic notification mechanism so can be reused on other
platforms.
The PAL API previously allowed for returning more memory than asked for.
This was when the PAL performed the alignment work, now this is done in
large alloc, so removing from the PAL.
Fixes a few places where Clang complains about Windows specific code,
and also uses macros supported by Clang on Windows. A few places
separating platform and compiler specific code, as MSVC and WIN32 were
used interchangably previously.
HEADER_GLOBAL was using non-standard attributes to achieve what C++17
now permits with a keyword. Use the standard formulation.
Update the README to note that gcc is still not recommended, but because
of its poor codegen for 128-bit atomic compare and exchange, rather than
because it doesn't support the attribute used for HEADER_GLOBAL.
The PAL can now advertise that it supports aligned allocation. If it
does not, then the memory provider will do the alignment for it.
This change still leaves the PAL responsible for systematic testing, but
it should now be much easier to lift that out.
This does not deallocate memory until the OS tells us that we are short
on memory, then tries to decommit all of the cached chunks (except for
the first page, used for the linked lists).
Nowhere near enough testing to commit to master yet!
The newer API (Windows 10 and newer) allows the allocator to ask for
strongly aligned memory.
This is enabled only if the `WINVER` macro is set to target Windows 10
or newer. There is now a CMake option to target older versions of
Windows, so we can test both code paths.
The Azure Pipelines config now includes a test of the compatibility
version. This runs only the release build, because it's mainly there as
a sanity check - 99% of the code is the same as the default Windows
config.