summary refs log tree commit diff stats
path: root/lib/system/atomics.nim
diff options
context:
space:
mode:
authorReimer Behrends <behrends@gmail.com>2014-10-30 03:42:50 +0100
committerReimer Behrends <behrends@gmail.com>2014-10-30 03:42:50 +0100
commit6e3720155adec34f938974be1e7d5df07901bd2d (patch)
tree506dffd49ffc7dd127e7a6730dcbfd303d78f379 /lib/system/atomics.nim
parentd5b94390dcfe61c645b43305e3673b6c696b39c7 (diff)
downloadNim-6e3720155adec34f938974be1e7d5df07901bd2d.tar.gz
Various atomics fixes for gcc/clang.
Make atomicInc/atomicDec work with clang, too; also, actually import
the memory model constants from C rather than relying on the enum
matching the C constants by happenstance.
Diffstat (limited to 'lib/system/atomics.nim')
-rw-r--r--lib/system/atomics.nim48
1 files changed, 27 insertions, 21 deletions
diff --git a/lib/system/atomics.nim b/lib/system/atomics.nim
index 695a5f63e..3ef9d00ec 100644
--- a/lib/system/atomics.nim
+++ b/lib/system/atomics.nim
@@ -13,24 +13,30 @@
 const someGcc = defined(gcc) or defined(llvm_gcc) or defined(clang)
 
 when someGcc and hasThreadSupport:
-  type 
-    AtomMemModel* = enum
-      ATOMIC_RELAXED,  ## No barriers or synchronization. 
-      ATOMIC_CONSUME,  ## Data dependency only for both barrier and
-                       ## synchronization with another thread.
-      ATOMIC_ACQUIRE,  ## Barrier to hoisting of code and synchronizes with
-                       ## release (or stronger) 
-                       ## semantic stores from another thread.
-      ATOMIC_RELEASE,  ## Barrier to sinking of code and synchronizes with
-                       ## acquire (or stronger) 
-                       ## semantic loads from another thread. 
-      ATOMIC_ACQ_REL,  ## Full barrier in both directions and synchronizes
-                       ## with acquire loads 
-                       ## and release stores in another thread.
-      ATOMIC_SEQ_CST   ## Full barrier in both directions and synchronizes
-                       ## with acquire loads 
-                       ## and release stores in all threads.
-
+  type AtomMemModel* = distinct cint
+  var ATOMIC_RELAXED* {.importc: "__ATOMIC_RELAXED", nodecl.}: AtomMemModel
+    ## No barriers or synchronization.
+  var ATOMIC_CONSUME* {.importc: "__ATOMIC_CONSUME", nodecl.}: AtomMemModel
+    ## Data dependency only for both barrier and
+    ## synchronization with another thread.
+  var ATOMIC_ACQUIRE* {.importc: "__ATOMIC_ACQUIRE", nodecl.}: AtomMemModel
+    ## Barrier to hoisting of code and synchronizes with
+    ## release (or stronger) 
+    ## semantic stores from another thread.
+  var ATOMIC_RELEASE* {.importc: "__ATOMIC_RELEASE", nodecl.}: AtomMemModel
+    ## Barrier to sinking of code and synchronizes with
+    ## acquire (or stronger) 
+    ## semantic loads from another thread. 
+  var ATOMIC_ACQ_REL* {.importc: "__ATOMIC_ACQ_REL", nodecl.}: AtomMemModel
+    ## Full barrier in both directions and synchronizes
+    ## with acquire loads 
+    ## and release stores in another thread.
+  var ATOMIC_SEQ_CST* {.importc: "__ATOMIC_SEQ_CST", nodecl.}: AtomMemModel
+    ## Full barrier in both directions and synchronizes
+    ## with acquire loads 
+    ## and release stores in all threads.
+
+  type
     TAtomType* = TNumber|pointer|ptr|char
       ## Type Class representing valid types for use with atomic procs
 
@@ -166,14 +172,14 @@ else:
     result = p[]
 
 proc atomicInc*(memLoc: var int, x: int = 1): int =
-  when defined(gcc) and hasThreadSupport:
+  when someGcc and hasThreadSupport:
     result = atomic_add_fetch(memLoc.addr, x, ATOMIC_RELAXED)
   else:
     inc(memLoc, x)
     result = memLoc
   
 proc atomicDec*(memLoc: var int, x: int = 1): int =
-  when defined(gcc) and hasThreadSupport:
+  when someGcc and hasThreadSupport:
     when declared(atomic_sub_fetch):
       result = atomic_sub_fetch(memLoc.addr, x, ATOMIC_RELAXED)
     else:
@@ -196,7 +202,7 @@ else:
   # XXX is this valid for 'int'?
 
 
-when (defined(x86) or defined(amd64)) and (defined(gcc) or defined(llvm_gcc)):
+when (defined(x86) or defined(amd64)) and someGcc:
   proc cpuRelax {.inline.} =
     {.emit: """asm volatile("pause" ::: "memory");""".}
 elif (defined(x86) or defined(amd64)) and defined(vcc):