From d3eb1383d12d6dc20774b082b4085990bbc518dc Mon Sep 17 00:00:00 2001 From: ringabout <43030857+ringabout@users.noreply.github.com> Date: Wed, 23 Nov 2022 14:20:35 +0800 Subject: [PATCH] alloc uses atomic operations only when necessary (#20899) --- lib/system/alloc.nim | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/lib/system/alloc.nim b/lib/system/alloc.nim index 69bab5a85e..04cbb9e3e1 100644 --- a/lib/system/alloc.nim +++ b/lib/system/alloc.nim @@ -759,10 +759,14 @@ proc deallocBigChunk(a: var MemRegion, c: PBigChunk) = when defined(gcDestructors): template atomicPrepend(head, elem: untyped) = # see also https://en.cppreference.com/w/cpp/atomic/atomic_compare_exchange - while true: + when hasThreadSupport: + while true: + elem.next.storea head.loada + if atomicCompareExchangeN(addr head, addr elem.next, elem, weak = true, ATOMIC_RELEASE, ATOMIC_RELAXED): + break + else: elem.next.storea head.loada - if atomicCompareExchangeN(addr head, addr elem.next, elem, weak = true, ATOMIC_RELEASE, ATOMIC_RELAXED): - break + head.storea elem proc addToSharedFreeListBigChunks(a: var MemRegion; c: PBigChunk) {.inline.} = sysAssert c.next == nil, "c.next pointer must be nil" @@ -842,7 +846,11 @@ proc rawAlloc(a: var MemRegion, requestedSize: int): pointer = sysAssert c.size == size, "rawAlloc 6" when defined(gcDestructors): if c.freeList == nil: - c.freeList = atomicExchangeN(addr c.sharedFreeList, nil, ATOMIC_RELAXED) + when hasThreadSupport: + c.freeList = atomicExchangeN(addr c.sharedFreeList, nil, ATOMIC_RELAXED) + else: + c.freeList = c.sharedFreeList + c.sharedFreeList = nil compensateCounters(a, c, size) if c.freeList == nil: sysAssert(c.acc + smallChunkOverhead() + size <= SmallChunkSize, @@ -869,7 +877,11 @@ proc rawAlloc(a: var MemRegion, requestedSize: int): pointer = trackSize(c.size) else: when defined(gcDestructors): - let deferredFrees = atomicExchangeN(addr a.sharedFreeListBigChunks, nil, ATOMIC_RELAXED) + when hasThreadSupport: + let deferredFrees = atomicExchangeN(addr a.sharedFreeListBigChunks, nil, ATOMIC_RELAXED) + else: + let deferredFrees = a.sharedFreeListBigChunks + a.sharedFreeListBigChunks = nil if deferredFrees != nil: freeDeferredObjects(a, deferredFrees)