diff options
-rw-r--r-- | lib/nimbase.h | 10 | ||||
-rw-r--r-- | lib/system/atomics.nim | 40 |
2 files changed, 30 insertions, 20 deletions
diff --git a/lib/nimbase.h b/lib/nimbase.h index 37f8f5c3d..52de60969 100644 --- a/lib/nimbase.h +++ b/lib/nimbase.h @@ -415,16 +415,6 @@ struct TFrame { #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__ # define likely(x) __builtin_expect(x, 1) # define unlikely(x) __builtin_expect(x, 0) diff --git a/lib/system/atomics.nim b/lib/system/atomics.nim index a79dcb152..3a43729dc 100644 --- a/lib/system/atomics.nim +++ b/lib/system/atomics.nim @@ -14,6 +14,7 @@ const someGcc = defined(gcc) or defined(llvm_gcc) or defined(clang) when someGcc and hasThreadSupport: type AtomMemModel* = distinct cint + var ATOMIC_RELAXED* {.importc: "__ATOMIC_RELAXED", nodecl.}: AtomMemModel ## No barriers or synchronization. var ATOMIC_CONSUME* {.importc: "__ATOMIC_CONSUME", nodecl.}: AtomMemModel @@ -165,7 +166,8 @@ when someGcc and hasThreadSupport: template fence*() = atomicThreadFence(ATOMIC_SEQ_CST) elif defined(vcc) and hasThreadSupport: proc addAndFetch*(p: ptr int, val: int): int {. - importc: "NimXadd", nodecl.} + importc: "_InterlockedExchangeAdd", header: "<intrin.h>".} + proc fence*() {.importc: "_ReadWriteBarrier", header: "<intrin.h>".} else: @@ -176,6 +178,8 @@ else: proc atomicInc*(memLoc: var int, x: int = 1): int = when someGcc and hasThreadSupport: result = atomic_add_fetch(memLoc.addr, x, ATOMIC_RELAXED) + elif defined(vcc) and hasThreadSupport: + result = addAndFetch(memLoc.addr, x) else: inc(memLoc, x) result = memLoc @@ -186,17 +190,33 @@ proc atomicDec*(memLoc: var int, x: int = 1): int = result = atomic_sub_fetch(memLoc.addr, x, ATOMIC_RELAXED) else: result = atomic_add_fetch(memLoc.addr, -x, ATOMIC_RELAXED) + elif defined(vcc) and hasThreadSupport: + result = addAndFetch(memLoc.addr, -x) else: dec(memLoc, x) result = memLoc -when defined(windows) and not someGcc: - proc interlockedCompareExchange(p: pointer; exchange, comparand: int): int - {.importc: "InterlockedCompareExchange", header: "<windows.h>", cdecl.} +when defined(vcc): + proc interlockedCompareExchange64(p: pointer; exchange, comparand: int64): int64 + {.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 = - interlockedCompareExchange(p, cast[int](newValue), cast[int](oldValue)) != 0 - # XXX fix for 64 bit build + when sizeof(T) == 8: + 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): when defined(amd64): {.emit:""" @@ -237,7 +257,7 @@ static int __tcc_cas(int *ptr, int oldVal, int newVal) return 1; } """.} - + proc tcc_cas(p: ptr int; oldValue, newValue: int): bool {.importc: "__tcc_cas", nodecl.} proc cas*[T: bool|int|ptr](p: ptr T; oldValue, newValue: T): bool = @@ -249,14 +269,14 @@ else: # 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.} = {.emit: """asm volatile("pause" ::: "memory");""".} elif someGcc or defined(tcc): proc cpuRelax* {.inline.} = {.emit: """asm volatile("" ::: "memory");""".} -elif (defined(x86) or defined(amd64)) and defined(vcc): - proc cpuRelax* {.importc: "YieldProcessor", header: "<windows.h>".} elif defined(icl): proc cpuRelax* {.importc: "_mm_pause", header: "xmmintrin.h".} elif false: |