alloc uses atomic operations only when necessary (#20899)

This commit is contained in:
ringabout 2022-11-23 14:20:35 +08:00 • committed by GitHub
commit d3eb1383d1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -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)