Add cpuRelax assembler for other platforms
This commit is contained in:
parent
08c0ba379a
commit
ddeefe85d2
1 changed files with 57 additions and 54 deletions
|
|
@ -21,19 +21,19 @@ when someGcc and hasThreadSupport:
|
||||||
## synchronization with another thread.
|
## synchronization with another thread.
|
||||||
var ATOMIC_ACQUIRE* {.importc: "__ATOMIC_ACQUIRE", nodecl.}: AtomMemModel
|
var ATOMIC_ACQUIRE* {.importc: "__ATOMIC_ACQUIRE", nodecl.}: AtomMemModel
|
||||||
## Barrier to hoisting of code and synchronizes with
|
## Barrier to hoisting of code and synchronizes with
|
||||||
## release (or stronger)
|
## release (or stronger)
|
||||||
## semantic stores from another thread.
|
## semantic stores from another thread.
|
||||||
var ATOMIC_RELEASE* {.importc: "__ATOMIC_RELEASE", nodecl.}: AtomMemModel
|
var ATOMIC_RELEASE* {.importc: "__ATOMIC_RELEASE", nodecl.}: AtomMemModel
|
||||||
## Barrier to sinking of code and synchronizes with
|
## Barrier to sinking of code and synchronizes with
|
||||||
## acquire (or stronger)
|
## acquire (or stronger)
|
||||||
## semantic loads from another thread.
|
## semantic loads from another thread.
|
||||||
var ATOMIC_ACQ_REL* {.importc: "__ATOMIC_ACQ_REL", nodecl.}: AtomMemModel
|
var ATOMIC_ACQ_REL* {.importc: "__ATOMIC_ACQ_REL", nodecl.}: AtomMemModel
|
||||||
## Full barrier in both directions and synchronizes
|
## Full barrier in both directions and synchronizes
|
||||||
## with acquire loads
|
## with acquire loads
|
||||||
## and release stores in another thread.
|
## and release stores in another thread.
|
||||||
var ATOMIC_SEQ_CST* {.importc: "__ATOMIC_SEQ_CST", nodecl.}: AtomMemModel
|
var ATOMIC_SEQ_CST* {.importc: "__ATOMIC_SEQ_CST", nodecl.}: AtomMemModel
|
||||||
## Full barrier in both directions and synchronizes
|
## Full barrier in both directions and synchronizes
|
||||||
## with acquire loads
|
## with acquire loads
|
||||||
## and release stores in all threads.
|
## and release stores in all threads.
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
@ -46,11 +46,11 @@ when someGcc and hasThreadSupport:
|
||||||
## ATOMIC_RELAXED, ATOMIC_SEQ_CST, ATOMIC_ACQUIRE, ATOMIC_CONSUME.
|
## ATOMIC_RELAXED, ATOMIC_SEQ_CST, ATOMIC_ACQUIRE, ATOMIC_CONSUME.
|
||||||
|
|
||||||
proc atomicLoad*[T: TAtomType](p, ret: ptr T, mem: AtomMemModel) {.
|
proc atomicLoad*[T: TAtomType](p, ret: ptr T, mem: AtomMemModel) {.
|
||||||
importc: "__atomic_load", nodecl.}
|
importc: "__atomic_load", nodecl.}
|
||||||
## This is the generic version of an atomic load. It returns the contents at p in ret.
|
## This is the generic version of an atomic load. It returns the contents at p in ret.
|
||||||
|
|
||||||
proc atomicStoreN*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel) {.
|
proc atomicStoreN*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel) {.
|
||||||
importc: "__atomic_store_n", nodecl.}
|
importc: "__atomic_store_n", nodecl.}
|
||||||
## This proc implements an atomic store operation. It writes val at p.
|
## This proc implements an atomic store operation. It writes val at p.
|
||||||
## ATOMIC_RELAXED, ATOMIC_SEQ_CST, and ATOMIC_RELEASE.
|
## ATOMIC_RELAXED, ATOMIC_SEQ_CST, and ATOMIC_RELEASE.
|
||||||
|
|
||||||
|
|
@ -60,39 +60,39 @@ when someGcc and hasThreadSupport:
|
||||||
|
|
||||||
proc atomicExchangeN*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
proc atomicExchangeN*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
||||||
importc: "__atomic_exchange_n", nodecl.}
|
importc: "__atomic_exchange_n", nodecl.}
|
||||||
## This proc implements an atomic exchange operation. It writes val at p,
|
## This proc implements an atomic exchange operation. It writes val at p,
|
||||||
## and returns the previous contents at p.
|
## and returns the previous contents at p.
|
||||||
## ATOMIC_RELAXED, ATOMIC_SEQ_CST, ATOMIC_ACQUIRE, ATOMIC_RELEASE, ATOMIC_ACQ_REL
|
## ATOMIC_RELAXED, ATOMIC_SEQ_CST, ATOMIC_ACQUIRE, ATOMIC_RELEASE, ATOMIC_ACQ_REL
|
||||||
|
|
||||||
proc atomicExchange*[T: TAtomType](p, val, ret: ptr T, mem: AtomMemModel) {.
|
proc atomicExchange*[T: TAtomType](p, val, ret: ptr T, mem: AtomMemModel) {.
|
||||||
importc: "__atomic_exchange", nodecl.}
|
importc: "__atomic_exchange", nodecl.}
|
||||||
## This is the generic version of an atomic exchange. It stores the contents at val at p.
|
## This is the generic version of an atomic exchange. It stores the contents at val at p.
|
||||||
## The original value at p is copied into ret.
|
## The original value at p is copied into ret.
|
||||||
|
|
||||||
proc atomicCompareExchangeN*[T: TAtomType](p, expected: ptr T, desired: T,
|
proc atomicCompareExchangeN*[T: TAtomType](p, expected: ptr T, desired: T,
|
||||||
weak: bool, success_memmodel: AtomMemModel, failure_memmodel: AtomMemModel): bool {.
|
weak: bool, success_memmodel: AtomMemModel, failure_memmodel: AtomMemModel): bool {.
|
||||||
importc: "__atomic_compare_exchange_n ", nodecl.}
|
importc: "__atomic_compare_exchange_n ", nodecl.}
|
||||||
## This proc implements an atomic compare and exchange operation. This compares the
|
## This proc implements an atomic compare and exchange operation. This compares the
|
||||||
## contents at p with the contents at expected and if equal, writes desired at p.
|
## contents at p with the contents at expected and if equal, writes desired at p.
|
||||||
## If they are not equal, the current contents at p is written into expected.
|
## If they are not equal, the current contents at p is written into expected.
|
||||||
## Weak is true for weak compare_exchange, and false for the strong variation.
|
## Weak is true for weak compare_exchange, and false for the strong variation.
|
||||||
## Many targets only offer the strong variation and ignore the parameter.
|
## Many targets only offer the strong variation and ignore the parameter.
|
||||||
## When in doubt, use the strong variation.
|
## When in doubt, use the strong variation.
|
||||||
## True is returned if desired is written at p and the execution is considered
|
## True is returned if desired is written at p and the execution is considered
|
||||||
## to conform to the memory model specified by success_memmodel. There are no
|
## to conform to the memory model specified by success_memmodel. There are no
|
||||||
## restrictions on what memory model can be used here. False is returned otherwise,
|
## restrictions on what memory model can be used here. False is returned otherwise,
|
||||||
## and the execution is considered to conform to failure_memmodel. This memory model
|
## and the execution is considered to conform to failure_memmodel. This memory model
|
||||||
## cannot be __ATOMIC_RELEASE nor __ATOMIC_ACQ_REL. It also cannot be a stronger model
|
## cannot be __ATOMIC_RELEASE nor __ATOMIC_ACQ_REL. It also cannot be a stronger model
|
||||||
## than that specified by success_memmodel.
|
## than that specified by success_memmodel.
|
||||||
|
|
||||||
proc atomicCompareExchange*[T: TAtomType](p, expected, desired: ptr T,
|
proc atomicCompareExchange*[T: TAtomType](p, expected, desired: ptr T,
|
||||||
weak: bool, success_memmodel: AtomMemModel, failure_memmodel: AtomMemModel): bool {.
|
weak: bool, success_memmodel: AtomMemModel, failure_memmodel: AtomMemModel): bool {.
|
||||||
importc: "__atomic_compare_exchange_n ", nodecl.}
|
importc: "__atomic_compare_exchange_n ", nodecl.}
|
||||||
## This proc implements the generic version of atomic_compare_exchange.
|
## This proc implements the generic version of atomic_compare_exchange.
|
||||||
## The proc is virtually identical to atomic_compare_exchange_n, except the desired
|
## The proc is virtually identical to atomic_compare_exchange_n, except the desired
|
||||||
## value is also a pointer.
|
## value is also a pointer.
|
||||||
|
|
||||||
## Perform the operation return the new value, all memory models are valid
|
## Perform the operation return the new value, all memory models are valid
|
||||||
proc atomicAddFetch*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
proc atomicAddFetch*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
||||||
importc: "__atomic_add_fetch", nodecl.}
|
importc: "__atomic_add_fetch", nodecl.}
|
||||||
proc atomicSubFetch*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
proc atomicSubFetch*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
||||||
|
|
@ -101,64 +101,64 @@ when someGcc and hasThreadSupport:
|
||||||
importc: "__atomic_or_fetch ", nodecl.}
|
importc: "__atomic_or_fetch ", nodecl.}
|
||||||
proc atomicAndFetch*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
proc atomicAndFetch*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
||||||
importc: "__atomic_and_fetch", nodecl.}
|
importc: "__atomic_and_fetch", nodecl.}
|
||||||
proc atomicXorFetch*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
proc atomicXorFetch*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
||||||
importc: "__atomic_xor_fetch", nodecl.}
|
importc: "__atomic_xor_fetch", nodecl.}
|
||||||
proc atomicNandFetch*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
proc atomicNandFetch*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
||||||
importc: "__atomic_nand_fetch ", nodecl.}
|
importc: "__atomic_nand_fetch ", nodecl.}
|
||||||
|
|
||||||
## Perform the operation return the old value, all memory models are valid
|
## Perform the operation return the old value, all memory models are valid
|
||||||
proc atomicFetchAdd*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
proc atomicFetchAdd*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
||||||
importc: "__atomic_fetch_add", nodecl.}
|
importc: "__atomic_fetch_add", nodecl.}
|
||||||
proc atomicFetchSub*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
proc atomicFetchSub*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
||||||
importc: "__atomic_fetch_sub", nodecl.}
|
importc: "__atomic_fetch_sub", nodecl.}
|
||||||
proc atomicFetchOr*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
proc atomicFetchOr*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
||||||
importc: "__atomic_fetch_or", nodecl.}
|
importc: "__atomic_fetch_or", nodecl.}
|
||||||
proc atomicFetchAnd*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
proc atomicFetchAnd*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
||||||
importc: "__atomic_fetch_and", nodecl.}
|
importc: "__atomic_fetch_and", nodecl.}
|
||||||
proc atomicFetchXor*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
proc atomicFetchXor*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
||||||
importc: "__atomic_fetch_xor", nodecl.}
|
importc: "__atomic_fetch_xor", nodecl.}
|
||||||
proc atomicFetchNand*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
proc atomicFetchNand*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
||||||
importc: "__atomic_fetch_nand", nodecl.}
|
importc: "__atomic_fetch_nand", nodecl.}
|
||||||
|
|
||||||
proc atomicTestAndSet*(p: pointer, mem: AtomMemModel): bool {.
|
proc atomicTestAndSet*(p: pointer, mem: AtomMemModel): bool {.
|
||||||
importc: "__atomic_test_and_set", nodecl.}
|
importc: "__atomic_test_and_set", nodecl.}
|
||||||
## This built-in function performs an atomic test-and-set operation on the byte at p.
|
## This built-in function performs an atomic test-and-set operation on the byte at p.
|
||||||
## The byte is set to some implementation defined nonzero “set” value and the return
|
## The byte is set to some implementation defined nonzero “set” value and the return
|
||||||
## value is true if and only if the previous contents were “set”.
|
## value is true if and only if the previous contents were “set”.
|
||||||
## All memory models are valid.
|
## All memory models are valid.
|
||||||
|
|
||||||
proc atomicClear*(p: pointer, mem: AtomMemModel) {.
|
proc atomicClear*(p: pointer, mem: AtomMemModel) {.
|
||||||
importc: "__atomic_clear", nodecl.}
|
importc: "__atomic_clear", nodecl.}
|
||||||
## This built-in function performs an atomic clear operation at p.
|
## This built-in function performs an atomic clear operation at p.
|
||||||
## After the operation, at p contains 0.
|
## After the operation, at p contains 0.
|
||||||
## ATOMIC_RELAXED, ATOMIC_SEQ_CST, ATOMIC_RELEASE
|
## ATOMIC_RELAXED, ATOMIC_SEQ_CST, ATOMIC_RELEASE
|
||||||
|
|
||||||
proc atomicThreadFence*(mem: AtomMemModel) {.
|
proc atomicThreadFence*(mem: AtomMemModel) {.
|
||||||
importc: "__atomic_thread_fence", nodecl.}
|
importc: "__atomic_thread_fence", nodecl.}
|
||||||
## This built-in function acts as a synchronization fence between threads based
|
## This built-in function acts as a synchronization fence between threads based
|
||||||
## on the specified memory model. All memory orders are valid.
|
## on the specified memory model. All memory orders are valid.
|
||||||
|
|
||||||
proc atomicSignalFence*(mem: AtomMemModel) {.
|
proc atomicSignalFence*(mem: AtomMemModel) {.
|
||||||
importc: "__atomic_signal_fence", nodecl.}
|
importc: "__atomic_signal_fence", nodecl.}
|
||||||
## This built-in function acts as a synchronization fence between a thread and
|
## This built-in function acts as a synchronization fence between a thread and
|
||||||
## signal handlers based in the same thread. All memory orders are valid.
|
## signal handlers based in the same thread. All memory orders are valid.
|
||||||
|
|
||||||
proc atomicAlwaysLockFree*(size: int, p: pointer): bool {.
|
proc atomicAlwaysLockFree*(size: int, p: pointer): bool {.
|
||||||
importc: "__atomic_always_lock_free", nodecl.}
|
importc: "__atomic_always_lock_free", nodecl.}
|
||||||
## This built-in function returns true if objects of size bytes always generate
|
## This built-in function returns true if objects of size bytes always generate
|
||||||
## lock free atomic instructions for the target architecture. size must resolve
|
## lock free atomic instructions for the target architecture. size must resolve
|
||||||
## to a compile-time constant and the result also resolves to a compile-time constant.
|
## to a compile-time constant and the result also resolves to a compile-time constant.
|
||||||
## ptr is an optional pointer to the object that may be used to determine alignment.
|
## ptr is an optional pointer to the object that may be used to determine alignment.
|
||||||
## A value of 0 indicates typical alignment should be used. The compiler may also
|
## A value of 0 indicates typical alignment should be used. The compiler may also
|
||||||
## ignore this parameter.
|
## ignore this parameter.
|
||||||
|
|
||||||
proc atomicIsLockFree*(size: int, p: pointer): bool {.
|
proc atomicIsLockFree*(size: int, p: pointer): bool {.
|
||||||
importc: "__atomic_is_lock_free", nodecl.}
|
importc: "__atomic_is_lock_free", nodecl.}
|
||||||
## This built-in function returns true if objects of size bytes always generate
|
## This built-in function returns true if objects of size bytes always generate
|
||||||
## lock free atomic instructions for the target architecture. If it is not known
|
## lock free atomic instructions for the target architecture. If it is not known
|
||||||
## to be lock free a call is made to a runtime routine named __atomic_is_lock_free.
|
## to be lock free a call is made to a runtime routine named __atomic_is_lock_free.
|
||||||
## ptr is an optional pointer to the object that may be used to determine alignment.
|
## ptr is an optional pointer to the object that may be used to determine alignment.
|
||||||
## A value of 0 indicates typical alignment should be used. The compiler may also
|
## A value of 0 indicates typical alignment should be used. The compiler may also
|
||||||
## ignore this parameter.
|
## ignore this parameter.
|
||||||
|
|
||||||
template fence*() = atomicThreadFence(ATOMIC_SEQ_CST)
|
template fence*() = atomicThreadFence(ATOMIC_SEQ_CST)
|
||||||
|
|
@ -178,7 +178,7 @@ proc atomicInc*(memLoc: var int, x: int = 1): int =
|
||||||
else:
|
else:
|
||||||
inc(memLoc, x)
|
inc(memLoc, x)
|
||||||
result = memLoc
|
result = memLoc
|
||||||
|
|
||||||
proc atomicDec*(memLoc: var int, x: int = 1): int =
|
proc atomicDec*(memLoc: var int, x: int = 1): int =
|
||||||
when someGcc and hasThreadSupport:
|
when someGcc and hasThreadSupport:
|
||||||
when declared(atomic_sub_fetch):
|
when declared(atomic_sub_fetch):
|
||||||
|
|
@ -206,6 +206,9 @@ else:
|
||||||
when (defined(x86) or defined(amd64)) and someGcc:
|
when (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:
|
||||||
|
proc cpuRelax* {.inline.} =
|
||||||
|
{.emit: """asm volatile("" ::: "memory");""".}
|
||||||
elif (defined(x86) or defined(amd64)) and defined(vcc):
|
elif (defined(x86) or defined(amd64)) and defined(vcc):
|
||||||
proc cpuRelax* {.importc: "YieldProcessor", header: "<windows.h>".}
|
proc cpuRelax* {.importc: "YieldProcessor", header: "<windows.h>".}
|
||||||
elif defined(icl):
|
elif defined(icl):
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue