summary refs log tree commit diff stats
path: root/lib/system
diff options
context:
space:
mode:
Diffstat (limited to 'lib/system')
-rw-r--r--lib/system/atomics.nim38
1 files changed, 32 insertions, 6 deletions
diff --git a/lib/system/atomics.nim b/lib/system/atomics.nim
index f4d3a873f..c0612c9a5 100644
--- a/lib/system/atomics.nim
+++ b/lib/system/atomics.nim
@@ -12,6 +12,10 @@
 
 const someGcc = defined(gcc) or defined(llvm_gcc) or defined(clang)
 
+type
+  AtomType* = SomeNumber|pointer|ptr|char|bool
+    ## Type Class representing valid types for use with atomic procs
+
 when someGcc and hasThreadSupport:
   type AtomMemModel* = distinct cint
 
@@ -37,10 +41,6 @@ when someGcc and hasThreadSupport:
     ## with acquire loads
     ## and release stores in all threads.
 
-  type
-    AtomType* = SomeNumber|pointer|ptr|char|bool
-      ## Type Class representing valid types for use with atomic procs
-
   proc atomicLoadN*[T: AtomType](p: ptr T, mem: AtomMemModel): T {.
     importc: "__atomic_load_n", nodecl.}
     ## This proc implements an atomic load operation. It returns the contents at p.
@@ -164,6 +164,34 @@ when someGcc and hasThreadSupport:
 
   template fence*() = atomicThreadFence(ATOMIC_SEQ_CST)
 elif defined(vcc) and hasThreadSupport:
+  type AtomMemModel* = distinct cint
+
+  const
+    ATOMIC_RELAXED = 0.AtomMemModel
+    ATOMIC_CONSUME = 1.AtomMemModel
+    ATOMIC_ACQUIRE = 2.AtomMemModel
+    ATOMIC_RELEASE = 3.AtomMemModel
+    ATOMIC_ACQ_REL = 4.AtomMemModel
+    ATOMIC_SEQ_CST = 5.AtomMemModel
+
+  proc `==`(x1, x2: AtomMemModel): bool {.borrow.}
+
+  proc readBarrier() {.importc: "_ReadBarrier",  header: "<intrin.h>".}
+  proc writeBarrier() {.importc: "_WriteBarrier",  header: "<intrin.h>".}
+  proc fence*() {.importc: "_ReadWriteBarrier", header: "<intrin.h>".}
+
+  template barrier(mem: AtomMemModel) =
+    when mem == ATOMIC_RELAXED: discard
+    elif mem == ATOMIC_CONSUME: readBarrier()
+    elif mem == ATOMIC_ACQUIRE: writeBarrier()
+    elif mem == ATOMIC_RELEASE: fence()
+    elif mem == ATOMIC_ACQ_REL: fence()
+    elif mem == ATOMIC_SEQ_CST: fence()
+
+  proc atomicLoadN*[T: AtomType](p: ptr T, mem: static[AtomMemModel]): T =
+    result = p[]
+    barrier(mem)
+
   when defined(cpp):
     when sizeof(int) == 8:
       proc addAndFetch*(p: ptr int, val: int): int {.
@@ -181,8 +209,6 @@ elif defined(vcc) and hasThreadSupport:
       proc addAndFetch*(p: ptr int, val: int): int {.
         importc: "_InterlockedExchangeAdd", header: "<intrin.h>".}
 
-  proc fence*() {.importc: "_ReadWriteBarrier", header: "<intrin.h>".}
-
 else:
   proc addAndFetch*(p: ptr int, val: int): int {.inline.} =
     inc(p[], val)