fixes #3279
This commit is contained in:
parent
479373ad79
commit
646a569421
2 changed files with 30 additions and 20 deletions
|
|
@ -415,16 +415,6 @@ struct TFrame {
|
||||||
|
|
||||||
#define NIM_POSIX_INIT __attribute__((constructor))
|
#define NIM_POSIX_INIT __attribute__((constructor))
|
||||||
|
|
||||||
#if defined(_MSCVER) && defined(__i386__)
|
|
||||||
__declspec(naked) int __fastcall NimXadd(volatile int* pNum, int val) {
|
|
||||||
__asm {
|
|
||||||
lock xadd dword ptr [ECX], EDX
|
|
||||||
mov EAX, EDX
|
|
||||||
ret
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
# define likely(x) __builtin_expect(x, 1)
|
# define likely(x) __builtin_expect(x, 1)
|
||||||
# define unlikely(x) __builtin_expect(x, 0)
|
# define unlikely(x) __builtin_expect(x, 0)
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ const someGcc = defined(gcc) or defined(llvm_gcc) or defined(clang)
|
||||||
|
|
||||||
when someGcc and hasThreadSupport:
|
when someGcc and hasThreadSupport:
|
||||||
type AtomMemModel* = distinct cint
|
type AtomMemModel* = distinct cint
|
||||||
|
|
||||||
var ATOMIC_RELAXED* {.importc: "__ATOMIC_RELAXED", nodecl.}: AtomMemModel
|
var ATOMIC_RELAXED* {.importc: "__ATOMIC_RELAXED", nodecl.}: AtomMemModel
|
||||||
## No barriers or synchronization.
|
## No barriers or synchronization.
|
||||||
var ATOMIC_CONSUME* {.importc: "__ATOMIC_CONSUME", nodecl.}: AtomMemModel
|
var ATOMIC_CONSUME* {.importc: "__ATOMIC_CONSUME", nodecl.}: AtomMemModel
|
||||||
|
|
@ -165,7 +166,8 @@ when someGcc and hasThreadSupport:
|
||||||
template fence*() = atomicThreadFence(ATOMIC_SEQ_CST)
|
template fence*() = atomicThreadFence(ATOMIC_SEQ_CST)
|
||||||
elif defined(vcc) and hasThreadSupport:
|
elif defined(vcc) and hasThreadSupport:
|
||||||
proc addAndFetch*(p: ptr int, val: int): int {.
|
proc addAndFetch*(p: ptr int, val: int): int {.
|
||||||
importc: "NimXadd", nodecl.}
|
importc: "_InterlockedExchangeAdd", header: "<intrin.h>".}
|
||||||
|
|
||||||
proc fence*() {.importc: "_ReadWriteBarrier", header: "<intrin.h>".}
|
proc fence*() {.importc: "_ReadWriteBarrier", header: "<intrin.h>".}
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
@ -176,6 +178,8 @@ else:
|
||||||
proc atomicInc*(memLoc: var int, x: int = 1): int =
|
proc atomicInc*(memLoc: var int, x: int = 1): int =
|
||||||
when someGcc and hasThreadSupport:
|
when someGcc and hasThreadSupport:
|
||||||
result = atomic_add_fetch(memLoc.addr, x, ATOMIC_RELAXED)
|
result = atomic_add_fetch(memLoc.addr, x, ATOMIC_RELAXED)
|
||||||
|
elif defined(vcc) and hasThreadSupport:
|
||||||
|
result = addAndFetch(memLoc.addr, x)
|
||||||
else:
|
else:
|
||||||
inc(memLoc, x)
|
inc(memLoc, x)
|
||||||
result = memLoc
|
result = memLoc
|
||||||
|
|
@ -186,17 +190,33 @@ proc atomicDec*(memLoc: var int, x: int = 1): int =
|
||||||
result = atomic_sub_fetch(memLoc.addr, x, ATOMIC_RELAXED)
|
result = atomic_sub_fetch(memLoc.addr, x, ATOMIC_RELAXED)
|
||||||
else:
|
else:
|
||||||
result = atomic_add_fetch(memLoc.addr, -x, ATOMIC_RELAXED)
|
result = atomic_add_fetch(memLoc.addr, -x, ATOMIC_RELAXED)
|
||||||
|
elif defined(vcc) and hasThreadSupport:
|
||||||
|
result = addAndFetch(memLoc.addr, -x)
|
||||||
else:
|
else:
|
||||||
dec(memLoc, x)
|
dec(memLoc, x)
|
||||||
result = memLoc
|
result = memLoc
|
||||||
|
|
||||||
when defined(windows) and not someGcc:
|
when defined(vcc):
|
||||||
proc interlockedCompareExchange(p: pointer; exchange, comparand: int): int
|
proc interlockedCompareExchange64(p: pointer; exchange, comparand: int64): int64
|
||||||
{.importc: "InterlockedCompareExchange", header: "<windows.h>", cdecl.}
|
{.importc: "_InterlockedCompareExchange64", header: "<intrin.h>".}
|
||||||
|
proc interlockedCompareExchange32(p: pointer; exchange, comparand: int32): int32
|
||||||
|
{.importc: "_InterlockedCompareExchange", header: "<intrin.h>".}
|
||||||
|
proc interlockedCompareExchange8(p: pointer; exchange, comparand: byte): byte
|
||||||
|
{.importc: "_InterlockedCompareExchange64", header: "<intrin.h>".}
|
||||||
|
|
||||||
proc cas*[T: bool|int|ptr](p: ptr T; oldValue, newValue: T): bool =
|
proc cas*[T: bool|int|ptr](p: ptr T; oldValue, newValue: T): bool =
|
||||||
interlockedCompareExchange(p, cast[int](newValue), cast[int](oldValue)) != 0
|
when sizeof(T) == 8:
|
||||||
# XXX fix for 64 bit build
|
interlockedCompareExchange64(p, cast[int64](newValue), cast[int64](oldValue)) ==
|
||||||
|
cast[int64](oldValue)
|
||||||
|
elif sizeof(T) == 4:
|
||||||
|
interlockedCompareExchange32(p, cast[int32](newValue), cast[int32](oldValue)) ==
|
||||||
|
cast[int32](oldValue)
|
||||||
|
elif sizeof(T) == 1:
|
||||||
|
interlockedCompareExchange8(p, cast[byte](newValue), cast[byte](oldValue)) ==
|
||||||
|
cast[byte](oldValue)
|
||||||
|
else:
|
||||||
|
{.error: "invalid CAS instruction".}
|
||||||
|
|
||||||
elif defined(tcc) and not defined(windows):
|
elif defined(tcc) and not defined(windows):
|
||||||
when defined(amd64):
|
when defined(amd64):
|
||||||
{.emit:"""
|
{.emit:"""
|
||||||
|
|
@ -237,7 +257,7 @@ static int __tcc_cas(int *ptr, int oldVal, int newVal)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
""".}
|
""".}
|
||||||
|
|
||||||
proc tcc_cas(p: ptr int; oldValue, newValue: int): bool
|
proc tcc_cas(p: ptr int; oldValue, newValue: int): bool
|
||||||
{.importc: "__tcc_cas", nodecl.}
|
{.importc: "__tcc_cas", nodecl.}
|
||||||
proc cas*[T: bool|int|ptr](p: ptr T; oldValue, newValue: T): bool =
|
proc cas*[T: bool|int|ptr](p: ptr T; oldValue, newValue: T): bool =
|
||||||
|
|
@ -249,14 +269,14 @@ else:
|
||||||
# XXX is this valid for 'int'?
|
# XXX is this valid for 'int'?
|
||||||
|
|
||||||
|
|
||||||
when (defined(x86) or defined(amd64)) and someGcc:
|
when (defined(x86) or defined(amd64)) and defined(vcc):
|
||||||
|
proc cpuRelax* {.importc: "YieldProcessor", header: "<windows.h>".}
|
||||||
|
elif (defined(x86) or defined(amd64)) and someGcc:
|
||||||
proc cpuRelax* {.inline.} =
|
proc cpuRelax* {.inline.} =
|
||||||
{.emit: """asm volatile("pause" ::: "memory");""".}
|
{.emit: """asm volatile("pause" ::: "memory");""".}
|
||||||
elif someGcc or defined(tcc):
|
elif someGcc or defined(tcc):
|
||||||
proc cpuRelax* {.inline.} =
|
proc cpuRelax* {.inline.} =
|
||||||
{.emit: """asm volatile("" ::: "memory");""".}
|
{.emit: """asm volatile("" ::: "memory");""".}
|
||||||
elif (defined(x86) or defined(amd64)) and defined(vcc):
|
|
||||||
proc cpuRelax* {.importc: "YieldProcessor", header: "<windows.h>".}
|
|
||||||
elif defined(icl):
|
elif defined(icl):
|
||||||
proc cpuRelax* {.importc: "_mm_pause", header: "xmmintrin.h".}
|
proc cpuRelax* {.importc: "_mm_pause", header: "xmmintrin.h".}
|
||||||
elif false:
|
elif false:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue