Lazily initialise TLS on slow paths.

Copying an idea from mimalloc, initialise the TLS variable to a global
allocator that doesn't own any memory and then lazily check when we hit
a slow path (which we always do when using the global allocator, because
it doesn't own any memory) if we are the global allocator and replace
it.

There is a slight complication compared to mimalloc's version of this
idea.  Snmalloc collects outgoing messages and it's possible for the
first operation in a thread to be a free of memory allocated by a
different thread.  We address this by initialising the queues with a
size value indicating that they are full and then do the lazy check when
about to insert a message that would make a queue full.  This will then
trigger lazy creation of an allocator.

Global initialisation doesn't work for the fake allocator, so skip most
of its constructor.
This commit is contained in:
David Chisnall
2019-07-02 16:07:56 +01:00
parent 7dc30cc6fc
commit b8a5d7fca9
4 changed files with 184 additions and 74 deletions

View File

@@ -6,11 +6,25 @@
namespace snmalloc
{
inline void* lazy_replacement(void*);
using Alloc =
Allocator<GlobalVirtual, SNMALLOC_DEFAULT_PAGEMAP, true, lazy_replacement>;
template<class MemoryProvider>
class AllocPool : Pool<Allocator<MemoryProvider>, MemoryProvider>
class AllocPool : Pool<
Allocator<
MemoryProvider,
SNMALLOC_DEFAULT_PAGEMAP,
true,
lazy_replacement>,
MemoryProvider>
{
using Alloc = Allocator<MemoryProvider>;
using Parent = Pool<Allocator<MemoryProvider>, MemoryProvider>;
using Alloc = Allocator<
MemoryProvider,
SNMALLOC_DEFAULT_PAGEMAP,
true,
lazy_replacement>;
using Parent = Pool<Alloc, MemoryProvider>;
public:
static AllocPool* make(MemoryProvider& mp)
@@ -175,5 +189,4 @@ namespace snmalloc
return AllocPool<MemoryProvider>::make(mp);
}
using Alloc = Allocator<GlobalVirtual>;
} // namespace snmalloc