Skip to content

Commit

Permalink
Fix issue 16352 - dead-lock in std.allocator.free_list unittest
Browse files Browse the repository at this point in the history
  • Loading branch information
WalterWaldron committed Dec 23, 2016
1 parent e08d4f4 commit 5caa66e
Showing 1 changed file with 23 additions and 17 deletions.
40 changes: 23 additions & 17 deletions std/experimental/allocator/building_blocks/free_list.d
Expand Up @@ -760,6 +760,7 @@ struct SharedFreeList(ParentAllocator,
"Maximum size must accommodate a pointer.");

import core.atomic : atomicOp, cas;
import core.internal.spinlock : SpinLock;

static if (minSize != chooseAtRuntime)
{
Expand Down Expand Up @@ -924,6 +925,8 @@ struct SharedFreeList(ParentAllocator,

mixin(forwardToMember("parent", "expand"));

private SpinLock lock;

private struct Node { Node* next; }
static assert(ParentAllocator.alignment >= Node.alignof);
private Node* _root;
Expand Down Expand Up @@ -958,18 +961,22 @@ struct SharedFreeList(ParentAllocator,
assert(bytes < size_t.max / 2);
if (!freeListEligible(bytes)) return parent.allocate(bytes);
if (maxSize != unbounded) bytes = max;
// Pop off the freelist
shared Node* oldRoot = void, next = void;
do

// Try to pop off the freelist
lock.lock();
if (!_root)
{
oldRoot = _root; // atomic load
if (!oldRoot) return allocateFresh(bytes);
next = oldRoot.next; // atomic load
lock.unlock();
return allocateFresh(bytes);
}
else
{
auto oldRoot = _root;
_root = _root.next;
decNodes();
lock.unlock();
return (cast(ubyte*) oldRoot)[0 .. bytes];
}
while (!cas(&_root, oldRoot, next));
// great, snatched the root
decNodes();
return (cast(ubyte*) oldRoot)[0 .. bytes];
}

private void[] allocateFresh(const size_t bytes) shared
Expand All @@ -984,14 +991,11 @@ struct SharedFreeList(ParentAllocator,
if (!nodesFull && freeListEligible(b.length))
{
auto newRoot = cast(shared Node*) b.ptr;
shared Node* oldRoot;
do
{
oldRoot = _root;
newRoot.next = oldRoot;
}
while (!cas(&_root, oldRoot, newRoot));
lock.lock();
newRoot.next = _root;
_root = newRoot;
incNodes();
lock.unlock();
return true;
}
static if (hasMember!(ParentAllocator, "deallocate"))
Expand All @@ -1004,6 +1008,8 @@ struct SharedFreeList(ParentAllocator,
bool deallocateAll() shared
{
bool result = false;
lock.lock();
scope(exit) lock.unlock();
static if (hasMember!(ParentAllocator, "deallocateAll"))
{
result = parent.deallocateAll();
Expand Down

0 comments on commit 5caa66e

Please sign in to comment.